• Delphi 常用数据类型 字符串类型 数据类型等等


    字符串类型

    Delphi有三种类型的字符:

    ●AnsiChar这是标准的1字节的ANSI字符,程序员都对它比较熟悉。

    ●WideChar这是2字节的Unicode字符。

    ●Char在目前Delphi早前的版本相当于AnsiChar,但在Delphi以后版本中相当于WideChar.

    var

    c: Char; {Char 类型的取值范围是: #0..#255, 用十六进制表示是: #$0..#$FF}

    begin

    {用十进制方式赋值:}

    c := #65;

    ShowMessage(c); {A}

    {用十六进制方式赋值:}

    c := #$41;

    ShowMessage(c); {A}

    {用 Chr 函数代替 # 符号}

    c := Chr(65);

    ShowMessage(c); {A}

    c := Chr($41);

    ShowMessage(c); {A}

    {Char 长度当然会是 1}

    ShowMessage(IntToStr(Length(c))); {1}

    {Char、AnsiChar 允许这样方便地赋值(也就是和 1 字节长度的字符串是兼容的):}

    c := 'B';

    ShowMessage(c); {B}

    end;

    //UniCode 字符 WideChar; 和 AnsiChar 不同, WideChar 是占 2 字节大小.

    var

    c: WideChar; {WideChar 的取值范围是: #0..#65535, 用十六进制表示是: #$0..#$FFFF}

    begin

    {WideChar 兼容了 AnsiChar 的 #0..#255; 但占用了 2 字节大小}

    c := #65;

    ShowMessage(c); {A}

    ShowMessage(IntToStr(Length(c))); {1; 这是字符长度}

    ShowMessage(IntToStr(SizeOf(c))); {2; 但占用 2 个字节}

    {用十六进制赋值}

    c := #$4E07;

    ShowMessage(c); {万}

    ShowMessage(IntToStr(Length(c))); {1; 这是字符长度}

    ShowMessage(IntToStr(SizeOf(c))); {2; 但占用 2 个字节}

    {如果不超出 #255 的范围是可以直接赋值的}

    c := 'B';

    ShowMessage(c); {万}

    end;

    记住因为一个字符在长度上并不表示一个字节,所以不能在应用程序中对字符长度进行硬编码,而应该使用Sizeof()函数。注意Sizeof()标准函数返回类型或实例的字节长度。

    字符串是代表一组字符的变量类型,Delphi有下列几种不同的字符串类型来满足程序的要求:

    ●AnsiString这是Pascal缺省的字符串类型(string),它由AnsiChar字符组成,其长度没有限制,同时与null结束的字符串相兼容。

    ●ShortString保留该类型是为了向后兼容Delphi1.0,它的长度限制在255个字符内。

    ●WideString功能上类似于AnsiString,但它是由WideChar字符组成的。

    ●PChar指向null结束的Char字符串的指针,类似于C的char*或lpstr类型。

    ●PAnsiChar指向null结束的AnsiChar字符串的指针。

    ●PWideChar指向null结束的WideChar字符串的指针。

    1.AnsiString类型

    AnsiString(或长字符串)类型是在Delphi2.0开始引入的,因为Delphi1.0的用户特别需要一个容易使用而且没有255个字符限制的字符串类型,而AnsiString正好能满足这些要求。

    虽然AnsiString在外表上跟以前的字符串类型几乎相同,但它是动态分配的并有自动回收功能,正是因为这个功能AnsiString有时被称为生存期自管理类型。ObjectPascal能根据需要为字符串分配空间,所以不用像在C/C++中所担心的为中间结果分配缓冲区。实际上,AnsiString类型是一个指向在堆栈中的字符串结构的指针。

    AnsiString字符串类型有引用计数的功能,这表示几个字符串都能指向相同的物理地址。因此,复制字符串因为仅仅是复制了指针而不是复制实际的字符串而变得非常快。当两个或更多的AnsiString类型共享一个指向相同物理地址的引用时,Delphi内存管理使用了copy-on-write技术,一个字符串要等到修改结束,才释放一个引用并分配一个物理字符串。当我们声明一个AnsiString变量时,它是没有长度的,因此字符串没有为字符申请内存空间。为了申请字符串的内存空间,我们可以给它赋值为一行字符或者另一个字符串变量,也可以使用SetLength()函数。

    var

      str: string;

      s: string;

    begin

      str := 'delphi';

      s[1] := 'd';//错误,s此时还没有申请内存空间。

      s := 'delphi'; //或者s := str; 或者SetLength(s, 4);

    end;

    AnsiString字符串总是null结束的,这就使得调用Win32API函数或其他需要PChar型字符串的函数变得容易了。只要把一个字符类型强制转换为PChar类型。我们在调用时进行强制类型转换PChar(s),或者@s[1]。(s[1]是字符串s的第一个字符,@是取地址。s[0]存放的是字符串s的长度)。下面的代码演示了怎样调用Win32的GetWindowsDirectory()函数,这个函数需要一个PChar类型的参数:

    var

    S:String;

    begin

    SetLength(S,256);//重要!首先给字符串分配空间

    //调用API函数,S现在包含目录字符串

    GetWindowsDirectory(PChar(S),256);

    如果使用了将AnsiString字符串强制转换为PChar类型的函数和过程,在使用结束后,要手工把它的长度恢复为原来以null结束的长度。STRUTILS单元中的RealizeLenght()函数可以实现这一点:

    procedure RealizeLength(varS:string);

    begin

    SetLength(S,StrLen(PChar(S)));

    end;

    调用ReallizeLength():

    var

    S:string;

    begin

    SetLength(S,256);//重要!首先给字符串分配空间

    //调用函数,S现在包含目录字符串

    GetWindowDirectory(PChar(S),256);

    RealizeLength(S);//设置S的长度为null结束的长度

    end;

    2. ShortString类型

    ShortString类型跟以null结尾的字符串不兼容,正因为这样,用ShortString调用Win32函数时,要做一些工作。下面这个ShortStringAsPChar()函数是在STRUTILS.PAS单元中定义的。

    function ShortStringAsPChar(varS:ShortString): PChar;

    {这函数能使一个字符串以null结尾,这样就能传递给需要PChar类型参数的Win32API函数,如果字符串超过254个字符,多出的部分将被截掉}

    begin

    if Length(S)=High(S) then Dec(S[0]); {如果S太长,就截取一部分}

    S[Ord(Length(S))+1]:=#0;{把null加到字符串的最后}

    Result:=@S[1];{返回PChar化的字符串}

    end;

    Win32API函数需要以null结尾的字符串,不要把ShortString字符串传递给API函数,因为编译器将报错,长字符串可以传递给Win32API函数。

    3.WideString类型

    WideString类型像AnsiString一样是生存期自管理类型,它们都能动态分配、自动回收并且彼此能相互兼容,不过WideString和AnsiString的不同主要在三个方面:

    ●WideString由WideChar字符组成,而不是由AnsiChar字符组成的,它们跟Unicode字符串兼容。

    ●WideString用SysAllocStrLen()API函数进行分配,它们跟OLE的BSTR字符串相兼容。

    ●WideString没有引用计数,所以将一个WideString字符串赋值给另一个WideString字符串时,就需要从内存中的一个位置复制到另一个位置。这使得WideString在速度和内存的利用上不如AnsiString有效。

    就像上面所提到的,编译器自动在AnsiString类型和WideString类型的变量间进行转换。示例如下:

    var

    W:wideString;

    S:string;

    begin

    W:='Margaritaville';

    S:=W;//wideString转换成AnsiString

    S:='ComeMonday';

    W:=S;//AnsiString转换成WideString

    end;

    为了能灵活地运用WideString类型,ObjectPascal重载了Concat()、Copy、Insert()、Length()、Pos()和SetLength()等例程以及+、=和<>等运算符。就像AnsiString和ShortString类型一样,能用数组的下标来访问WideString中一个特定的字符。

    4.字符串指针

    Delphi有三种不同的以null结束的字符串类型:PChar、PAnsiChar和PWideChar。它们都是由Delphi的三种不同字符组成的。这三种类型在总体上跟PChar是一致的。PChar之所以保留是为了跟Delphi1.0和Win32API兼容,而它们需要使用以null结束的字符串,PChar被定义成一个指向以null(零)结束的字符串指针与AnsiString和WideString类型不同,PChar的内存不是由ObjectPascal自动产生和管理的,要用Object Pascal的内存管理函数来为PChar所指向的内存进行分配。PChar字符串的理论最大长度是4GB。

    在大多数情况下,AnsiString类型能被用成PChar,应该尽可能地使用AnsiString,因为它对字符串内存的管理是自动,极大地减少了应用程序中内存混乱的错误代码,因此,要尽可能地避免用PChar类型以及对它相应进行人工分配内存。在Debug下开启内存泄漏:

    {$ifdef DEBUG}

    ReportMemoryLeaksOnShutDown := True; //插入到应用程序入口的begin语句下。

    {$endif}

    通常,用StrAlloc()函数为PChar缓冲区分配内存,但是其他几种函数也能用来为PChar类型分配函数,包括AllocMem()、GetMem()、StrNew()和VirtualAlloc()API函数。这些函数有相应的释放内存的函数。

    var

    p: PChar;

    str: string;

    begin

    {可以给 PChar 直接赋予字符串常量}

    p := '中国';

    ShowMessage(IntToStr(Length(p))); {4}

    {给变量值需要转换}

    str := '中国杭州';

    p := PChar(str); {转换}

    ShowMessage(p); {中国杭州}

    ShowMessage(IntToStr(Length(p))); {8}

    end;

    //宽字符指针 PWideChar

    var

    p: PWideChar;

    str: WideString; {注意这里不是 String}

    begin

    {可以给 PWideChar 直接赋予字符串常量}

    p := '中国';

    ShowMessage(IntToStr(Length(p))); {2}

    {给变量值需要转换}

    str := '中国杭州';

    p := PWideChar(str); {转换}

    ShowMessage(p); {中国杭州}

    ShowMessage(IntToStr(Length(p))); {4}

    end;

    数值型

    整数型(Integer:整数型是整数的集合,包括多种不同的整数类别。

    类型

    表示范围

    字节

    ShortInt

    -128~127

    8位,有正负符号标志

    SmallInt

    -32 768~32 767

    16位,有正负符号标志

    LongInt

    -2 147 443 648~2 147 483 647

    32位,有正负符号标志

    Integer

    -2 147 443 648~2 147 483 647

    32位,有正负符号标志

    Int64

    -263~263-1

    64位,有正负符号标志

    Byte

    0~255

    8位,无正负符号标志

    Word

    0~65 535

    16位,无正负符号标志

    LongWord

    0~4 294 967 295

    32位,无正负符号标志

    Cardinal

    0~4 294 967 295

    32位,无正负符号标志

    实数型(Real):实数型是实数的集合,包括多种不同的类型。Real类型只有在和以前Borland Pascal兼容的情况下才使用,否则应使用DoubleExtended类型。

    类型

    范围

    有效位

    存储字节

    Real48

    2.9×10-39 ~ 1.7×1038

    11~12

    6

    Single

    1.5×10-45 ~ 3.4×1038

    7~8

    4

    Double

    5.0×10-324 ~ 1.7×10308

    15~16

    8

    Extended

    3.6×10-4951 ~ 1.1×104932

    19~20

    10

    Comp

    -263+1 ~ 263-1

    19~20

    8

    Currency

    -922 337 203 685 477.5 808 ~ 922 337 203 685 477.5 807

    19~20

    8

    Real

    5.0×10-324 ~ 1.7×10308

    15~16

    8

    Delphi数据类型分类如下:

    Delphi 数据类型列表

    分类

    范围

    字节

    备注

    简单类型

    序数

    整数

    Integer

    -2147483648 .. 2147483647

    4

    有符号32

    Cardinal

    0 .. 4294967295

    4

    无符号32

    Shortint

    -128 .. 127

    1

    有符号8

    Smallint

    -32768 .. 32767

    2

    有符号16

    Longint

    -2147483648 .. 2147483647

    4

    有符号32

    Int64

    -263 .. 263

    8

    有符号64

    Byte

    0 .. 255

    1

    无符号8

    Word

    0 .. 65535

    2

    无符号16

    Longword

    0 .. 4294967295

    4

    无符号32

    字符

    AnsiChar(Char)

    ANSI字符集

     

    8

    WideChar

    Unicode字符集

     

    16

    布尔

    Boolean

    False < True
    Ord(False) = 0
    Ord(True) = 1
    Succ(False) = True
    Pred(True) = False

    1

     

    ByteBool

    False <> True
    Ord(False) = 0
    Ord(True) <> 0
    Succ(False) = True
    Pred(False) = True

    1

     

    WordBool

    2

     

    LongBool

    4

     

    枚举

           

    子界

           

    实数

     

    Real

    5.0×10-324 .. 1.7×10308

    8

    [精度]15..16

    Real48

    2.9×10-39 .. 1.7×1038

    6

    [精度]11..12;
    向后兼容

    Single

    1.5×10-45 .. 3.4×1038

    4

    [精度]7..8

    Double

    5.0×10-324 .. 1.7×10308

    8

    [精度]15..16

    Extended

    3.6×10-4951 .. 1.1×104932

    10

    [精度]19..20

    Comp

    -263 + 1 .. 263 - 1

    8

    [精度]19..20

    Currency

    -922337203685477.5808 ..
    922337203685477.5807

    8

    [精度]19..20

    字符串

     

     

    ShortString

    255个字符

    2..256B

    向后兼容

    AnsiString

    大约 231 个字符

    4B..2GB

    8(ANSI)字符

    WideString

    大约 230 个字符

    4B..2GB

    多用户服务和
    多语言应用程序;
    com定义的BSTR兼容

    其他

    String
    String[0..255]
    PChar
    PAnsiString
    PWideString

       

    结构类型

    集合

     

    Set

    最多256个元素[0..255]

       

    数组

    静态数组

     

     

       

    动态数组

     

         

    记录

     

    Record

         

    文件

     

    File

         

     

    Class

         

    类引用

     

    Class reference

         

    接口

     

    Interface

         

    指针类型

    无类型指针

     

    Pointer

         

    有类型指针

    预定义类型指针

    PAnsiString
    PString
    PByteArray
    PCurrency
    PDouble
    PExtended
    PSingle
    PInteger
    POleVariant
    PShortString
    PTextBuf
    PVarRec
    PVariant
    PWideString
    PWordArray

         

    过程类型

    程序过程类型

     

    Procedural

         

    对象过程类型

     

    Procedural

     

       

    变体类型

     

     

    Variant

     

       

     

    OleVariant

     

       

    强制类型转换

    一、数的类型转换

      把表达式的类型从一种类型转化为另一种类型,结果值是把原始值截断或扩展,符号位保持不变。例如:

    数的类型转换

    字符转换为整数 Integer('A')

    整数转换为字符 Char(48)

    整数转换为1个字节的逻辑型 Boolean(0)

    整数转换为2个字节的逻辑型 WordBool(0)

    整数转换为4个字节的逻辑型 LongBool(0)

    整数转换为10进制pascal型字符串 caption:=intToStr(15)

    整数转换为16进制pascal型4位字符串 caption:=intToHex(15,4)

    地址转换为长整型数 Longint(@Buffer)

    二、数的"分开"与"合成"

    取32位longint型数的 高16位数为 hiword(longint-var)

    低16位数为 loword(longint-var)

    取16位数的 高8位数为 hibyte(integer_var)

    低8位数为 lobyte(integer_var)

    取32位地址的段选择符和偏移量 段选择符(高16位地址)为 selectorof(p)

    偏移量(低16位地址)为 offsetof(p)

    段选择符和偏移量合成为指针   Ptr(SEG, OFS: Word)相当于C语言的宏MK-FP(SEG,OFS)

    例如在Windows中,Task DataBase结构0FAh偏移处包含'TD'标识,我们可以容易地编写如下代码观察到这个位于Windows内部的未公开的秘密:

      {函数ptr(seg,ofs)的用法,相当于C语言的MK-FP(seg,ofs)}

      var p:pbyte;ch:char;

      p:=ptr(getcurrentTask,$FA);

      ch:=char(p^); {结果为ch='T'}

      p:=ptr(getcurrentTask,$FA+1);

      ch:=char(p^);   {结果为ch='D'}

    三、字符串string 字符数组与指向字符串的指针pchar的区别与联系

    1、使用指向字符串的指针,如果不是以0结尾,运行时就会出现错误。为了避免这种错误,需要在字符串结尾人工加入0 即char(0),或用strpcopy函数在字符串结尾自动加0。

      例1: 指向字符串的指针,如果不是以0结尾,运行时会出现错误:

      {s[0]=3 s[1]='n' s[2]='e' s[3]='w'}

      var

      s:string;

    p:pchar;

      begin

      s:='new';

      label1.caption:=s; {new}

     label2.caption:=intTostr(integer(s[0]));{3是字符串的长度}

      p:=@s[1];{不是以0结尾,莫用pchar型指针}

       label3.caption:=strpas(p); {运行时出现错误}

      end;

      例2:在字符串结尾人工加入0即char(0),可使用指向字符串的指针。

      {s[0]=4 s[1]='n' s[2]='e' s[3]='w' s[4]=0;}

      {p-->'new'}

      var

    s:string;

    p:pchar;

      begin

      p:=@s[1];

      s:='new'+char(0); {以0结尾,可用pchar型指针}

      label1.caption:=strpas(p); {new}

      label2.caption:=s; {new}

       label3.caption:=intTostr(integer(s[0])); {4是字符串长度}

      end;

      例3: 用strpcopy函数赋值会在字符串s结尾自动加0。

      {s[0]=4 s[1]='n' s[2]='e' s[3]='w' s[4]=0;}

      {p-->'new'}

      var

    s:string;

    p:pchar;

      begin

      p:=@s[1];

     strpcopy(p,'new');{strpcopy函数在字符串结尾自动加0}

      label1.caption:=strpas(p);{new}

       label2.caption:=s;{new}

      label3.caption:=intTostr(integer(s[0]));{4}

      end;

      2、下标为0的字符串标识符存放的是字符串长度,字符型数组基本相当于字符串,但不能存放字符串长度。字符串可以用s:='a string'的形式赋值,但是字符型数组a[ ]不可直接用a:='array'的形式赋值,用此种形式会出现类型不匹配错误,可选用strpcopy函数赋值。

      例4: 字符型数组s[ ]相当于字符串,但没有存放字符串长度的位置。

      {s[1]='n' s[2]='e' s[3]='w' s[4]=0;}

      {p-->'new'}

      var

    s:array[1..10] of char;

    p:pchar;

      begin

      {s:='new'+char(0); error}{错误}

      p:=@s[1];

      {p:=@s; is not correct}

      strpcopy(p,'new');

      label1.caption:=strpas(p);{new}

      label2.caption:=s;{new}

       {label3.caption:=intTostr(integer(s[0]));}{不会出现4, 下标超出错误}

      end;

      例5:下标从0开始的字符数组s,s相当于@s[0]。

      { s[0]='n' s[1]='e' s[2]='w' s[3]=0;}{p-->'new'}

      var

    s:array[1..10] of char;

    p:pchar;

      begin

      {s:='new'+char(0); error}{错误}

      p:=s;

      {p:=@s[0] is also correct}

      strpcopy(p,'new');

      label1.caption:=strpas(p);{new}

      label2.caption:=s;{new}

      label3.caption:=s[0];{n}

    end;

      3、下标从0开始和从1开始的字符数组地址的表示方法也有细微不同:

      例6:下标从1开始的数组a 与下标从0开始的数组b 的比较。

      var

    a:array[1..10]of char;

    b:array[0..10]of char;

      {a:='1..10';}{type mismatch}

      {b:='0..10';}{type mismatch}

    begin

      strpcopy( b, 'from 0 to 10'); {正确 因为b即是@b[0] }

      strpcopy(@b[0], 'from 0 to 10'); {正确 与上个表达式结果相同}

      strpcopy(@a[1], 'from 1 to 10'); {正确 }

      strpcopy( a, 'from 1 to 10'); {类型匹配错误 因为a即是@a[0]}

    end;

  • 相关阅读:
    笨方法学python笔记
    Orchard CMS 单点解决方案(SSO)及两种身份认证模块的介绍
    Orchard Oauth身份认证模块,在原基础上支持百度,豆瓣,开心,QQ,人人,新浪,淘宝
    凉鞋
    第一天
    网络编程vc++、socket机制
    定时器
    界面的多语言切换/通过读取xml文件实现
    svn快速教程
    文件读写
  • 原文地址:https://www.cnblogs.com/wordgao/p/4515490.html
Copyright © 2020-2023  润新知