我在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&#34; ABC&#34;字符串,但将每个字符变为wchar_t
- 意味着该对'A' + char(0)
不转向L'A'
而是转向L'A' + L'\0'
我在这里做错了什么,或者这是MultiByteToWideChar
的预期行为?
答案 0 :(得分:5)
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
字符都将被解释为codepoint { {1}},其余字符将按原样解释,因为它们都小于U+0000
。因此,你的&#34; UTF-8&#34;中没有多字节序列。字符串,只有单字节序列。
您最终得到的UTF-16 U+0080
包含以下代码点:
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
正确编码为UTF-8,然后将其解释为UTF-8,那么您最终会得到正确的UTF-16 str
:
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
编码为UTF-16并将其解释为UTF-16(您无法对str
执行此操作,则必须手动执行此操作),您仍将结束使用包含正确代码点的UTF-16 MultiByteToWideChar()
:
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);
答案 1 :(得分:3)
您正在错误地编码字符串"ABC"
。空字符是虚假的。 ASCII范围中的字符以UTF-8中的单个八位字节编码。
将其编码为:
std::string str;
str += 'A';
str += 'B':
str += 'C';
str += 0;
虽然
std::string str = "ABC";
更简单。