0%

C++ std::string std::wstring LPCWSTR相互转换

  1. std::wstring 与 std::string 相互转换
  2. std::string 与 LPCWSTR 相互转换
    1. 通过std::wstring作为中转(推荐)
    2. 直接转换(没事找事)

在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::wstringc_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::wstringstd::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,特别是当这个返回值还是个变量,除非水平超高。