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_t并wstring基于它,指定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_t并char32_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字符串的各种其他方法.
| 归档时间: |
|
| 查看次数: |
2232 次 |
| 最近记录: |