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