你的转换函数有问题。
MultiByteToWideChar() 的返回值是宽字符数,而不是您当前处理的字节数。调用malloc()时需要将值乘以sizeof(WCHAR)。
您也没有考虑到返回值不包含空终止符的空间,因为您没有在cbMultiByte 参数中传递-1。 Read the MultiByteToWideChar() documentation:
cbMultiByte [输入]
lpMultiByteStr 参数指示的字符串的大小(以字节为单位)。或者,如果字符串以 null 结尾,则可以将此参数设置为 -1。请注意,如果cbMultiByte 为0,则函数失败。
如果此参数为 -1,则函数处理整个输入字符串,包括终止空字符。因此,生成的 Unicode 字符串有一个终止空字符,并且函数返回的长度包括该字符。
如果此参数设置为正整数,则函数会精确处理指定的字节数。 如果提供的大小不包含终止空字符,则生成的 Unicode 字符串不会以空字符结尾,并且返回的长度不包含此字符。
...
返回值
如果成功,则返回写入lpWideCharStr 指示的缓冲区的字符数。如果函数成功且cchWideChar 为0,则返回值为lpWideCharStr 指示的缓冲区所需的大小,以字符为单位。
您没有以空值终止您的输出字符串。
convert_from_wstring() 函数也是如此。 Read the WideCharToMultiByte() documentation:
cchWideChar [输入]
lpWideCharStr 指示的字符串的大小(以字符为单位)。或者,如果字符串以 null 结尾,则可以将此参数设置为 -1。如果cchWideChar设置为0,则函数失败。
如果此参数为 -1,则函数处理整个输入字符串,包括终止空字符。因此,生成的字符串有一个终止空字符,函数返回的长度包括这个字符。
如果此参数设置为正整数,则该函数将精确处理指定数量的字符。 如果提供的大小不包含终止空字符,则生成的字符串不是空终止字符,并且返回的长度不包含此字符。
...
返回值
如果成功,则返回写入lpMultiByteStr 指向的缓冲区的字节数。如果函数成功并且cbMultiByte 为0,则返回值为lpMultiByteStr 指示的缓冲区所需的大小,以字节为单位。
话虽如此,您的main() 代码正在泄漏分配的字符串。由于它们是使用malloc() 分配的,因此在使用完它们后,您需要使用free() 释放它们:
此外,您不能将WCHAR* 字符串传递给std::cout。好吧,你可以,但它没有用于宽字符串输入的operator<<,但它确实有用于void* 输入的operator<<,所以它最终只会输出内存地址 WCHAR* 指向,而不是实际字符。如果要输出宽字符串,请改用std::wcout。
试试这样的:
WCHAR* convert_to_wstring(const char* str)
{
int str_len = (int) strlen(str);
int num_chars = MultiByteToWideChar(CP_UTF8, 0, str, str_len, NULL, 0);
WCHAR* wstrTo = (WCHAR*) malloc((num_chars + 1) * sizeof(WCHAR));
if (wstrTo)
{
MultiByteToWideChar(CP_UTF8, 0, str, str_len, wstrTo, num_chars);
wstrTo[num_chars] = L'\0';
}
return wstrTo;
}
CHAR* convert_from_wstring(const WCHAR* wstr)
{
int wstr_len = (int) wcslen(wstr);
int num_chars = WideCharToMultiByte(CP_UTF8, 0, wstr, wstr_len, NULL, 0, NULL, NULL);
CHAR* strTo = (CHAR*) malloc((num_chars + 1) * sizeof(CHAR));
if (strTo)
{
WideCharToMultiByte(CP_UTF8, 0, wstr, wstr_len, strTo, num_chars, NULL, NULL);
strTo[num_chars] = '\0';
}
return strTo;
}
int main()
{
const WCHAR* wText = L"Wide string";
const char* text = convert_from_wstring(wText);
std::cout << text << "\n";
free(text);
const WCHAR *wtext = convert_to_wstring("Multibyte string");
std::wcout << wtext << "\n";
free(wtext);
return 0;
}
话虽如此,您确实应该使用std::string 和std::wstring 而不是char* 和wchar_t* 以获得更好的内存管理:
std::wstring convert_to_wstring(const std::string &str)
{
int num_chars = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
std::wstring wstrTo;
if (num_chars)
{
wstrTo.resize(num_chars);
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &wstrTo[0], num_chars);
}
return wstrTo;
}
std::string convert_from_wstring(const std::wstring &wstr)
{
int num_chars = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), NULL, 0, NULL, NULL);
std::string strTo;
if (num_chars > 0)
{
strTo.resize(num_chars);
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), &strTo[0], num_chars, NULL, NULL);
}
return strTo;
}
int main()
{
const WCHAR* wText = L"Wide string";
const std::string text = convert_from_wstring(wText);
std::cout << text << "\n";
const std::wstring wtext = convert_to_wstring("Multibyte string");
std::wcout << wtext << "\n";
return 0;
}
如果您使用的是 C++11 或更高版本,请查看 std::wstring_convert 类在 UTF 字符串之间进行转换,例如:
std::wstring convert_to_wstring(const std::string &str)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conv;
return conv.from_bytes(str);
}
std::string convert_from_wstring(const std::wstring &wstr)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conv;
return conv.to_bytes(wstr);
}
如果您需要与基于char*/wchar_t*、std::string 作为接受char* 输入的构造函数和可用于char* 输出的c_str() 方法的其他代码进行交互,std::wstring 和 wchar_t* 也是如此。