Pregunta

Estoy escribiendo una pequeña aplicación que necesito probar con los caracteres utf-8 de diferente número de longitudes de bytes.

Puedo ingresar caracteres Unicode para probar que están codificados en utf-8 con 1,2 y 3 bytes muy bien al hacer, por ejemplo:

string in = "pi = \u3a0";

¿Pero cómo obtengo un carácter Unicode que está codificado con 4 bytes? Lo he intentado:

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

Que, por lo que entiendo, debería estar dando salida. Pero cuando imprimo eso, obtengo & # 7478; 0

¿Qué me estoy perdiendo?

EDIT:

Lo hice funcionar agregando ceros a la izquierda:

string in = "\U00010102";

Ojalá hubiera pensado en eso antes :)

¿Fue útil?

Solución

Hay una forma de escape más larga en el patrón \ U seguido de ocho dígitos, en lugar de \ u seguido de cuatro dígitos. Esto también se usa en Java y Python, entre otros:

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

Sin embargo, si está utilizando cadenas de bytes, ¿por qué no simplemente escapa cada byte como arriba, en lugar de confiar en el compilador para convertir el escape en una cadena UTF-8? Esto también parece ser más portátil, si compilo el siguiente 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;
}

En win32 con mis opciones actuales cl da:

warning C4566: el carácter representado por el nombre de carácter universal '\ UD800DD02' no se puede representar en la página de códigos actual (932)

El compilador intenta convertir todos los escapes de Unicode en cadenas de bytes a la página de códigos del sistema, que a diferencia de UTF-8 no puede representar todos los caracteres de Unicode. Curiosamente, ha entendido que \ U00010102 es \ uD800 \ uDD02 en UTF-16 (su representación interna de Unicode) y modificó el escape en el mensaje de error ...

Cuando se ejecuta, el programa se imprime:

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

Tenga en cuenta que las cadenas de caracteres UTF-8 y las cadenas anchas son correctas, pero el compilador no pudo convertir " \ U00010102 " , dando la cadena de bytes " ?? " , un resultado incorrecto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top