国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

Unicode和字符串處理(轉(zhuǎn))

2019-11-08 03:21:19
字體:
供稿:網(wǎng)友

我在為公司編寫打印機程序時,遇到了一個字符串傳參時格式的問題,看了這個人的博客,解決了問題,現(xiàn)在轉(zhuǎn)載過來:http://blog.csdn.net/lihao21

我們熟悉的ASCII碼全稱是美國國家信息交換標準碼,它起源于20世紀50年代末,并于1967年最終定型。ASCIIS碼使用7位(bit)的寬度,有26個小寫字母,26個大寫字母,10個數(shù)字,32個符號,33個控制碼,一個空格碼,共128個代碼。      ASCII的使用相當普及,是一種非常可靠的標準。但是,ASCII是一個美國的標準,它甚至滿足不了其他英語國家的需求,例如,ASCII碼并沒有英鎊符號。      我們知道,一些語言文字系統(tǒng)(例如中國的漢字)的字符集有非常多的符號,但一個字節(jié)最多只能表示256個符號,這是遠遠不夠的。為了支持這些文字系統(tǒng),雙字節(jié)字符集(doube-byte character set, DBCS)應運而生。在雙字節(jié)字符集中,一個字符由1個或2個字節(jié)組成。對程序員來說,和雙字節(jié)字符集打交道就如同一場噩夢,因為程序員需要判斷每個字節(jié)是否雙字節(jié)的前導字節(jié)。      Unicode是1988年由Apple與Xerox共同建立的一項標準。與DBCS的混亂不同,Unicode統(tǒng)一使用16位進行編碼,即UTF-16編碼。UTF的全稱是Unicode Transformation Format(Unicode轉(zhuǎn)換格式)。UTF-16將每個字符編碼為2個字節(jié)(16位)。這樣一來,程序員在處理這種格式的編碼時,就顯得相對簡單。      除了UTF-16編碼,還有其他用于表示字符的UTF標準。UTF-8UTF-8將一些字符編碼為1個字節(jié),一些字符編碼為2個字節(jié),一些字符編碼為3個字節(jié),一些字符編碼為4個字節(jié)。值在0x0080以下的字符壓縮為1個字節(jié),這對美國使用的字符非常適合。0x0080和0x07ff之間的字符轉(zhuǎn)換為2個字節(jié),這對歐洲和中東地區(qū)的語言非常適合。0x0800以上的字符都轉(zhuǎn)換為3個字節(jié),適合東亞地區(qū)的語言。使用代理對(surrogate pair)轉(zhuǎn)換為4個字節(jié)。UTF-8是一種非常流行的編碼格式。UTF-32UTF-32將所有的字符都編碼為4個字節(jié)。從使用的角度來看,由于所有字符的字節(jié)數(shù)一定,所以處理起來較為簡單。但從內(nèi)存使用的角度來看,UTF-32并不是一種高效的編碼方式。因此,在網(wǎng)絡傳輸?shù)葓龊?,很少會使用UTF-32這種編碼格式。UTF-32一般在應用程序內(nèi)部使用。      在談到Unicode時,除非特別聲明,我們一般是指UTF-16編碼。

一、char數(shù)據(jù)類型

      我們知道,C語言用char數(shù)據(jù)類型來表示一個8位ANSI字符。當在代碼中聲明一個字符串時,C編譯器會把字符串中的字符轉(zhuǎn)換成由8位char數(shù)據(jù)類型組成的數(shù)組。例如,[cpp] view plain copychar c = 'A';  char szBuffer[100] = "A String";        可以定義一個指向字符串的指針: [cpp] view plain copychar *p;        由于windows是一個32位的系統(tǒng),指針變量p需要4個字節(jié)的存儲空間。也可以定義并初始化一個指向字符串的指針:[cpp] view plain copychar *p = "Hello!";        變量p和之前一樣,也只是需要4個字節(jié)的空間。字符串存儲在靜態(tài)內(nèi)存中并使用7個字節(jié)來存儲——其中6個字節(jié)存儲字符串,另一個字節(jié)存儲結(jié)束的'/0'。

二、wchat_t類型

      Microsoft的C/C++編譯器定義了一個內(nèi)建的數(shù)據(jù)類型wchat_t,表示一個16位的Unicode(UTF—16)字符。      聲明Unicode字符和字符串的方法如下:[cpp] view plain copywchar_t c = L'A';  wchar_t szBuffer[100] = L"A String";        字符串前面的大寫字母L通知編譯器該字符串應當編譯為一個Unicode字符串。當編譯器將此字符串放入程序的數(shù)據(jù)段時,會使用UTF-16來編碼每個字符。      為了與C語言有一些區(qū)分,Windows開發(fā)團隊希望定義自己的數(shù)據(jù)類型。于是,他們定義了以下數(shù)據(jù)類型:[cpp] view plain copytypedef char CHAR;       // 一個8位的字符  typedef wchar_t WCHAR;   // 一個16位的字符        除此之外,Windows還定義了一系列為我們提供方便的數(shù)據(jù)類型,可以用它們來處理字符指針和字符串指針:[cpp] view plain copy// 指向8位字符(串)的指針  typedef CHAR *PCHAR;  typedef CHAR *PSTR;  typedef CONST CHAR *PCSTR;    // 指向16位的字符(串)指針  typedef WCHAR *PWCHAR;  typedef WCHAR *PWSTR;  typedef CONST WCHAR *PCWSTR;  

三、維護一個源代碼

      在寫代碼的時候,可以使用ANSI 或Unicode字符/字符串。為使其能通過編譯,windows定義了以下的類型的宏:

[cpp] view plain copy#ifdef UNICODE    typedef WCHAR TCHAR, *PTCHAR, PTSTR;  typedef CONST WCHAR *PCTSTR;    #define __TEXT(quote) L##quote    #else    typedef CHAR TCHAR, *PTCHAR, PTSTR;  typedef CONST CHAR *PCTSTR;    #define __TEXT(quote) quote    #endif    #define TEXT(quote) __TEXT(quote)  

      利用這些類型和宏,無論使用ANSI還是Unicode,都可以通過編譯。[cpp] view plain copy// 若定義了UNICODE,則作用16位的字符,否則使用8位的字符  TCHAR C = TEXT('A');    // 若定義了UNICODE,則作用16位的字符串,否則使用8位的字符串   TCHAR szBuffer[100] = TEXT("A String");  

四、Windows中的Unicode函數(shù)和ANSI函數(shù)

      如果一個Windows函數(shù)的參數(shù)列表中有字符串,則該函數(shù)通常有兩個版本。例如MessageBox函數(shù),它有兩個入口點,一個名為MessageBoxA接受ANSI字符串,一個名為MessageBoxW接受Unicode字符串。      MessageBoxA的定義如下:[cpp] view plain copyint WINAPI MessageBoxA (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);  MessageBoxW的定義如下:[cpp] view plain copyint WINAPI MessageBoxW (HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);        注意第二第三個參數(shù)分別指向8位和16位的字符串。      在編寫代碼時,我們只需使用MessageBox,根據(jù)是否已定義UNICODE標識符,會自動選擇MessageBoxA函數(shù)還是MessageBoxW函數(shù)。[cpp] view plain copy#ifdef UNICODE  #define MessageBox MessageBoxW  #else  #define MessageBox MessageBoxA  

五、C運行庫中的Unicode函數(shù)和ANSI函數(shù)

      在C運行庫中,strlen是一個返回ANSI字符串長度的函數(shù),與之對應的是wcslen函數(shù),它返回的是Unicode字符串的長度。      為方便使用,定義了以下的宏:[cpp] view plain copy#ifdef _UNICODE  #define _tcslen wcslen  #else  #define _tcslen strlen  #endif        這樣,只需要代碼中使用_tcslen,即可以獲得字符串的長度。

六、推薦的字符和字符串處理方式

1. 將文本字符串想象為字符的數(shù)組,而不是char或者字節(jié)的數(shù)組2. 使用通用的數(shù)據(jù)類型(如TCHAR/PTSTR)來表示文本字符和字符串3. 用明確的數(shù)據(jù)類型(如BYTE或PBYTE)表未字節(jié),字節(jié)指針和數(shù)據(jù)緩沖區(qū)4. 用TEXT或_T宏來表示字面常字符和字符串,但為了保持一致,請避免混用5. UNICODE和_UNICODE符號要么同時指定,要不都不指定6. 避免使用PRintf系列函數(shù),尤其不要使用%s和%S來進行ANSI與Unicode字符串之間的轉(zhuǎn)換,正確的做法是使用MultiByteToWideChar和WideCharToMultiByte函數(shù)7. 修改有關字符串的計算。例如,函數(shù)經(jīng)常希望傳給它的是緩沖區(qū)大小的字符數(shù),而不是字節(jié)數(shù),這時應使用_countof(szBuffer),而不是sizeof(szBuffer)。如果要為一個字符串分配內(nèi)存塊,那么請記住內(nèi)存是以字節(jié)來分配的。這意味著需使用malloc(nCharacters * sizeof(TCHAR)),而不是調(diào)用malloc(nCharacters)。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 岳阳县| 扎鲁特旗| 德化县| 华蓥市| 循化| 繁昌县| 长丰县| 海宁市| 阜宁县| 任丘市| 浮梁县| 安化县| 汉阴县| 库尔勒市| 兰坪| 石渠县| 武平县| 铜梁县| 曲水县| 轮台县| 正安县| 莒南县| 平遥县| 澄迈县| 原平市| 浮梁县| 北海市| 虎林市| 湛江市| 定边县| 治多县| 山西省| 潜山县| 临城县| 凤城市| 芷江| 夹江县| 乾安县| 辰溪县| 射洪县| 新兴县|