zoukankan      html  css  js  c++  java
  • 关于Delphi中的字符串的详细分析

    关于Delphi中的字符串的详细分析

     

    只是浅浅的解析下,让大家可以快速的理解字符串。

    其中的所有代码均在Delphi7下测试通过。

    Delphi 4,5,6,7中有字符串类型包括了:

    • 短字符串(Short String
    • 长字符串(Long String
    • 宽字符串(Wide String
    • 零结尾字符串(Null-Terminated String)、PChar和字符数组

    1、短字符串(Short String

    固 定长度,最大字符数个数为255,短字符串也成为长度字节(Length-byte)字符串,这时因为短字符串的第0个元素包含了这个字符串的长度(字符 串中字符的个数)。因此ShortString的缺省最大长度为256个字节(255个字符+1个长度字节=256),声明一个短字符串有两种方式,如 下:

    1. var
    2.   S: ShortString;   { 255个字符长度,256个字节}
    3.   S1: String[255];  { S1和S的字符类型一样}
    4.   Len: Integer;
    5. begin
    6.   S := 'Hello';
    7.   Len := Ord(S[0]); { Len现在包含S的长度为5,Ord函数可以把一个字符类型转换为整数类型}
    8.   Len := SizeOf(S); { Len现在包含的是ShortString类型的大小,为256字节} 
    9. end;

    以上例子通过S[0]可以获得S的字符串长度,当然也可以用Length函数来确定一个短字符串的长度。

    可以通过数组的下标来访问ShortString中的一个特定位置的字符,具体使用参看下面例子和注释说明:

    1. var
    2.   S: string[8];
    3.   i: Integer;
    4. begin
    5.   S := 'a_pretty_darn_long_string';
    6.   { 因为S只有8个字符大小,
    7.   因此s的实际存储的内容为“a_pretty”}
    8.   i := 10;
    9.   S[i] := 's';
    10.   { 因为S只有8个字符大小,
    11.   试图改写第10个元素,将会使内存混乱}
    12. end;

    2、长字符串(Long String

    长字符串 (AnsiString)是一种动态分配的字符串,其大小只受可用内存的限制。声明一个长字符串,只需要用关键字String不加大小参数即可。

    在Delphi 7中AnsiString包含的字符是用单字节存储的。

    1. var
    2.   S: string;

    由于是动态分配的,一次可以随意修改字符串,而不用担心对其他的影响,也不用担心越界的问题。String类型没有0元素,试图存取String类型的0元素会产生一个编译错误。

    通过Length函数也可以获得长字符串的长度,也可以通过SetLength过程为长字符串设置长度。其在内存中分配情况如下:

     

    3、宽字符串(Wide String

    宽字符串和长字符串一样,大小只受有效内存的限制,并实行动态分配。

    在Delphi 7 中WideString被实现为2个字节存储一个字符,用WideString来处理多字节字符是十分方便的。如:

    1. var
    2.   S: string;
    3.   { 在Delphi 7中默认string等同于AnsiString}
    4.   WS: WideString;
    5. begin
    6.   S := '世界你好';
    7.   WS := S;
    8.   ShowMessage(S[1]);  { 此时无任何显示,因为S[1]取出的是‘世’的一半}
    9.   ShowMessage(WS[1]); { 显示‘世’}
    10. end;

    4、零结尾字符串(Null-Terminated String)、PChar和字符数组

    在C和C++中没有真正的字符串数据类型,都是通过以Null结尾(0)的字符数组来实现的,字符数组没有长度字节,因此只能通过结尾的Null标 志来作为字符串的字符结束标志。又因为Windows是用C编写的,很多Windows函数要用到以字符数组作为参数,但Pascal字符串类型不是字符 数组,因为为了让Pascal字符串也能与Windows兼容,就需要一个字符串数组,PChar类型正是符合这种需求,在任何需要字符数组的地方都可用 PChar。

    虽然AnsiString和WideString都已经实现了NULL

    相应的也有PAnsiChar和PWideChar,分别对应于AnsiChar字符和WideChar字符。

    例如:Windows MessageBox函数,此函数声明如下:

    1. function MessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;

    第二个和第三个参数需要一个指向字符数组的指针,为了可以调用此函数,有以下三种方法来实现

    1PChar()类型转换

    1. var
    2.   Text: string;
    3.   Caption: string;
    4. begin
    5.   Text := 'This is a test.';
    6.   Caption := 'Test Message';
    7.   MessageBox(0, PChar(Text), PChar(Caption), 0);
    8.   { 这里PChar用来把string类型转换为Null结尾的字符串}
    9. end;

    其中

    2PChar变量

    我们先做一个实现,看看PChar类型到底是啥呢?

    运行下面程序

    1. var
    2.   Text: PChar;    { 声明为PChar类型}
    3.   Str: string;    { 声明为String类型}
    4. begin
    5.   Text := 'This is a test.';             { 都被赋予了相同的字符串}
    6.   Str := 'This is a test.';
    7.   ShowMessage(IntToStr(SizeOf(Text)));   { 4字节,实质是指针}
    8.   ShowMessage(IntToStr(SizeOf(Str)));    { 也是4字节,也是指针}
    9. end;

    通过上面的程序,我们知道Text只不过是一个指针而已。

    1. var
    2.   Text: PChar;
    3. begin
    4.   Text := 'This is a test.';
    5.   MessageBox(0, Text, 'Test Message', 0);
    6.   { 这里Text直接声明为了PChar类型,字符串常量可以直接用}
    7. end;

    指针Text指向了这样一个内存区域,一个包含Null的结尾的’This is a test’字符串的区域。其等同于下面的代码:

    1. const
    2.   TempString: array[0..15] of Char = 'This is a test.'#0;
    3. var
    4.   Text: PChar;
    5. begin
    6.   Text := @TempString[0];
    7.   {Text指向Null结尾的TempString字符数组的第0个元素的地址,
    8.   也就是整个字符数组的首地址}
    9.   MessageBox(0, Text, 'Test Message', 0);
    10. end;

    3Char类型字符数组

    最有还可以用Char数组来代替PChar,代码如下:

    1. var
    2.   Text1: array[0..14] of Char;  { 大小为15个字符}
    3.   Text2: array[0..20] of Char;  { 大小为21个字符}
    4. begin
    5.   Text1 := 'This is a test.';   {Text1和Text2的字符长度都为15个字符}
    6.   Text2 := 'This is a test.';
    7.   MessageBox(0, Text1, 'Test Message 1', 0);
    8.   {因为Text1的字符长度超过了其声明的大小,因为会内存访问混乱,显示换乱}
    9.  
    10.   MessageBox(0, Text2, 'Test Message 2', 0);
    11.   {Text2的字符长度比起声明的大小要小,因为正常访问,显示正确}
    12. end;

    显示结果如下:

     

    关于字符串就先浅浅的谈到这个,以后再深入了解。

    ********************************************************************

    Delphi字符串、PChar与字符数组之间的转换

    var

      s: string;

      p: pchar;

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

    1、字符串 ---> PChar

      p := PChar(s); 

    2、PChar ---> 字符串

      s := p; 

    3、PChar ---> 字符数组

      StrCopy(@a , p); 

    4、字符数组 ---> PChar

      PChar(@a); 

    5、字符串 ---> 字符数组

      StrCopy(@a , PChar(s)); 

    6、字符数组 ---> 字符串

      s := PChar(@a); 

    【注】字符串和字符数组之间的转换借助 PChar 做中转;

  • 相关阅读:
    21天打造分布式爬虫-房天下全国658城市房源(十一)
    21天打造分布式爬虫-简书整站爬取(十)
    21天打造分布式爬虫-下载汽车之家图片(九)
    21天打造分布式爬虫-Crawl类爬取小程序社区(八)
    21天打造分布式爬虫-Spider类爬取糗事百科(七)
    21天打造分布式爬虫-Selenium爬取拉钩职位信息(六)
    21天打造分布式爬虫-多线程下载表情包(五)
    21天打造分布式爬虫-中国天气网和古诗文网实战(四)
    21天打造分布式爬虫-豆瓣电影和电影天堂实战(三)
    3.使用Selenium模拟浏览器抓取淘宝商品美食信息
  • 原文地址:https://www.cnblogs.com/bjxsky/p/4619868.html
Copyright © 2011-2022 走看看