您需要确保使用正确的数据初始化字符串,然后迭代器生成正确的值。
您使用的是 VS2010,所以字符串文字有点问题。C++ 实现有一个“执行字符集”,它们将来自“源字符集”的字符和字符串文字转换为该字符集。Visual Studio 不支持 UTF-8 作为执行字符集,因此不会有意生成 UTF-8 编码的字符串文字。
您可以通过欺骗编译器或使用十六进制转义来获得一个。此外,您可以获取包含正确数据的宽字符串,然后在运行时将其转换为 UTF-8,而不是获取 UTF-8 字符串文字。
编辑:Visual Studio 的最新版本现在确实有获取 UTF-8 字符串文字的方法。Visual Studio 2015 现在支持 C++11 的 UTF-8 字符串文字。在 Visual Studio 2015 Update 2 中,您还可以使用编译器标志/execution-charset:utf-8 或 /utf-8。
欺骗编译器
如果您将源代码保存为“不带签名的 UTF-8”,那么编译器会认为源编码是系统区域设置编码。VS 总是使用系统语言环境编码作为执行编码。因此,当它认为源编码和执行编码相同时,它不会执行任何转换,并且您的源字节(实际上是 UTF-8)将直接用于字符串文字,从而生成 UTF-8 编码的字符串文字。(请注意,这会破坏对宽字符和字符串文字所做的转换。)
十六进制转义
十六进制转义码允许您手动将任何值的代码单元(在本例中为字节)插入到字符串文字中。您可以手动确定所需的 UTF-8 编码,然后将这些值插入到字符串文字中。
std::string s1 = "\xd0\x94\xd0\xbe\xd0\xb1\xd1\x80\xd1\x8b\xd0\xb9 \xd0\xb4\xd0\xb5\xd0\xbd\xd1\x8c";
UTF-8 字符串文字前缀
C++11 指定了一个前缀,该前缀创建一个 UTF-8 字符串文字,而不管执行编码如何,但 Visual Studio 尚未实现这一点。这看起来像:
string s1 = u8"Добрый день";
它要求编译器知道并使用正确的源编码(因此源编码支持所需的字符串)。然后编译器将源编码转换为 UTF-8,而不是执行编码。当 Visual Studio 支持此功能时,您可能希望将源代码保存为“带签名的 UTF-8”。(同样,VS 依赖于签名来识别 UTF-8 源。)
在你有一个 UTF-8 字符串之后,假设 UTF-8 迭代器工作,你的示例代码应该产生正确的 11 个代码点,我认为输出文本应该如下所示:
104410861073108810991081321076107710851100
插入一些空格使其可读,您可以验证您是否获得了正确的值:
1044 1086 1073 1088 1099 1081 32 1076 1077 1085 1100
或者将其设为十六进制并添加 Unicode 前缀:
U+0414 U+043e U+0431 U+0440 U+044b U+0439 U+0020 U+0434 U+0435 U+043d U+044c
如果你真的想生成一个 UTF-8 编码的输出文件,那么无论如何你都不应该使用 utf-8 迭代器。
string s1 = "Добрый день";
std::cout << s1;
当输出重定向到文件时,该文件将包含 UTF-8 编码数据:
Добрый день
我不明白为什么您的实际输出当前包含一堆额外的空格,但看起来正在访问的实际数字是:
63 63 63 63 63 63 32 63 63 63 63
63 是 '?' 的 ASCII 码 32是空格的ASCII码;?????? ????
. 因此,您显然正在遭受 VC++ 将字符串文字转换为系统区域设置编码的痛苦。