Как мне ввести 4-байтовые символы UTF-8? - PullRequest
4 голосов
/ 15 октября 2008

Я пишу небольшое приложение, которое мне нужно протестировать с символами utf-8 разного количества байтов.

Я могу ввести символы юникода для проверки, которые хорошо зашифрованы в utf-8 с 1,2 и 3 байтами, например:

string in = "pi = \u3a0";

Но как мне получить символ Unicode, который закодирован 4 байтами? Я пробовал:

string in = "aegan check mark = \u10102";

Который, насколько я понимаю, должен выводить. Но когда я распечатываю это, я получаю ᴶ0

Чего мне не хватает?

EDIT:

Я получил его на работу, добавив лидирующие нули:

string in = "\U00010102";

Жаль, что я думал об этом раньше:)

1 Ответ

5 голосов
/ 15 октября 2008

В шаблоне \U есть более длинная форма escape, за которой следуют восемь цифр, а не \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)

Компилятор пытается преобразовать все экранированные символы Юникода в байтовых строках в системную кодовую страницу, которая в отличие от UTF-8 не может представлять все символы Юникода. Как ни странно, он понял, что \U00010102 равен \uD800\uDD02 в UTF-16 (его внутреннее представление в кодировке Unicode), и исказил escape в сообщении об ошибке ...

При запуске программа печатает:

narrow: 2 utf8: 3 wide: 1
narrow: 2 utf8: 4 wide: 2

Обратите внимание, что строки байтов UTF-8 и широкие строки верны, но компилятору не удалось преобразовать "\U00010102", что дает строку байтов "??", неверный результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...