c++ - MultiByteToWideChar 不能很好地转换我的字符串

标签 c++ winapi unicode

我正在 std::string 上构建一个合成的 UTF-8 字符串,并尝试使用 MultiByteToWideChar 对其进行转换。 这是我的代码:

std::string str;
str += 'A'; 
str += char(0);
str += 'B';
str += char(0);
str += 'C';
str += char(0);
str += char(0);
str += char(0);
std::wstring wstr;

if (str.empty()){
    wstr = L"";
}
int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), NULL, 0) + 1;
std::wstring wstrTo(sizeNeeded, 0);
MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), &wstrTo[0], sizeNeeded);
wstr = wstrTo;

std::wcout << wstr; 

事实证明,MultiByteToWideChar 并没有将 str 简单地转换为 L"ABC"字符串,而是将每个字符分别转换为 wchar_t - 意思是'A' + char(0) 不会变成 L'A' 而是变成 L'A' + L'\0'

我是不是做错了什么,或者这是 MultiByteToWideChar 的预期行为?

最佳答案

std::string str;
str += 'A'; 
str += char(0);
str += 'B';
str += char(0);
str += 'C';
str += char(0);
str += char(0);
str += char(0);

这不是生成 UTF-8 编码的字符串!它正在生成一个 UTF-16 编码的字符串。

int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), NULL, 0) + 1;

您告诉 MultiByteToWideChar()str 的原始字节解释为 UTF-8,即使它实际上并未以 UTF-8 编码。

Unicode 代码点 U+0000 在 UTF-8 中有效(它被编码为 0x00),因此 中的每个 0x00 字符>str 将被解释为代码点 U+0000,其余字符将按原样解释,因为它们都小于 U+0080。因此,在您的“UTF-8”字符串中没有多字节序列,只有单字节序列。

您最终得到一个包含以下代码点的 UTF-16 wstring:

0x41 -> U+0041 
0x00 -> U+0000
0x42 -> U+0042
0x00 -> U+0000
0x43 -> U+0043
0x00 -> U+0000
0x00 -> U+0000
0x00 -> U+0000

如果您将 str 正确编码为 UTF-8,然后将其解释为 UTF-8,您最终会得到正确的 UTF-16 wstring:

std::string str;
str += 'A'; 
str += 'B';
str += 'C';
str += char(0);

0x41 -> U+0041 
0x42 -> U+0042
0x43 -> U+0043
0x00 -> U+0000

或者,如果您将 str 编码为 UTF-16 并将其解释为 UTF-16(您不能使用 MultiByteToWideChar(),您将不得不这样做它手动),你仍然会得到一个包含正确代码点的 UTF-16 wstring:

std::string str;
str += 'A'; 
str += char(0);
str += 'B';
str += char(0);
str += 'C';
str += char(0);
str += char(0);
str += char(0);

0x41 0x00 -> U+0041 
0x42 0x00 -> U+0042
0x43 0x00 -> U+0043
0x00 0x00 -> U+0000

关于c++ - MultiByteToWideChar 不能很好地转换我的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30278849/

相关文章:

c++ - 查找内存分配错误

python - 将带有子元素的整个 QGraphicSscene 保存到文件中

c++ - 如何在发送 EM_SETCUEBANNER 消息时更改文本提示的颜色?

c++ - 当基于 CDialog 的应用程序启动时,如何将我的辅助对话窗口置于顶部?

mysql - 中文名称和 Unicode 基本多语言平面 (BMP)

python - 使用 python 2.7,为什么我的 unicode 文件名在调用 file() 时会引发 IOError ?

unicode - Google 计算器千位分隔符特殊字符

c++ - 共享库对象文件链接

c++ - 尝试使用opencv(c++)在实时视频帧的中间绘制垂直线

c++ - 如何在不需要消息循环的情况下使套接字访问行为为 'asynchronously'?