Como faço para entrada de 4 bytes caracteres UTF-8?
-
03-07-2019 - |
Pergunta
Eu estou escrevendo um pequeno aplicativo que eu preciso para testar com utf-8 caracteres de um número diferente de comprimentos de byte.
eu posso caracteres de entrada Unicode para teste que são codificados em utf-8 com 1,2 e 3 bytes muito bem, fazendo, por exemplo:
string in = "pi = \u3a0";
Mas como faço para obter um caractere Unicode que está codificado com 4 bytes? Eu tentei:
string in = "aegan check mark = \u10102";
que, tanto quanto eu entendo deve ser outputting. Mas quando eu imprimir isso eu recebo ?0
O que eu estou ausente?
EDIT:
Eu tenho que trabalhar, adicionando zeros à esquerda:
string in = "\U00010102";
desejo que eu tinha pensado nisso mais cedo:)
Solução
Há uma forma mais longa de fuga na \U
padrão seguido por oito dígitos, em vez de \u
seguido por quatro dígitos. Isso também é usado em Java e Python, entre outros:
>>> '\xf0\x90\x84\x82'.decode("UTF-8")
u'\U00010102'
No entanto, se você estiver usando cadeias de bytes, porque não basta escapar cada byte como acima, em vez de depender o compilador para converter a fuga para uma string UTF-8? Este parece ser mais portátil, bem como - se eu compilar o seguinte programa:
#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;
}
No win32 com meu opções atual cl dá:
warning C4566: character represented by universal-character-name '\UD800DD02' cannot be represented in the current code page (932)
O compilador tenta converter todos os escapes Unicode em strings de bytes para a página de código do sistema, que UTF-8 ao contrário não pode representar todos os caracteres Unicode. Estranhamente tem entendido que \U00010102
é \uD800\uDD02
em UTF-16 (a sua representação interna unicode) e mutilado a fuga na mensagem de erro ...
Quando executado, o programa imprime:
narrow: 2 utf8: 3 wide: 1
narrow: 2 utf8: 4 wide: 2
Note que as UTF-8 bytestrings e as grandes cadeias estão corretas, mas o compilador não conseguiu "\U00010102"
convertido, dando a "??"
cadeia de bytes, um resultado incorreto.