C++中的Unicode字符串索引

Bah*_*ami 5 c++ string unicode

我来自python,你可以使用'string [10]'按顺序访问一个字符.如果字符串是用Unicode编码的,它会给我预期的结果.但是当我在C++中对字符串使用索引时,只要字符是ASCII就可以工作,但是当我在字符串中使用Unicode字符并使用索引时,在输出中我将得到像/ 201这样的八进制表示.例如:

string ramp = "Ðð??ŠšÝýÞþŽž";
cout << ramp << "\n";    
cout << ramp[5] << "\n";
Run Code Online (Sandbox Code Playgroud)

输出:

Ðð??ŠšÝýÞþŽž
/201
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况,如何在字符串表示中访问该字符,或者如何将八进制表示转换为实际字符?

Dev*_*lar 11

标准C++没有配备正确的Unicode处理,给你的问题就像你观察到的那样.

这里的问题是C++ 以一个舒适的边距超前于 Unicode.这意味着,即使该字符串文字你将在一个被解释实现定义的方式,因为这些字符不在基本源字符集定义(其是,基本上,ASCII-7字符减去@,$和反引号).

C++ 98根本没有提到Unicode.它提到wchar_twstring基于它,指定wchar_t能够"表示当前语言环境中的任何字符".但那造成了更多的伤害而不是好的......

微软定义wchar_t为16位,这足以为Unicode码点在那个时候.但是,从那时起,Unicode已经扩展到超出16位范围......并且Windows 16位wchar_t不再"宽",因为你需要其中两个代表BMP以外的字符- 而且微软的文档是众所周知的关于wchar_tUTF-16(具有代理对的多字节编码)或UCS-2(宽编码而不支持BMP之外的字符)的含义不明确.

就在这时,一个Linux wchar_t是32位,这足够宽UTF-32 ...

C++ 11对该主题进行了重大改进,添加char16_tchar32_t包括其相关string变体以消除歧义,但仍然没有完全配备Unicode操作.

就像一个例子,尝试将德语"Fuß"转换为大写,你会看到我的意思.(单个字母'ß'需要扩展为'SS',标准函数 - 处理一个字符,一次一个字符 - 不能这样做.)

但是,有帮助.在Unicode的国际组件(ICU)完全有能力处理Unicode在C++中.至于在源代码中指定特殊字符,您将必须使用u8"",u""U""分别使用八进制/十六进制转义或依赖于编译器实现来强制解析字符串文字为UTF-8,UTF-16和UTF-32适当地处理非ASCII-7编码.

即使这样你也会得到一个整数值std::cout << ramp[5],因为对于C++来说,一个字符只是一个具有语义含义的整数.ICU 为类ustream.h提供了operator<<重载icu::UnicodeString,但ramp[5]它只是一个16位无符号整数(1),如果它们unsigned short突然被解释为字符,人们会看着你.你需要C-API u_fputs()/u_printf()/ u_fprintf()函数.

#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <unicode/ustdio.h>

#include <iostream>

int main()
{
    // make sure your source file is UTF-8 encoded...
    icu::UnicodeString ramp( icu::UnicodeString::fromUTF8( "Ðð??ŠšÝýÞþŽž" ) );
    std::cout << ramp << "\n";
    std::cout << ramp[5] << "\n";
    u_printf( "%C\n", ramp[5] );
}
Run Code Online (Sandbox Code Playgroud)

编译g++ -std=c++11 testme.cpp -licuio -licuuc.

Ðð??ŠšÝýÞþŽž
353
š
Run Code Online (Sandbox Code Playgroud)

(1)ICU在内部使用UTF-16,并UnicodeString::operator[]返回代码单元,而不是代码,因此您可能最终得到代理对的一半.查找API文档以获取索引unicode字符串的各种其他方法.


Pup*_*ppy 5

C++没有有用的本机Unicode支持.你几乎肯定需要一个像ICU这样的外部库.