標籤:
只是淺淺的解析下,讓大家可以快速的理解字串。
其中的所有代碼均在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;
- 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;
顯示結果如下:
關於字串就先淺淺的談到這個,以後再深入瞭解。
********************************************************************
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 做中轉;
關於Delphi中的字串的詳細分析