徹底搞定char/wchar_t!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
一.ANSI和UNICODE
1.為什麼要使用Unicode?
(1) 可以很容易地在不同語言之間進行資料交換。
(2) 使你能夠分配支援所有語言的單個二進位制.exe檔案或DLL檔案。
(3) 提高應用程式的執行效率。
Windows 2000是使用Unicode從頭進行開發的,如果呼叫任何一個Windows函式並給它傳遞一個ANSI字串,那麼系統首先要將字串轉換成Unicode,然後將Unicode字串傳遞給作業系統。如果希望函式返回ANSI字串,系統就會首先將Unicode字串轉換成ANSI字串,然後將結果返回給你的應用程式。進行這些字串的轉換需要佔用系統的時間和記憶體。通過從頭開始用
Windows 98只支援ANSI,只能為開發ANSI應用程式。 Windows CE 就是使用Unicode的作業系統,完全不支援ANSI版函式。
Microsoft將COM從Win16轉換成Win32時,所有COM介面方法都只能接受Unicode字串。
2.ANSI字元和Unicode字元
ANSI字元型別為CHAR,指向字串的指標PSTR(LPSTR),指向一個常數字符串的指標PCSTR(LPCSTR);對應的Windows定義的Unicode字元型別為WCHAR(typedef WCHAR wchar_t),指向
ANSI “ANSI”
Unicode L“UNICODE”
ANSI/Unicode T(“string”)或_TEXT(“string”)
3.ANSI字元和Unicode字串的操作
雙位元組(DBCS)字符集中,字串的每個字元可以包含一個或兩個位元組。如果只是呼叫strlen()函式,那麼你就無法知道字串到底有多少個字元,它只能告訴你到達結尾的0之前有多少個位元組。
標準c中的strcpy,strchr,strcat等只能用於ANSI字串,不能正確處理Unicode字串,因此也提供了一組補充函式,功能等價,但用於Unicode
// …\Microsoft Visual Studio 8\VC\include\string.h
char *strcat(char*,const char*);
wchar_t *wcschr(wchat_t*, const wchar_t*);
類似的還有strchr/wcschr,strcmp/wcscmp,strlen/wcslen etc. ANSI 操作函式以str開頭 strcpy ,Unicode操作函式以wcs開頭 wcscpy
MBCS 操作函式以_mbs開頭 _mbscpy
ANSI/Unicode 操作函式以_tcs開頭 _tcscpy(C執行期庫)
ANSI/Unicode 操作函式以lstr開頭 lstrcpy(Windows API)
所有新的和未過時的函式在Windows2000中都同時擁有ANSI和Unicode兩個版本。ANSI版本函式結尾以A表示;Unicode版本函式結尾以W表示。
二.ANSI/UNICODE通用字元/字串型別TCHAR/LPTSTR/LPCTSTR
Neutral ANSI/UNICODE types
1.通用字元型TCHAR
ifdef UNICODE it is wchar_t(WCHAR)for Unicode platforms;
else it is char for ANSI and DBCS platforms.
2.通用字串指標LPTSTR
ifdef UNICODE it is LPWSTR(*wchar_t) for Unicode platforms;
else it is LPSTR (*char) for ANSI and DBCS platforms.
3.通用通用常數字符串指標LPCTSTR
ifdef UNICODE it is LPCWSTR(*const wchar_t) for Unicode platforms;
else it is LPCSTR (*const char) for ANSI and DBCS platforms.
typedef LPWSTR LP;
#define __TEXT(quote) L##quote // r_winnt
<1>_UNICODE巨集用於C執行期標頭檔案,UNICODE巨集則用於Windows標頭檔案,當編譯程式碼模組時,通常必須同時定義這兩個巨集。
<2>如果定義了_UNICODE,若要生成一個Unicode字串,字串前要加L巨集,用於告訴編譯器該字串應該作為Unicode字串來編譯處理。但是這樣又有個問題就是如果沒有定義_UNICODE則編譯出錯。為了解決這個問題我們必須用到_TEXT巨集,這個巨集也在TChar.h中做了定義。使用該巨集後,無論原始檔有沒有定義_UNICODE都不會出現編譯錯誤。
<3>Unicode與ANSI字串的轉換:Windows函式MultiByteToWideChar/mbstowcs函式用於將多位元組字串轉換成寬字串,函式WideCharToMultiByte/wcstombs將寬字串轉換成等價的多位元組字串。
三.ANSI/UNICODE字串通用函式lstrcmp/lstrcpy/lstrcat/lstrlen
// …\Microsoft Visual Studio 8\VC\PlatformSDK\Include\Winbase.h -- 已經包含在windows.h中。
lstrcmp(lstrcmpi)
WINBASEAPI
int
WINAPI
lstrcmpA(
__in LPCSTR lpString1,
__in LPCSTR lpString2
);
WINBASEAPI
int
WINAPI
lstrcmpW(
__in LPCWSTR lpString1,
__in LPCWSTR lpString2
);
#ifdef UNICODE
#define lstrcmp lstrcmpW
#else
#define lstrcmp lstrcmpA
#endif // !UNICODE
lstrcpy
WINBASEAPI
__out
LPSTR
WINAPI
lstrcpyA(
__out LPSTR lpString1,
__in LPCSTR lpString2
);
WINBASEAPI
__out
LPWSTR
WINAPI
lstrcpyW(
__out LPWSTR lpString1,
__in LPCWSTR lpString2
);
#ifdef UNICODE
#define lstrcpy lstrcpyW
#else
#define lstrcpy lstrcpyA
#endif // !UNICODE
另外還有lstrcat(W/A)和lstrlen(W/A),這裡未列出其函式定義。
四.使用shlwapi標頭檔案中定義的函式StrCat/StrCmp/StrCpy
shlwapi.dll是UNC和URL地址動態連結庫檔案,用於註冊鍵值和色彩設定。因為作業系統字串函式常常被大型應用程式比如作業系統的外殼程序Explorer.exe所使用。由於這些函式使用得很多,因此,在應用程式執行時,它們可能已經被裝入RAM。這將有助於稍稍提高應用程式的執行效能。
// …\Microsoft Visual Studio 8\VC\PlatformSDK\Include\shlwapi.h
注意:使用StrCat、StrCmp、StrCpy etc時要#include "shlwapi.h"
LWSTDAPI_(LPWSTR) StrCatW(LPWSTR psz1, LPCWSTR psz2);
LWSTDAPI_(int) StrCmpW(LPCWSTR psz1, LPCWSTR psz2);
LWSTDAPI_(LPWSTR) StrCpyW(LPWSTR psz1, LPCWSTR psz2);
#ifdef UNICODE
#define StrCat StrCatW
#define StrCmp StrCmpW
#define StrCpy StrCpyW
#else
#define StrCat lstrcatA
#define StrCmp lstrcmpA
#define StrCpy lstrcpyA
etc
參考: