关于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),声明⼀个短字符串有两种⽅式,如下:
var
S: ShortString; { 255个字符长度,256个字节}
S1: String[255]; { S1和S的字符类型⼀样}
Len: Integer;
begin
S := 'Hello';
Len := Ord(S[0]); { Len现在包含S的长度为5,Ord函数可以把⼀个字符类型转换为整数类型}
Len := SizeOf(S); { Len现在包含的是ShortString类型的⼤⼩,为256字节}
end;
以上例⼦通过S[0]可以获得S的字符串长度,当然也可以⽤Length函数来确定⼀个短字符串的长度。
可以通过数组的下标来访问ShortString中的⼀个特定位置的字符,具体使⽤参看下⾯例⼦和注释说明:
var
S: string[8];
i: Integer;
begin
S := 'a_pretty_darn_long_string';
{ 因为S只有8个字符⼤⼩,
因此s的实际存储的内容为“a_pretty”}
i := 10;
S[i] := 's';
{ 因为S只有8个字符⼤⼩,
试图改写第10个元素,将会使内存混乱}
end;
2、长字符串(Long String)
长字符串(AnsiString)是⼀种动态分配的字符串,其⼤⼩只受可⽤内存的限制。声明⼀个长字符串,只需要⽤关键字String不加⼤⼩参数即可。
在Delphi 7中AnsiString包含的字符是⽤单字节存储的。
var
S: string;
由于是动态分配的,⼀次可以随意修改字符串,⽽不⽤担⼼对其他的影响,也不⽤担⼼越界的问题。String类型没有0元素,试图存取String 类型的0元素会产⽣⼀个编译错误。
通过Length函数也可以获得长字符串的长度,也可以通过SetLength过程为长字符串设置长度。其在内存中分配情况如下:
3、宽字符串(Wide String)
宽字符串和长字符串⼀样,⼤⼩只受有效内存的限制,并实⾏动态分配。
在Delphi 7 中WideString被实现为2个字节存储⼀个字符,⽤WideString来处理多字节字符是⼗分⽅便的。如:
var
S: string;
{ 在Delphi 7中默认string等同于AnsiString}
WS: WideString;
begin
S := '世界你好';
WS := S;
ShowMessage(S[1]); { 此时⽆任何显⽰,因为S[1]取出的是‘世’的⼀半}
ShowMessage(WS[1]); { 显⽰‘世’}
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函数,此函数声明如下:
function MessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;
第⼆个和第三个参数需要⼀个指向字符数组的指针,为了可以调⽤此函数,有以下三种⽅法来实现
1、PChar()类型转换
var
Text: string;
Caption: string;
delphi trunc函数begin
Text := 'This is a test.';
Caption := 'Test Message';
MessageBox(0, PChar(Text), PChar(Caption), 0);
{ 这⾥PChar⽤来把string类型转换为Null结尾的字符串}
end;
其中
2、PChar变量
我们先做⼀个实现,看看PChar类型到底是啥呢?
运⾏下⾯程序:
var
Text: PChar; { 声明为PChar类型}
Str: string; { 声明为String类型}
begin
Text := 'This is a test.'; { 都被赋予了相同的字符串}
Str := 'This is a test.';
ShowMessage(IntToStr(SizeOf(Text))); { 4字节,实质是指针}
ShowMessage(IntToStr(SizeOf(Str))); { 也是4字节,也是指针}
end;
通过上⾯的程序,我们知道Text只不过是⼀个指针⽽已。
var
Text: PChar;
begin
Text := 'This is a test.';
MessageBox(0, Text, 'Test Message', 0);
{ 这⾥Text直接声明为了PChar类型,字符串常量可以直接⽤}
end;
指针Text指向了这样⼀个内存区域,⼀个包含Null的结尾的’This is a test’字符串的区域。其等同于下⾯的代码:
const
TempString: array[0..15] of Char = 'This is a test.'#0;
var
Text: PChar;
begin
Text := @TempString[0];
{Text指向Null结尾的TempString字符数组的第0个元素的地址,
也就是整个字符数组的⾸地址}
MessageBox(0, Text, 'Test Message', 0);
end;
3、Char类型字符数组
最有还可以⽤Char数组来代替PChar,代码如下:
var
Text1: array[0..14] of Char; { ⼤⼩为15个字符}
Text2: array[0..20] of Char; { ⼤⼩为21个字符}
begin
Text1 := 'This is a test.'; {Text1和Text2的字符长度都为15个字符}
Text2 := 'This is a test.';
MessageBox(0, Text1, 'Test Message 1', 0);
{因为Text1的字符长度超过了其声明的⼤⼩,因为会内存访问混乱,显⽰换乱} MessageBox(0, Text2, 'Test Message 2', 0);
{Text2的字符长度⽐起声明的⼤⼩要⼩,因为正常访问,显⽰正确}
end;
显⽰结果如下:
关于字符串就先浅浅的谈到这个,以后再深⼊了解。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论