C/C++中char *与wchar_t*的几种转换方法
多字節(char *)和寬字符(wchar_t *)之間的轉換有幾種方式,下面按照從通用到特殊的順序逐一介紹。
1、C庫函數
?1.1 關鍵函數
? ? (1) setlocale()
? ? ? ? 功能:配置地域化信息
? ? ? ? 頭文件:<locale.h>
? ? ? ? 函數原型:
char *setlocale(int category, const char *locale);
? ? ? ? 函數參數:
category:表示對本地化的某項內容進行設置,可取如下值:?
LC_ALL 包括下面的全部選項都要
LC_COLLATE 配置字符串比較
C_CTYPE 配置字符類別及轉換,例如全變大寫 strtoupper()
LC_MONETARY 配置金融貨幣
LC_NUMERIC 配置小數點后的位數
LC_TIME 配置時間日期格式,與 strftime() 合用
locale:表示本地域代號
? ? ? ? 返回值: 如果為NULL,則返回當前的locale名稱(一般為C);如果非空,則根據category和locale進行設置,如果成功,則返回新的locale名稱(地域名稱),如果失敗,則返回NULL。
? (2) wcstombs_s()
? ? 功能:將寬字符編碼字符串轉換成多字節編碼字符串
? ? 頭文件:<stdlib.h>
? ? ?函數原型:
? ? errno_t __cdecl wcstombs_s(size_t *_PtNumOfCharConverted, char * _Dst, size_t _DstSizeInBytes, const wchar_t * _Src, size_t _MaxCountInBytes);
? ? ? 函數參數:
?PtNumOfCharConverted:指向轉換后的字符串的長度加上結束符(單位字節)
Dst:指向轉換后的字符串首地址
DstSizeInBytes:目的地址最大字節空間(單位字節)?
_Src:源寬字符串首地址
_MaxCountInBytes:最多可存入多字節字符串緩沖最的字節數,用于裁剪轉換后的字符串
? ? ? ?返回值:成功返回0,失敗則返回失敗代碼
? ?(3) mbstowcs_s()
? ? 函數功能:將多字節編碼字符串轉換成寬字符編碼字符串
? ? 頭文件:<stdlib.h>
? ? ?函數原型:
errno_t __cdecl mbstowcs_s(size_t * _PtNumOfCharConverted, wchar_t * _DstBuf, size_t _SizeInWords, const char * _SrcBuf, size_t _MaxCount );
? ? 參數說明:?
PtNumOfCharConverted:指向轉換后的字符串的長度加上結束符(單位wchar_t)
_DstBuf:指向轉換后的字符串首地址
_SizeInWords:目的地址最大字符空間大小(單位wchar_t)
_SrcBuf:源多字節字符串首地址
_MaxCount:最多可存入寬字符串緩沖中的字符個數,用于裁剪轉換后的寬字符串
? ? ?返回值:成功返回0, 失敗則返回失敗代碼
1.2 實例
實例用C++實現,是為了使用string和wstring作為參數或返回值,內部仍然是把string轉換為char*,把wstring轉換為wchar_t*
如需C版本只要截取函數內部char*和wchar_t*互相轉換部分即可
#include <iostream> #include <locale.h> #include <string> using namespace std;string ws2s(const wstring& ws) {size_t convertedChars=0;string curLocale=setlocale(LC_ALL,NULL); //curLocale="C"setlocale(LC_ALL,"chs");const wchar_t* wcs = ws.c_str();size_t dByteNum=sizeof(wchar_t)*ws.size()+1;cout<<"ws.size():"<<ws.size()<<endl; //8 “123ABC你好”共8個字符char* dest=new char[dByteNum];wcstombs_s(&convertedChars,dest,dByteNum,wcs,_TRUNCATE);cout<<"ws2s_convertedChars:"<<convertedChars<<endl; //11 共使用了11個字節存儲多字節字符串 包括結束符string result=dest;delete[] dest;setlocale(LC_ALL,curLocale.c_str());return result; }wstring s2ws(const string& s) {size_t convertedChars=0;string curLocale=setlocale(LC_ALL,NULL); //curLocale="C"setlocale(LC_ALL,"chs");const char* source=s.c_str();size_t charNum=sizeof(char)*s.size()+1;cout<<"s.size():"<<s.size()<<endl; //10 “123ABC你好”共10個字節wchar_t* dest=new wchar_t[charNum];mbstowcs_s(&convertedChars,dest,charNum,source,_TRUNCATE);cout<<"s2ws_convertedChars:"<<convertedChars<<endl; //9 轉換為9個字符 包括結束符wstring result=dest;delete[] dest;setlocale(LC_ALL,curLocale.c_str());return result; }int main() {wchar_t *pwstr = L"123ABC你好";string sRet= ws2s(pwstr);cout<<sRet<<endl; //輸出 123ABC你好char *pstr = "123ABC你好";wstring swRet = s2ws(pstr);setlocale(LC_ALL, "chs"); //為了使wcout輸出中文 也可用wcout.imbue(locale("chs")) "chs"和"Chinese-simplified"通用wcout<<swRet<<endl; //輸出 123ABC你好}2.Windows API
在Windows平臺下,可以使用Windows提供的API進行轉換。
2.1 關鍵函數
(1)WideCharToMultiByte()?
功能:將寬字符串轉換成多字節字符串?
頭文件:<winnls.h>?
函數原型:
WINAPI
WideCharToMultiByte(
? ? _In_ UINT CodePage,
? ? _In_ DWORD dwFlags,
? ? _In_NLS_string_(cchWideChar) LPCWCH lpWideCharStr,
? ? _In_ int cchWideChar,
? ?_Out_writes_bytes_to_opt_(cbMultiByte, return) LPSTR lpMultiByteStr,
? ? _In_ int cbMultiByte,
? ? _In_opt_ LPCCH lpDefaultChar,
? ? _Out_opt_ LPBOOL lpUsedDefaultChar
);
函數參數:?
CodePage:指定執行轉換的代碼頁字符集,可以為操作系統已安裝或有效的任何代碼頁字符集,也可以指定其為下面的任意一值:?
CP_ACP:ANSI代碼頁;CP_ACP:ANSI代碼頁;CP_MACCP:Macintosh代碼頁;CP_OEMCP:OEM代碼頁;CP_SYMBOL:符號代碼頁;CP_THREAD_ACP:當前線程ANSI代碼頁;CP_UTF7:使用UTF-7轉換;CP_UTF8:使用UTF-8轉換。使用最多的就是CP_ACP和CP_UTF8;?
dwFlags:指定如何處理沒有轉換成功的字符,也可以不設此參數(設置為0),函數會運行的更快一些。對于UTF-8,dwflags必須為0或者WC_ERR_INVALID_CHARS,否則函數都將失敗返回并設置錯誤碼ERROR_INVALID_FLAGS,可以調用GetLastError獲得
lpWideCharStr:待轉換為寬字符串
cchWideChar:待轉換的寬字符串的長度(字符個數),-1表示轉換到字符串結尾
lpMultiByteStr:轉換后目的字符串緩沖區
cbMultiByte:目的字符串緩沖區大小(單位字節)。如果設置為0,函數將返回所需緩沖區大小而忽略lpMultiByteSt?
lpDefaultChar:指向字符的指針,在指定編碼里找不到相應字符時使用此字符作為默認字符替代。如果為NULL,則使用系統默認字符。使用dwFlags時不能使用此參數,否則報ERROR_INVLID_PARAMETER錯誤
lpUsedDefaultChar:開關變量的指針,表明是否使用過默認字符。對于要求此參數為NULL的dwflags而使用此參數,函數將失敗返回,并設置錯誤碼ERROR_INVLID_PARAMETER。lpDefaultChar和lpUsedDefaultChar都設為NULL,函數會更快一些
返回值:如果函數運行成功,并且cbMultiByte不為零,返回值是由 lpMultiByteStr指向的緩沖區中寫入的字節數;如果函數運行成功,并且cbMultiByte為零,返回值是接存放目的字符串緩沖區所必需的字節數。如果函數運行失敗,返回值為零。若想獲得更多錯誤信息,請調用GetLastError函數。
(2)MultiByteToWideChar()?
功能:多字節字符串到款字節字符串的轉換;?
頭文件:<winnls.h>?
函數原型:
int WINAPI MultiByteToWideChar(
? ? _In_ UINT CodePage,
? ? _In_ DWORD dwFlags,
? ? _In_NLS_string_(cbMultiByte) LPCCH lpMultiByteStr,
? ? _In_ int cbMultiByte,
? ? _Out_writes_to_opt_(cchWideChar, return) LPWSTR lpWideCharStr,
? ? _In_ int cchWideChar
);
函數參數:?
CodePage:同上;?
dwFlags:指定是否轉換成預制字符或合成的寬字符,是否使用象形文字替代控制字符,以及如何處理無效字符。對于UTF-8,dwflags必須為0或者WC_ERR_INVALID_CHARS,否則函數都將失敗返回并設置錯誤碼ERROR_INVALID_FLAGS,可以調用GetLastError獲得
lpMultiByteStr:多字節字符串
cbMultiByte:待轉換的多字節字符串長度,-1表示轉換到字符串結尾
lpWideCharStr:存放轉換后的寬字符串緩沖
cchWideChar:寬字符串緩沖的大小(單位字符數)
返回值:如果函數運行成功,并且cchWideChar不為零,返回值是由 lpWideCharStr指向的緩沖區中寫入的字符數;如果函數運行成功,并且cchWideChar為零,返回值是接存放目的字符串緩沖區所必需的字符數。如果函數運行失敗,返回值為零。若想獲得更多錯誤信息,請調用GetLastError函數。
2.2 實例
#include <windows.h> #include <iostream> using std::cout; using std::wcout; using std::locale; using std::endl;int main() {//寬字符轉多字節wchar_t *pws = L"我是寬字符串ABC";//第五個參數置NULL,用來計算多字節字符串需要的空間大小(單位字節,包括結束符)int bufSize = WideCharToMultiByte(CP_ACP,NULL,pws,-1,NULL,0,NULL,FALSE);cout<<bufSize<<endl;char *ps = new char[bufSize];WideCharToMultiByte(CP_ACP,NULL,pws,-1,ps,bufSize,NULL,FALSE);cout<<ps<<endl;delete [] ps;//多字節轉寬字符char *pstr = "我是多字節字符串ABC";//第五個參數置NULL,用來計算寬字符串需要的空間大小(字符個數,包括結束符)bufSize = MultiByteToWideChar(CP_ACP,0,pstr,-1,NULL,0);cout<<bufSize<<endl;wchar_t *pwstr = new wchar_t[bufSize];MultiByteToWideChar(CP_ACP,0,pstr,-1,pwstr,bufSize);wcout.imbue(locale("chs"));//或使用setlocale(LC_ALL, "chs") "chs"和"Chinese-simplified"通用wcout<<pwstr<<endl;delete [] pwst;return 0; }
2.3 關于locale設置
locale(即系統區域設置,即國家或地區設置)將決定程序所使用的當前語言編碼、日期格式、數字格式及其它與區域有關的設置,locale設置的正確與否將影響到程序中字符串處理(wchar_t如何輸出、strftime()的格式等)。
C locale和C++ locale是獨立的。C locale用setlocale(LC_CTYPE, “”)初始化。
C++ locale用std::locale::global(std::locale(“”))初始化。這樣就可以根據當前運行環境正確設置locale。
其他更具體的介紹請參考C++中的locale設置。
3.Winidows ATL
ATL定義了兩個轉換宏A2W()和W2A(),可以更方便的在char*和wchar_t*之間轉換。
頭文件:<atlconv.h>
USES_CONVERSION; ?char sz[] = "我是多字節string"; wchar_t *pWChar = A2W(sz); ?wchar_t wsz[] = L"我是寬字符string"; char *pChar = W2A(wsz);
備注:1. 需要先調用USES_CONVERSION宏,因為參數定義都在這里
??????????2. 轉換宏內部使用棧空間內存,最大2M,所以不要循環調用防止溢出; 建議把A2W()和W2A()放到大括號里調用
?
總結
以上是生活随笔為你收集整理的C/C++中char *与wchar_t*的几种转换方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows下ab的安装和压测
- 下一篇: IIS请求筛选模块被配置为拒绝超过请求内