程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Unicode和字符串處理

Unicode和字符串處理

編輯:C++入門知識

      我們熟悉的ASCII碼全稱是美國國家信息交換標准碼,它起源於20世紀50年代末,並於1967年最終定型。ASCIIS碼使用7位(bit)的寬度,有26個小寫字母,26個大寫字母,10個數字,32個符號,33個控制碼,一個空格碼,共128個代碼。       ASCII的使用相當普及,是一種非常可靠的標准。但是,ASCII是一個真正的美國標准,它甚至滿足不了其他英語國家的需求,例如,ASCII碼並沒有英鎊符號。       我們知道,一些語言文字系統(例如中國的漢字)的字符集有非常多的符號,但一個字節最多只能表示256個符號,這是遠遠不夠的。為了支持這些文字系統,雙字節字符集(doube-byte character set, DBCS)應運而生。在雙字節字符集中,一個字符由1個或2個字節組成。對程序員來說,和雙字節字符集打交道就如同一場噩夢,因為程序員需要判斷每個字節是否雙字節的前導字節。       與DBCS的混亂不同,Unicode統一使用16位進行編碼,即UTF-16編碼。UTF的全稱是Unicode Transformation Format。UTF-16將每個字符編碼2個字節(16位)。這樣一來,應用程序很容易遍歷字符串長度。 一、char數據類型       我們知道,C語言用char數據類型來表示一個8位ANSI字符。當在代碼中聲明一個字符串時,C編譯器會把字符串中的字符轉換成由8位char數據類型組成的數組。例如, [cpp]   char c = 'A';   char szBuffer[100] = "A String";         可以定義一個指向字符串的指針:  [cpp]   char *p;         由於windows是一個32位的系統,指針變量p需要4個字節的存儲空間。也可以定義並初始化一個指向字符串的指針: [cpp]  char *p = "Hello!";         變量p和之前一樣,也只是需要4個字節的空間。字符串存儲在靜態內存中並使用7個字節來存儲——其中6個字節存儲字符串,另一個字節存儲結束的'\0'。 二、wchat_t類型       Microsoft的C/C++編譯器定義了一個內建的數據類型wchat_t,表示一個16位的Unicode(UTF—16)字符。       聲明Unicode字符和字符串的方法如下: [cpp]   wchar_t c = L'A';   wchar_t szBuffer[100] = L"A String";         字符串前面的大寫字母L通知編譯器該字符串應當編譯為一個Unicode字符串。當編譯器將此字符串放入程序的數據段時,會使用UTF-16來編碼每個字符。       為了與C語言有一些區分,Windows開發團隊希望定義自己的數據類型。於是,他們定義了以下數據類型: [cpp]   typedef char CHAR;       // 一個8位的字符   typedef wchar_t WCHAR;   // 一個16位的字符         除此之外,Windows還定義了一系列為我們提供方便的數據類型,可以用它們來處理字符指針和字符串指針: [cpp]   // 指向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]   #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]  // 若定義了UNICODE,則作用16位的字符,否則使用8位的字符   TCHAR C = TEXT('A');      // 若定義了UNICODE,則作用16位的字符串,否則使用8位的字符串    TCHAR szBuffer[100] = TEXT("A String");   四、Windows中的Unicode函數和ANSI函數       如果一個Windows函數的參數列表中有字符串,則該函數通常有兩個版本。例如MessageBox函數,它有兩個入口點,一個名為MessageBoxA接受ANSI字符串,一個名為MessageBoxW接受Unicode字符串。       MessageBoxA的定義如下: [cpp]   int WINAPI MessageBoxA (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);   MessageBoxW的定義如下: [cpp]  int WINAPI MessageBoxW (HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);         注意第二第三個參數分別指向8位和16位的字符串。       在編寫代碼時,我們只需使用MessageBox,根據是否已定義UNICODE標識符,會自動選擇MessageBoxA函數還是MessageBoxW函數。 [cpp]   #ifdef UNICODE   #define MessageBox MessageBoxW   #else   #define MessageBox MessageBoxA   五、C運行庫中的Unicode函數和ANSI函數       在C運行庫中,strlen是一個返回ANSI字符串長度的函數,與之對應的是wcslen函數,它返回的是Unicode字符串的長度。       為方便使用,定義了以下的宏: [cpp]   #ifdef _UNICODE   #define _tcslen wcslen   #else   #define _tcslen strlen   #endif         這樣,只需要代碼中使用_tcslen,即可以獲得字符串的長度。 六、推薦的字符和字符串處理方式 1. 將文本字符串想象為字符的數組,而不是char或者字節的數組 2. 使用通用的數據類型(如TCHAR/PTSTR)來表示文本字符和字符串 3. 用明確的數據類型(如BYTE或PBYTE)表未字節,字節指針和數據緩沖區 4. 用TEXT或_T宏來表示字面常字符和字符串,但為了保持一致,請避免混用 5. UNICODE和_UNICODE符號要麼同時指定,要不都不指定 6. 避免使用printf系列函數,尤其不要使用%s和%S來進行ANSI與Unicode字符串之間的轉換,正確的做法是使用MultiByteToWideChar和WideCharToMultiByte函數 7. 修改有關字符串的計算。例如,函數經常希望傳給它的是緩沖區大小的字符數,而不是字節數,這時應使用_countof(szBuffer),而不是sizeof(szBuffer)。如果要為一個字符串分配內存塊,那麼請記住內存是以字節來分配的。這意味著需使用malloc(nCharacters * sizeof(TCHAR)),而不是調用malloc(nCharacters)。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved