關于Delphi中的字符串的詳細分析

字號:


    只是淺淺的解析下,讓大家可以快速的理解字符串。
    其中的所有代碼均在Delphi7下測試通過。
    Delphi 4,5,6,7中有字符串類型包括了:
    短字符串(Short String)
    長字符串(Long String)
    寬字符串(Wide String)
    零結尾字符串(Null-Terminated String)、PChar和字符數組
    1、短字符串(Short String)
    固 定長度,最大字符數個數為255,短字符串也成為長度字節(jié)(Length-byte)字符串,這時因為短字符串的第0個元素包含了這個字符串的長度(字符 串中字符的個數)。因此ShortString的缺省最大長度為256個字節(jié)(255個字符+1個長度字節(jié)=256),聲明一個短字符串有兩種方式,如 下:
    var
    S: ShortString; { 255個字符長度,256個字節(jié)}
    S1: String[255]; { S1和S的字符類型一樣}
    Len: Integer;
    begin
    S := 'Hello';
    Len := Ord(S[0]); { Len現在包含S的長度為5,Ord函數可以把一個字符類型轉換為整數類型}
    Len := SizeOf(S); { Len現在包含的是ShortString類型的大小,為256字節(jié)}
    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)是一種動態(tài)分配的字符串,其大小只受可用內存的限制。聲明一個長字符串,只需要用關鍵字String不加大小參數即可。
    在Delphi 7中AnsiString包含的字符是用單字節(jié)存儲的。
    var
    S: string;
    由于是動態(tài)分配的,一次可以隨意修改字符串,而不用擔心對其他的影響,也不用擔心越界的問題。String類型沒有0元素,試圖存取String類型的0元素會產生一個編譯錯誤。
    通過Length函數也可以獲得長字符串的長度,也可以通過SetLength過程為長字符串設置長度。其在內存中分配情況如下:
    名單
    3、寬字符串(Wide String)
    寬字符串和長字符串一樣,大小只受有效內存的限制,并實行動態(tài)分配。
    在Delphi 7 中WideString被實現為2個字節(jié)存儲一個字符,用WideString來處理多字節(jié)字符是十分方便的。如:
    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)的字符數組來實現的,字符數組沒有長度字節(jié),因此只能通過結尾的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字節(jié),實質是指針}
    ShowMessage(IntToStr(SizeOf(Str))); { 也是4字節(jié),也是指針}
    end;
    通過上面的程序,我們知道Text只不過是一個指針而已。
    var
    Text: PChar;
    begin
    Text := 'This is a test.';
    MessageBox(0, Text, 'Test Message', 0);
    { 這里Text直接聲明為了PChar類型,字符串常量可以直接用}
    end;
    指針Text指向了這樣一個內存區(qū)域,一個包含Null的結尾的’This is a test’字符串的區(qū)域。其等同于下面的代碼:
    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;
    顯示結果如下:
    名單
    關于字符串就先淺淺的談到這個,以后再深入了解。