第二章 字符和字符串(Working with Characters and Strings)
1. 字符的編碼方式
UTF:Unicode Transformation Format
三種編碼方式:UTF-8 UTF-16 UTF-32
UTF-8:根據(jù)字符的分類,分別用1~4字節(jié)來表示一個字符
UTF-32:所有的字符都用4字節(jié)表示
UTF-16:用兩字節(jié)表示大部分語言的字符,當(dāng)兩節(jié)字無法表示時通過surrogates四字節(jié)表示字符
注:.Net FrameWork用UTF 16對所有字符進行編碼,所以當(dāng)需要在托管和非托管代碼間傳遞字符或字符串時最好用UTF16統(tǒng)一字符的編碼方式。這樣可以提高程序的性能,節(jié)省內(nèi)存
2. Windows中自定義的字符類型
typedef char CHAR; // An 8-bit character
typedef unsigned short wchar_t;
typedef wchar_t WCHAR; // A 16-bit character
3.定義字符變量
wchar_t c = L'A';// A 16-bit character
wchar_t szBuffer[100] = L"A String";// An array up to 99 16-bit characters
and a 16-bit terminating zero.
TCHAR c = TEXT('A');
L 告訴編譯器它后面的字符要編譯成Unicode string
TEXT宏用于編寫ANSI和Unicode都能識別的代碼。
其實現(xiàn)如下:
#ifdef UNICODE
#define __TEXT(quote) L##quote
#else
#define __TEXT(quote) quote
#endif
#define TEXT(quote) __TEXT(quote)
4.頭文件注釋(Header Annotations)
頭文件注釋描述一個函數(shù)如何使用它的參數(shù)。在VS Enterprise版 中可以通過”Code Analysis”來分析函數(shù)的調(diào)用是否符合 Header annotation所定義的語義。
如:GetModuleFileName
(
__in_opt HMODULE hModule,
__out_ecount_part(nSize, return + 1) LPTSTR lpFilename,
__in DWORD nSize
);
_in The function reads from the buffer. The caller provides the buffer and initializes it.
_inout The function both reads from and writes to buffer. The caller provides the buffer and initializes it. If used with _deref, the buffer may be reallocated by the function.
詳見:http://msdn.microsoft.com/en-us/library/aa383701.aspx
5.Win API后綴 A/W
為提供對ANSI和Unicode的支持。Win API分別針對ANSI和Unicode版本提供了不同的版本實現(xiàn)。
如: CreateWindowEx 有兩個不同的實現(xiàn)
CreateWindowExW Unicode版
CreateWindowExA ANSI版
我們在調(diào)用時不用關(guān)心具體去調(diào)用哪個版本,因為Windows已經(jīng)處理好了。說見下:
#ifdef UNICODE
#define CreateWindowEx CreateWindowExW
#else
#define CreateWindowEx CreateWindowExA
#endif
其實CreateWindowExA內(nèi)部只是為把ANSI字符串轉(zhuǎn)換成Unicode字符串 然后調(diào)用CreateWindowExW
6.C Run Time Library 與ANSI 和Unicode
和Win API一樣 C Run Time Library 提供一套庫用于字符和字符串的操作。這個庫中的每個函數(shù)也有兩個版本,與Win API不同的是ANSI版本和Unicode版本的函數(shù)沒有相互調(diào)用的關(guān)系, 而且針針ANSI和Unicode做了完全不同的實現(xiàn)。
ASNI字符操作的頭文件中String.h, 如果要寫ANSI和Unicode都兼容的代碼則還需引用文件<TChar.h>它定義了一些宏,如下:
#ifdef _UNICODE
#define _tcslen wcslen
#else
#define _tcslen strlen
#endif
wcslen和strlen是CRT Library針對Unicode 和ANSI提供的求字符串長度的函數(shù)。
7.安全的字符串函數(shù)
安全的字符串函數(shù)的頭文件Strsafe.h
http://msdn2.microsoft.com/en-us/library/ms647466.aspx
cch 函數(shù)。如:StringCchCopy
C安全函數(shù)列表
http://msdn2.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx
所有函數(shù)都以_S結(jié)尾,如strcat_s, wcscat_s, _mbscat_s
HRESULT StringCchCopy (PTSTR pszDest, size_t cchDest, PCTSTR pszSrc);
HRESULT StringCchCopyEx (PTSTR pszDest, size_t cchDest, PCTSTR pszSrc, PTSTR *ppszDestEnd, size_t *pcchRemaining,DWORD dwFlags)
HRESULT StringCbCopy (LPTSTR pszDest,size_t cbDest,LPCTSTR pszSrc);
其中Cch是Count of character的縮寫,即字符的個數(shù),一個字符可能占一字節(jié),也可能占兩字節(jié),
其值用_countof() 宏算出。
WCHAR *w = L”abc”;
雖然sizeof(w) 是6 但 _countof(L”abc”) 等于3
與Cch相反,Cb是Count of bye的縮寫,即字節(jié)的個數(shù)
StringCchCopy 即可用于ANSI也可用于UNICODE
#ifdef UNICODE
#define StringCchCopy StringCchCopyW
#else
#define StringCchCopy StringCchCopyA
#endif // !UNICODE
Ex代表用戶可以控制字符串的操作。
PTSTR 其中
STR代表是字符串
P 代表是指針
T 代表該類型會根據(jù)UNICODE的宏對應(yīng)相應(yīng)的指針, char * 或 wchar_t *
強制用UNICODE時, 應(yīng)把UNICODE和_UNICODE宏定義在所有頭文件的前面,如下:
#define UNICODE
#define _UNICODE
#include <windows.h>