這節內容主要是介紹一下Unicode的背景知識,由於或計劃的趨勢本書作者是大力推薦使用Unicode進行編成的。但是我這種連VC++都不會使用,還考慮什麼國際化編程呀。不過還是小結一下吧,不然我就白看了......................
一、字符集的歷史
由於字符表示的需要,各個不同的人或組織根據自己的需要建立了不同的字符集系統。下面一個標表示了不同的字符集的建立時間和創立者:
字符集名稱 | 創立者 | 時間 | 初始目的 | 特點 |
莫斯電碼 | Samuel F. B. Morse | 1838年到1854年間 | 電報 | 字母表中的每個字符對應於一系列短的和長的脈衝(點和破折號),沒有大小寫區分,有數字 |
Braille代碼 | Louis Braille | 1821年到1824年之間 | 盲人閱讀 | 種6位代碼,它把字符、常用字母組合、常用單字和標點進行編碼。用特殊的符號標示大寫和數字的開始 |
Hollerith卡片 | Herman Hollerith | 首次在1890年的美國人口普查中使用 | ||
ASCII | 美國國家標準協會 | 完成於1967年 | 計算機 | 7bit |
ANSI/ISO 8859-1-1987 | Microsoft | 1985年11月發行 | 純Windows字符集,首次在Windows 1.0中出現 | |
雙字節字符集(DBCS) | 象形文字 | Windows支持四個不同的雙字節字符集:代碼頁932(日文)、936(簡體中文)、949(韓語)和950(繁體漢字)。只有爲這些國家(地區)生產的Windows版本才支持DBCS。 | ||
Unicode | 多家公司合作 | 1996 | 計算機 | 每個字符都是16位寬,表示65,536個字符 |
二、Windows和C對Unicode的支持
可以說現在的Windows和C都是對Unicode支持的。其中Windows95/98是通過轉換成ANSI的方式小範圍的進行支持,而之後的軟件都是從底層支持了,這一點可以從XP的兼容模式上得到印證。
而在VC++中使用Unicode編程還是比較麻煩的,這是由於很多已有的C標準函數還是使用舊有的字符集。強行使用會導致程序報錯,得不到應有的結果。所以,作者介紹了很多專門針對Unicode的編程函數。
不過這些都很沒有用啦。最關鍵的部分是:
所以,爲了看都後面的文章,瞭解一下UNICODE編成的方法,和特徵還是很重要的。對於這一部分,作者是說要用TCHAR的方式,經過查詢MSDN發現上面比作者所得還要有條理,我就COPY上面的好了:
ms-help://MS.MSDNQTR.2003FEB.2052/vccore/html/_core_generic.2d.text_mappings_in_tchar..h.htm
Visual C++ 概念:添加功能 |
爲簡化代碼傳輸以方便國際使用,Microsoft 運行時庫爲許多數據類型、例程和其他對象提供 Microsoft 特定的“一般文本”映射。您可以使用 TCHAR.H 中定義的這些代碼,根據使用 #define 語句定義的清單常數,編寫可以爲單字節、多字節或 Unicode 編譯的一般代碼。一般文本映射是與 ANSI 不兼容的 Microsoft 擴展。
使用頭文件 TCHAR.H 可以從同一個源中生成單字節、MBCS 和 Unicode 應用程序。TCHAR.H 定義以 _tcs 爲前綴的宏,這些宏根據正確的預處理器定義映射到適當的 str、_mbs 或 wcs 函數。若要生成 MBCS,請定義 _MBCS 符號。若要生成 Unicode,請定義 _UNICODE 符號。若要生成單字節應用程序,請不進行任何定義(默認)。默認情況下,爲 MFC 應用程序定義的是 _MBCS。
在 TCHAR.H 中根據條件定義 _TCHAR 數據類型。如果爲您的版本定義了 _UNICODE 符號,則 _TCHAR 被定義爲 wchar_t;否則,對於單字節和 MBCS 版本,_TCHAR 被定義爲 char。(wchar_t 是基本的 Unicode 寬字符數據類型,它是與 8 位有符號 char 對應的 16 位有符號 char。)對於國際應用程序,使用以 _TCHAR(而非字節)爲單位進行操作的 _tcs 函數族。例如,_tcsncpy 複製 n 個 _TCHAR,而不是 n 個字節。
由於 SBCS 字符串處理函數採用(有符號的)char* 參數,因此定義 _MBCS 時將產生類型不匹配的編譯器警告。有三種方法避免此警告,按效率高低的順序依次爲:
- 在 TCHAR.H 中使用“類型安全”內聯函數 thunk。這是默認行爲。
- 通過在命令行上定義 _MB_MAP_DIRECT,在 TCHAR.H 中使用“直接”宏。如果這樣做,必須手動匹配類型。這是最快的方法,但不是類型安全的方法。
- 在 TCHAR.H 中使用“類型安全”靜態鏈接庫函數 thunk。若要這樣做,請在命令行上定義 _NO_INLINING 常數。這是最慢的方法,但卻是類型安全性最高的方法。
一般文本映射的預處理器指令
# define | 編譯版本 | 示例 |
---|---|---|
_UNICODE | Unicode(寬字符) | _tcsrev 映射到 _wcsrev |
_MBCS | 多字節字符 | _tcsrev 映射到 _mbsrev |
無(默認:既未定義 _UNICODE 也未定義 _MBCS) | SBCS (ASCII) | _tcsrev 映射到 strrev |
例如,如果在程序中定義了 _MBCS,則 TCHAR.H 中定義的一般文本函數 _tcsrev 映射到 _mbsrev。或者如果在程序中定義了 _UNICODE,則 _tcsrev 映射到 _wcsrev。否則 _tcsrev 映射到 strrev。在 TCHAR.H 中還提供了其他數據類型映射以方便編程,但 _TCHAR 是最有用的。
一般文本數據類型映射
一般文本數據類型名 | 未定義 _UNICODE 或 _MBCS | 已定義 _MBCS |
已定義 _UNICODE |
---|---|---|---|
_TCHAR | char | char | wchar_t |
_TINT | int | int | wint_t |
_TSCHAR | signed char | signed char | wchar_t |
_TUCHAR | unsigned char | unsigned char | wchar_t |
_TXCHAR | char | unsigned char | wchar_t |
_T 或 _TEXT | 無效(由預處理器移除) | 無效(由預處理器移除) | L(將後面的字符或字符串轉換成相應的 Unicode 形式) |
有關例程、變量和其他對象的一般文本映射的完整列表,請參見“運行時庫參考”中的一般文本映射。
注意 Unicode 字符串有可能包含嵌入空字節,所以不要在 Unicode 字符串中使用 str 函數族。同樣道理,不要在 MBCS(或 SBCS)字符串中使用 wcs 函數族。
下列代碼片段闡釋了有關映射到 MBCS、Unicode 和 SBCS 模型的 _TCHAR 和 _tcsrev 的用法。
_TCHAR *RetVal, *szString; RetVal = _tcsrev(szString);
如果已定義 _MBCS,則預處理器將此片段映射到下列代碼:
char *RetVal, *szString; RetVal = _mbsrev(szString);
如果已定義 _UNICODE,則預處理器將此片段映射到下列代碼:
wchar_t *RetVal, *szString; RetVal = _wcsrev(szString);
如果既未定義 _MBCS 也未定義 _UNICODE,則預處理器將此片段映射到單字節 ASCII 代碼:
char *RetVal, *szString; RetVal = strrev(szString);
因此可以編寫、維護和編譯與三種字符集中任何一種的特定例程一起運行的單個源代碼文件。
請參見
---------------------------
書中說到“格式字符串”,一開始還不太理解,其實不是我一開始理解的是用來定義字符串的格式。可能是翻譯的問題吧,它的意思應該是包含了格式字符的字符串(比如說%d,/n都是格式字符)。BTW:這是我猜的:)