1. 程式人生 > >徹底搞定char/wchar_t!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

徹底搞定char/wchar_t!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

一.ANSIUNICODE

1.為什麼要使用Unicode

1 可以很容易地在不同語言之間進行資料交換。

2 使你能夠分配支援所有語言的單個二進位制.exe檔案或DLL檔案。

3 提高應用程式的執行效率。

Windows 2000是使用Unicode從頭進行開發的,如果呼叫任何一個Windows函式並給它傳遞一個ANSI字串,那麼系統首先要將字串轉換成Unicode,然後將Unicode字串傳遞給作業系統。如果希望函式返回ANSI字串,系統就會首先將Unicode字串轉換成ANSI字串,然後將結果返回給你的應用程式。進行這些字串的轉換需要佔用系統的時間和記憶體。通過從頭開始用

Unicode來開發應用程式,就能夠使你的應用程式更加有效地執行。

Windows 98只支援ANSI,只能為開發ANSI應用程式。 Windows CE 就是使用Unicode的作業系統,完全不支援ANSI版函式。

MicrosoftCOMWin16轉換成Win32時,所有COM介面方法都只能接受Unicode字串。

2ANSI字元和Unicode字元

ANSI字元型別為CHAR指向字串的指標PSTR(LPSTR)指向一個常數字符串的指標PCSTR(LPCSTR);對應的Windows定義的Unicode字元型別為WCHARtypedef WCHAR wchar_t,指向

Unicode字串的指標PWSTR ,指向一個常數Unicode字串的指標PCWSTR 

ANSI “ANSI” 

Unicode L“UNICODE”

ANSI/Unicode T(“string”)_TEXT(“string”)

3ANSI字元和Unicode字串的操作

雙位元組(DBCS)字符集中,字串的每個字元可以包含一個或兩個位元組。如果只是呼叫strlen()函式,那麼你就無法知道字串到底有多少個字元,它只能告訴你到達結尾的0之前有多少個位元組。

標準c中的strcpy,strchr,strcat等只能用於ANSI字串,不能正確處理Unicode字串,因此也提供了一組補充函式,功能等價,但用於Unicode

碼。我們來看看string .h字串標頭檔案中是怎樣處理char*wchar_t*兩個字串版本的:

// \Microsoft Visual Studio 8\VC\include\string.h

char *strcat(char*,const char*);

wchar_t *wcschr(wchat_t*, const wchar_t*);

類似的還有strchr/wcschrstrcmp/wcscmpstrlen/wcslen etc. ANSI 操作函式以str開頭 strcpy Unicode操作函式以wcs開頭 wcscpy

MBCS 操作函式以_mbs開頭 _mbscpy

ANSI/Unicode 操作函式以_tcs開頭 _tcscpyC執行期庫)

ANSI/Unicode 操作函式以lstr開頭 lstrcpyWindows API

所有新的和未過時的函式在Windows2000中都同時擁有ANSIUnicode兩個版本。ANSI版本函式結尾以A表示;Unicode版本函式結尾以W表示。

二.ANSI/UNICODE通用字元/字串型別TCHAR/LPTSTR/LPCTSTR

Neutral ANSI/UNICODE types

1.通用字元型TCHAR

ifdef UNICODE it is wchar_tWCHARfor 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>UnicodeANSI字串的轉換: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.dllUNCURL地址動態連結庫檔案,用於註冊鍵值和色彩設定。因為作業系統字串函式常常被大型應用程式比如作業系統的外殼程序Explorer.exe所使用。由於這些函式使用得很多,因此,在應用程式執行時,它們可能已經被裝入RAM。這將有助於稍稍提高應用程式的執行效能。

// …\Microsoft Visual Studio 8\VC\PlatformSDK\Include\shlwapi.h

注意:使用StrCatStrCmpStrCpy 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

參考: