上午在整理多線程的文章,沒注意時間今天發晚了,最近爭取日更!!
Delphi中的字符一直處于懵懵懂懂的狀態,不同于我接觸到的其它編程語言在Delphi中居然有好幾種字符串,今天好好研究一番!!
Delphi中字符串的操作很簡單,但幕后情況卻相當復雜。Pascal傳統的字符串操作方法與Windows不同,Windows吸取了C語言的字符串操作方法。
32位Delphi中增加了長字符串類型,該類型功能強大,是Delphi缺省的字符串類型。
傳統的字符串類型是一個字符序列,序列的頭部是一個長度字節,指示當前字符串的長度。由于只用一個字節來表示字符串的長度,所以字符串不能超過255個字符。
這一長度限制為字符串操作帶來不便,因為每個字符串必須定長(確省最大值為255),當然你也可以聲明更短的字符串以節約存儲空間。 為克服傳統Pascal字符串的局限性,32位Delphi增加了對長字符串的支持。這樣共有三種字符串類型:
ShortString短字符串類型也就是前面所述的傳統Pascal字符串類型。短字符串中的每個字符都屬于 AnsiChar類型(標準字符類型)
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;AnsiString
這種類型也有人稱為長字符串類型(LongString)同時也是Delphi默認的字符串類型,它是一種動態分配的字符串,其大小只受可用內存的限制。聲明一個長字符串,只需要用關鍵字String不加大小參數即可。據說使用了更新前拷貝(copy--on-write)技術。恕我才疏學淺沒研究過這個東西。這類字符串長度沒有限制(可以存儲多達20億個字符),其字符類型也是AnsiChar類型。
由于是動態分配的,一次可以隨意修改字符串,而不用擔心對其他的影響,也不用擔心越界的問題。String類型沒有0元素,試圖存取String類型的0元素會產生一個編譯錯誤。
之前在萬一老師的博客中看到了以下的代碼不太理解,現在可以完全解釋為什么我們試圖將一個string類型的變量直接賦值給字符數組時報錯了
//字符串 < > 字符數組,注意這里說的字符串僅僅是長字符串var arr: array[0..5] of Char; str: string;begin {可以把字符串常量直接賦給字符數組; 但超界不行} arr := 'Delphi'; ShowMessage(arr); {Delphi} {可以把字符數組直接賦給字符串變量} str := arr; ShowMessage(str); {Delphi} {其實字符串內部也是包含了一個字符數組, 所以能索引訪問, 不過它的索引起始于 1} ShowMessage(str[1]); {D} ShowMessage(arr[0]); {D} {但不能把一個字符串變量賦給字符數組} //arr := str; {錯誤; 這需要用其他手段實現, 譬如復制或移動內存}end;WideString
長字符串類型與AnsiString 類型相似,只是它基于WideChar字符類型,WideChar字符為雙字節Unicode字符。
var S: string; { 在Delphi 7中默認string等同于AnsiString} WS: WideString;begin S := '世界你好'; WS := S; ShowMessage(S[1]); { 此時無任何顯示,因為S[1]取出的是‘世’的一半} ShowMessage(WS[1]); { 顯示‘世’}end;
不過WideString和AnsiString的不同主要在三個方面:
WideString由WideChar字符組成,而不是由AnsiChar字符組成的,它們跟Unicode字符串兼容。WideString用SysAllocStrLen()API函數進行分配,它們跟OLE的BSTR字符串相兼容。WideString沒有引用計數,所以將一個WideString字符串賦值給另一個WideString字符串時,就需要從內存中的一個位置復制到另一個位置。這使得WideString在速度和內存的利用上不如AnsiString有 效。Ansi和Unicode字符編碼:為了區分一個字符到底使用了幾個字節,就不能將字符的編號直接存儲到計算機中,字符編號在存儲之前必須要經過轉換,在讀取時還要再逆向轉換一次,這套轉換方案就叫做字符編碼。它規定了如何將字符的編號存儲到計算機中
字符集:為每個字符分配了唯一的編號。可以將字符集理解成一個很大的表格,它列出了所有字符和二進制的對應關系,計算機顯示文字或者存儲文字,就是一個查表的過程。它定義了字符和二進制的對應關系
ASCII(American Standard Code for Information Interchange,美國信息交換標準碼),它使用7 bits來表示一個字符,總共表示128個字符,后來IBM公司在此基礎上進行了擴展,用8bit來表示一個字符,總共可以表示256個字符
ANSI(American National Standard Institite)美國國家標準學會(美國的一個非營利組織),首先ANSI編碼是一種對ASCII碼的拓展,它不是指的一種特定的編碼,而是不同地區擴展編碼方式的統稱,各個國家和地區所獨立制定的兼容ASCII但互相不兼容的字符編碼,微軟統稱為ANSI編碼
Unicode 是一套字符集,而不是一套字符編碼。它固定使用16 bits(兩個字節)來表示一個字符,共可以表示65536個字符。標準的Unicode稱為UTF-16。后來為了雙字節的Unicode能夠在現存的處理單字節的系統上正確傳輸,出現了UTF-8
個人理解:ANSI是每個國家根據自己的語言在ASCII基礎擴展的一些編碼。為了實現大一統出現了Unicode,而Unicode為了兼容以前的字符出現了雙字節(UTF-16)和單字節(UTF-8)之分
PChar和字符數組在第二季的視頻中我曾經對端口號做過一次轉換sin_addr.S_addr := inet_addr(PAnsiChar(AnsiString(EditAddr.Text))); 這段代碼,一個將字符串轉成PAnsiChar的一個場景,這是個什么玩意兒?其實這樣做純粹是為了兼容winAPI中的數據類型
在C和C++中沒有真正的字符串數據類型,都是通過以Null結尾(0)的字符數組來實現的,字符數組沒有長度字節,因此只能通過結尾的Null標志來作為字符串的字符結束標志。又因為Windows是用C編寫的,很多Windows函數要用到以字符數組作為參數,但Pascal字符串類型不是字符數組,因為為了讓Pascal字符串也能與Windows兼容,就需要一個字符串數組,PChar類型正是符合這種需求,在任何需要字符數組的地方都可用PChar。相應的也有PAnsiChar和PWideChar,分別對應于AnsiChar字符和WideChar字符。
其實最初我也被字符串折騰的不行不行的,所以整理這篇文章
本文發布于:2023-02-28 21:08:00,感謝您對本站的認可!
本文鏈接:http://m.newhan.cn/zhishi/a/1677728553100172.html
版權聲明:本站內容均來自互聯網,僅供演示用,請勿用于商業和其他非法用途。如果侵犯了您的權益請與我們聯系,我們將在24小時內刪除。
本文word下載地址:delphi7教程(delphi7基礎教程).doc
本文 PDF 下載地址:delphi7教程(delphi7基礎教程).pdf
| 留言與評論(共有 0 條評論) |