Как мне ввести 4-байтовые символы UTF-8?
Я пишу небольшое приложение, которое мне нужно протестировать с символами utf-8 разного количества байтов.
Я могу ввести символы юникода для тестирования, которые хорошо закодированы в utf-8 с 1,2 и 3 байтами, выполнив, например:
string in = "pi = \u3a0";
Но как мне получить символ Unicode, который закодирован с 4 байтами? Я пытался:
string in = "aegan check mark = \u10102";
Который, насколько я понимаю, должен выводить. Но когда я распечатываю это, я получаю ᴶ0
Что мне не хватает?
РЕДАКТИРОВАТЬ:
Я получил его на работу, добавив ведущие нули:
string in = "\U00010102";
Жаль, что я думал об этом раньше:)
1 ответ
В паттерне есть более длинная форма побега \U
с последующими восемью цифрами, а не \u
следуют четыре цифры. Это также используется в Java и Python, среди прочего:
>>> '\xf0\x90\x84\x82'.decode("UTF-8")
u'\U00010102'
Однако, если вы используете строки байтов, почему бы просто не экранировать каждый байт, как описано выше, вместо того, чтобы полагаться на компилятор для преобразования escape в строку 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 (его внутреннее представление в юникоде) и искалечил escape в сообщении об ошибке...
При запуске программа печатает:
narrow: 2 utf8: 3 wide: 1
narrow: 2 utf8: 4 wide: 2
Обратите внимание, что байтовые строки UTF-8 и широкие строки верны, но компилятору не удалось преобразовать "\U00010102"
, давая байтовую строку "??"
неверный результат.