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

时间:2015-05-16 17:45:09

标签: 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&#34; ABC&#34;字符串,但将每个字符变为wchar_t - 意味着该对'A' + char(0)不转向L'A'而是转向L'A' + L'\0'

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

2 个答案:

答案 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";

更简单。