如何输入4字节的UTF-8字符?

5
我正在编写一个小应用程序,需要测试不同字节长度的 utf-8 字符。
我可以输入经过 utf-8 编码的 1、2 和 3 字节的 Unicode 字符来进行测试,例如:
string in = "pi = \u3a0";

但是我该如何获得一个用4个字节编码的 Unicode 字符?我尝试过:
string in = "aegan check mark = \u10102";

“根据我的理解,应该输出。但当我打印出来时,得到的是ᴶ0。

我错过了什么吗?

编辑:

我通过添加前导零使其工作:


string in = "\U00010102";

希望我早点想到那个 :)

你使用的是什么打印方法?它是否支持Unicode? - luke
我只是使用Terminal.app中的cout,它与Unicode很好地配合工作。 - Cactuar
哈!我在撰写答案时没有看到那个编辑,应该更早地回复。 - gz.
不管怎样,还是谢谢您的回答,我得到了一些很好的建议 :) - Cactuar
1个回答

6

在模式\U后面跟着八个数字,而不是\u后面跟着四个数字,有一种更长的转义形式。这种形式也被用于Java和Python等其他语言中:

>>> '\xf0\x90\x84\x82'.decode("UTF-8")
u'\U00010102'

然而,如果您正在使用字节字符串,为什么不像上面那样转义每个字节,而不是依赖编译器将转义转换为UTF-8字符串呢?这似乎也更具可移植性 - 如果我编译以下程序:

#include <iostream>
#include <string>

int main()
{
    std::cout << "narrow: " << std::string("\uFF0E").length() <<
        " utf8: " << std::string("\xEF\xBC\x8E").length() <<
        " wide: " << std::wstring(L"\uFF0E").length() << std::endl;

    std::cout << "narrow: " << std::string("\U00010102").length() <<
        " utf8: " << std::string("\xF0\x90\x84\x82").length() <<
        " wide: " << std::wstring(L"\U00010102").length() << std::endl;
}

在win32平台下,使用当前选项时,cl会给出以下警告信息: warning C4566: character represented by universal-character-name '\UD800DD02' cannot be represented in the current code page (932) 编译器试图将字节字符串中的所有unicode转义序列转换为系统代码页,而与UTF-8不同,它不能表示所有的unicode字符。奇怪的是,它已经理解了\U00010102在UTF-16(其内部unicode表示)中是\uD800\uDD02,并且在错误消息中损坏了转义序列。
运行程序后,会打印出:
narrow: 2 utf8: 3 wide: 1
narrow: 2 utf8: 4 wide: 2

请注意,UTF-8字节串和宽字符串是正确的,但编译器无法转换"\U00010102",导致字节串"??",得到了错误的结果。

与你的第二句话相反,在Java中不使用\Uxxxxxxxx:http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.3 - T.J. Crowder
不使用十六进制转义手动编码的原因是需要手动进行编码并且会使代码变得模糊。最好使用Unicode转义序列,并告诉编译器使用UTF-8作为执行字符集。如果您的编译器尚未支持,请联系您的编译器供应商。 - bames53

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接