关于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. MessageBox(0, Text2, ‘Test Message 2‘, 0);
  10. {Text2的字符长度比起声明的大小要小,因为正常访问,显示正确}
  11. 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 做中转;

时间: 2024-10-09 22:12:19

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

关于Delphi中的字符串的浅析(瓢虫大作,里面有内存错误的举例)

关于Delphi中的字符串的浅析 只是浅浅的解析下,让大家可以快速的理解字符串. 其中的所有代码均在Delphi7下测试通过. Delphi 4,5,6,7中有字符串类型包括了: 短字符串(Short String) 长字符串(Long String) 宽字符串(Wide String) 零结尾字符串(Null-Terminated String).PChar和字符数组 1.短字符串(Short String) 固定长度,最大字符数个数为255,短字符串也成为长度字节(Length-byte)字

(转)Delphi 中的字符串

一.Delphi 2009 之前的字符串(不支持 Unicode): Delphi 2009 之前的字符串分为 3 种:ShortString.AnsiString.WideString. [ShortString] ShortString 是一种比较古老的 Pascal 字符串格式,它最多只能容纳 255 个字节的字符.当我们声明一个 ShortString 类型的变量时,Delphi 会自动申请 256 个字节的内存空间给该变量,其中第一个字节用来存放字符串的长度,后面的 255 个字节用来

比较C/C++和Delphi中的字符串和字符数组(数组和动态分配内存的情况)

本文所讲解的只是从其中一个方面来看待进行的总结,所以有必要结合<Delphi字符串与字符数组之间的转换(初始化的重要性)>等文章进行更全面的了解,会从更多方面来理解字符串.内存.类型转换 C/C++中的字符串.字符数组.字符指针分配的内存空间 我们知道在C/C++中,我们可以这样理解字符串和字符数组 1)字符串,就是一个以 '\0' 结尾的字符数组 2)字符数组,包括字符串,但是不一定要以 '\0' 结尾,如果不是以'\0' 结尾,那么就不能当做字符串使用 在C/C++中,使用字符串可以通过数

Delphi中分隔字符串函数的使用

下面介绍Delphi自带的字符串分割函数,根据你的需要来使用. 1.ExtractStrings function ExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: PChar; Strings: TStrings): Integer; 第一个参数是分隔符,可以是多个,例如 [';',',',':'] 可以按分号.逗号.分号来同时分割. 第二个参数是开头被忽略的字符,例如['<','>',''],被分割出的字符,如果开头有

js中cookie的使用详细分析

cookie概述 cookie 是浏览器提供的一种机制,它将document 对象的cookie属性提供给JavaScript.可以由JavaScript对其进行控制,而并不是JavaScript本身的性质.cookie是 存于用户硬盘的一个文件,这个文件通常对应于一个域名,当浏览器再次访问这个域名时,便使这个cookie可用.因此,cookie可以跨越一个域名下的 多个网页,但不能跨越多个域名使用. 不同的浏览器对cookie的实现也不一样,但其性质是相同的.例如在Windows 2000以及

【转】js中cookie的使用详细分析

cookie概述 cookie 是浏览器提供的一种机制,它将document 对象的cookie属性提供给JavaScript.可以由JavaScript对其进行控制,而并不是JavaScript本身的性质.cookie是 存于用户硬盘的一个文件,这个文件通常对应于一个域名,当浏览器再次访问这个域名时,便使这个cookie可用.因此,cookie可以跨越一个域名下的 多个网页,但不能跨越多个域名使用. 不同的浏览器对cookie的实现也不一样,但其性质是相同的.例如在Windows 2000以及

PHP中$_SERVER常量的详细分析

["HTTP_HOST"] => string(9) "127.0.0.1" ["SERVER_NAME"] => string(9) "127.0.0.1" PHP的SERVER保留变量中HTTP_HOST 和 SERVER_NAME经常是一样的,原因是服务器端口是80,那么HTTP_HOST将省略不显示,而HTTP服务的默认端口就是80,所以大多数情况下,HTTP_HOST都没有显示这个端口号.而如果使用的是s

Java中的&lt;&lt; 和 &gt;&gt; 和 &gt;&gt;&gt; 详细分析

<<表示左移移,不分正负数,低位补0: 注:以下数据类型默认为byte-8位 左移时不管正负,低位补0 正数:r = 20 << 2 20的二进制补码:0001 0100 向左移动两位后:0101 0000    结果:r = 80 负数:r = -20 << 2 -20 的二进制原码 :1001 0100 -20 的二进制反码 :1110 1011 -20 的二进制补码 :1110 1100 左移两位后的补码:1011 0000 反码:1010 1111 原码:110

Delphi中Android运行和JNI交互分析

Androidapi.JNIBridge负责和JNI交互.,既然要交互,那么首先就是需要获得JNI的运行环境,Android本身内置的就有一个Java(Dalvik)虚拟机.所以这个第一步就肯定是要这个虚拟机和我们当前的运行线程环境关联.这时候Androidapi.JNIBridge中的TJNIResolver就出场了.GetJNIEnv这个函数就是, [delphi] view plaincopy class function TJNIResolver.GetJNIEnv: PJNIEnv;