Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ UTF-8字符串迭代器_C++_String_Unicode_Utf 8_Iterator - Fatal编程技术网

C++ UTF-8字符串迭代器

C++ UTF-8字符串迭代器,c++,string,unicode,utf-8,iterator,C++,String,Unicode,Utf 8,Iterator,我正在尝试编写一个支持Unicode的跨平台应用程序。我正在使用库UTF8-C++(),但在遍历字符串时遇到问题: string s1 = "Добрый день"; utf8::iterator<string::iterator> iter(s1.begin(), s1.begin(), s1.end()); for(int i = 0; i < utf8::distance(s1.begin(), s1.end()); i++, ++iter) { cout &

我正在尝试编写一个支持Unicode的跨平台应用程序。我正在使用库UTF8-C++(),但在遍历字符串时遇到问题:

string s1 = "Добрый день";
utf8::iterator<string::iterator> iter(s1.begin(), s1.begin(), s1.end());

for(int i = 0; i < utf8::distance(s1.begin(), s1.end()); i++, ++iter)
{
    cout << (*iter);
}

如何使
s1
的内容正确显示在文件中?

答案已更新。使用wstring(我认为最好的VS2010)存储UTF16字符串,转换为UTF8,然后输出

当我在UTF8兼容编辑器(Scite)中查看时,这对我很有用

std::wstring s1=L“ббыббббб”;
std::向量UTF8;
utf8::utf16to8(s1.begin()、s1.end()、std::back_插入器(utf8));
用于(自动It=UTF8.begin();Itstd::cout您需要确保使用正确的数据初始化字符串,然后确保迭代器生成正确的值

您使用的是VS2010,因此字符串的文字有点问题。C++实现有一个“执行字符集”,它们将字符和字符串文字转换为“源字符集”。VisualStudio不支持UTF-8作为执行字符集,因此不会故意产生UTF-8编码的斯特林。g文字

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字符串文字,只获取包含正确数据的宽字符串,然后在运行时将其转换为UTF-8


编辑:较新版本的Visual Studio现在确实有办法获取UTF-8字符串文字。Visual Studio 2015现在支持C++11的UTF-8字符串文字。在Visual Studio 2015 Update 2中,您还可以使用编译器标志


欺骗编译器 如果将源代码保存为“不带签名的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;

我不明白为什么您的实际输出当前包含一堆额外的空格,但看起来正在访问的实际数字是:

63 63 63 63 63 63 32 63 63 63 63

63是“?”的ascii码,32是一个空格的ascii码;
??
。因此,很明显,您正在遭受VC++将字符串文字转换为系统区域设置编码的痛苦。

输出中的空格来自何处?源文件采用何种编码?您使用的是哪个版本的库?您确实不知道I don’我不想在内部使用UTF-8。它是一种非常棒的存储和传输格式,但在代码中使用它确实很痛苦。请将其转换为UTF-32(Unix)或UTF-16(中继UCS-2)(Win)并使用固定大小的质量。@LokiAstari和所有其他评论员-请阅读:。是的,您确实希望在内存中使用utf8,并且忘记终身的任何编码转换……根据我的经验,多个代码单元是否也构成一个代码点通常是无关紧要的。或者我可以根据代码单元工作(当规范化不是问题时;复制、连接、简单搜索等)或者我需要知道多个代码点必须被视为一个实体(不仅仅用于显示;用于光标移动、正则表达式、拆分等)。固定宽度编码没有任何价值。Unicode字符基本上是可变长度的。“在进行字符串操作时,固定宽度格式实际上是唯一的方法"-不完全正确。请参见utf8everywhere的常见问题18。您将看到固定宽度实际上不太好,变量也不太坏。当我按照您的指示更改程序时,我得到了以下输出:
2062496475326
。此外,我得到了一个警告:
警告C4244:“参数”:从“wcha”转换而来r_t'到'utf8::uint8_t',可能会丢失数据
。宽字符串永远不会存储在utf8中,因此使用utf8迭代器对其进行迭代没有多大意义。抱歉,也许我误解了这个问题-您希望它输出什么?实际的字符串?@MooingDuck是的,我遇到了错误的问题-因为他们试图存储将宽字符串转换为普通字符串并获取“?”。然后您不希望使用UTF8迭代器,这会获取字符的代码点,而不是通常可显示的内容。UTF8库更适合于将UTF8转换为普通字符串或宽字符串,然后将其显示为n
Добрый день
63 63 63 63 63 63 32 63 63 63 63