- std::wstring 与 std::string 相互转换
- std::string 与 LPCWSTR 相互转换
- 通过std::wstring作为中转(推荐)
- 直接转换(没事找事)
在C++的Windows.h中的许多界面函数为了兼容中文字符串,都用到了LPCWSTR
的数据类型(如OutputDebugString()
, MessageBox()
),该数据类型是const wchar_t *
的别名,即用宽字符表示的字符串。
在标准库STL中,表示宽字符的数据类型是std::wstring
,而最常用的字符串类型是std::string
。为了将std::string
转为LPCWSTR
,一种做法是首先将std::string
转为std::wstring
,再通过std::wstring::c_str()
方法获取静态宽字符串;另一种做法是将std::string
转为wchar_t *
,再直接赋值给LPCWSTR
。
std::wstring 与 std::string 相互转换
需要引入头文件Windows.h
,该文件包含了这一步必备的函数:MultiByteToWideChar
。
std::wstring -> std::string
1 2 3 4 5 6 7 8 9 10 11
| std::string ws2s(const std::wstring& ws) { int len; int slen = (int)ws.length() + 1; len = WideCharToMultiByte(CP_ACP, 0, ws.c_str(), slen, NULL, 0, NULL, NULL); char* buf = new char[len]; WideCharToMultiByte(CP_ACP, 0, ws.c_str(), slen, buf, len, NULL, NULL); std::string r(buf); delete[] buf; return r; }
|
std::string -> std::wstring
1 2 3 4 5 6 7 8 9 10 11
| std::wstring s2ws(const std::string& s) { int len; int slength = (int)s.length() + 1; len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, NULL, 0); wchar_t* buf = new wchar_t[len]; MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len); std::wstring r(buf); delete[] buf; return r; }
|
std::string 与 LPCWSTR 相互转换
通过std::wstring作为中转(推荐)
LPCWSTR
== const WCHAR *
== const wchar_t *
,明白了这个,就可以联想到,std::wstring
的c_str()
函数的返回值类型就是LPCWSTR
std::string -> LPCWSTR
1 2
| std::string text = "hello"; LPCWSTR r = s2ws(text).c_str();
|
LPCWSTR -> std::string:字符串默认是const char *
,加上L
表明是const wchar_t *
。
1 2
| LPCWSTR wstr = L"国泰民安"; std::string s = ws2s(wstr);
|
直接转换(没事找事)
直接转换纯属没事找事,用std::wstring
作为中转已经足够了,以下的方法仅作为记录,瞎折腾的笔记罢了。
LPCWSTR
-> std::string
: 和std::wstring
转std::string
写法一样
1 2 3 4 5 6 7 8 9 10 11
| std::string KvStrCvt::lpcwstr2string(LPCWSTR wstr) { int len; int slen = wcslen(wstr) + 1; len = WideCharToMultiByte(CP_ACP, 0, wstr, slen, NULL, 0, NULL, NULL); char* buf = new char[len]; WideCharToMultiByte(CP_ACP, 0, wstr, slen, buf, len, NULL, NULL); std::string r(buf); delete[] buf; return r; }
|
std::string
-> LPCWSTR
:先说结论:不推荐将返回值设置为LPCWSTR,推荐使用std::wstring作为中转。
如果不借用std::wstring
,一种实现的手段如下代码所示。但是这么写有一个问题:内存泄露
1 2 3 4 5 6 7 8 9 10
| LPCWSTR KvStrCvt::string2lpcwstr(const std::string& s) { int len; int slength = (int)s.length() + 1; len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, NULL, 0); wchar_t* buf = new wchar_t[len]; MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len); const wchar_t* wstr = buf; return wstr; }
|
把它写到一个循环中,会发现内存占用疯狂增加:
1 2 3 4
| while (true) { LPCWSTR wstr = KvStrCvt::string2lpcwstr("国泰民安"); }
|
改成如下的形式,会发现输出为乱码,并且编译器报错:C26816,指针指向堆栈上的内存
1 2 3 4 5 6 7 8 9 10 11
| LPCWSTR KvStrCvt::string2lpcwstr(const std::string& s) { int len; int slength = (int)s.length() + 1; len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, NULL, 0); wchar_t* buf = new wchar_t[len]; MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len); std::wstring wstr(buf); delete[] buf; return wstr.c_str(); }
|
因此,并不建议将转换的返回值直接设置为LPCWSTR
,特别是当这个返回值还是个变量,除非水平超高。