Impresión de cadenas de UTF-8 con printf – amplia frente literales de cadena multibyte

En declaraciones como estas, en donde ambos se introducen en el código fuente con la misma codificación (UTF-8) y la configuración regional está configurado correctamente, hay alguna diferencia práctica entre ellos?

printf("ο Δικαιοπολις εν αγρω εστιν\n");
printf("%ls", L"ο Δικαιοπολις εν αγρω εστιν\n");

Y, por consiguiente, no hay ninguna razón para preferir uno sobre el otro, cuando se hace la salida? Me imagino que el segundo realiza una feria poco peor, pero tiene la ventaja (o desventaja) de más de un multibyte literal?

EDIT: no Hay problemas con estas cadenas de impresión. Pero yo no estoy usando el ancho de las funciones de cadena, porque quiero ser capaz de utilizar printf etc. así. Así que la pregunta es ¿son estas formas de impresión diferente (dada la situación descrita anteriormente), y si es así, ¿el segundo tiene alguna ventaja?

EDIT2: a raíz de los comentarios de abajo, ahora sé que este programa funciona, que yo pensaba que no era posible:

int main()
{
    setlocale(LC_ALL, "");
    wprintf(L"ο Δικαιοπολις εν αγρω εστιν\n");  //wide output
    freopen(NULL, "w", stdout);                 //lets me switch
    printf("ο Δικαιοπολις εν αγρω εστιν\n");    //byte output
}

EDIT3: he hecho un poco de investigación adicional por mirar lo que está pasando con los dos tipos. Tomar una simplificación de la cadena:

wchar_t *wides = L"£100 π";
char *mbs = "£100 π";

El compilador genera código diferente. La amplia cadena es:

.string "\243"
.string ""
.string ""
.string "1"
.string ""
.string ""
.string "0"
.string ""
.string ""
.string "0"
.string ""
.string ""
.string " "
.string ""
.string ""
.string "\300\003"
.string ""
.string ""
.string ""
.string ""
.string ""

Mientras que la segunda es:

.string "\302\243100 \317\200"

Y mirando las codificaciones Unicode, la segunda es simple UTF-8. La amplia representación de caracteres con codificación UTF-32. Me doy cuenta de que esto va a ser dependiente de la implementación.

Así que tal vez el carácter de la representación de los literales es más portátil? Mi sistema no imprime UTF-16/UTF-32 codificaciones directamente, por lo que se convierte automáticamente en UTF-8 para la salida.

  • Usted dijo que ambos ejemplos se escriben con UTF-8. En la segunda línea de ejemplo, si el texto es en realidad UTF-8 en lugar de una amplia codificación, entonces usted probablemente no debería tener el L prefijo, y por lo tanto usted acaba de utilizar %s en lugar de %ls. O todavía estoy a la incomprensión de la pregunta.
  • ambas cadenas en el código fuente son UTF-8, sí. Pero un literal de cadena es siempre multibyte — «Un carácter literal de cadena es una secuencia de cero o más caracteres multibyte encerrado en comillas dobles, como en «xyz». Una amplia cadena literal es el mismo, excepto precedidos por la letra L.» de la norma.
  • AFAIR, los caracteres que no en la Fuente Básica de Conjunto de Caracteres (que es un subconjunto de US-ASCII-7) invocar la aplicación definida por el comportamiento, es decir, todo lo discutido aquí es, efectivamente, dependiendo del compilador utilizado. Si realmente quieres jugar a lo seguro (y portátil), usted tendría que recurrir a \u… y \U…
  • Bien podría ser en el área de aplicación. Lo que estoy tratando de hacer es cambiar a una amplia representación de los personajes todo el tiempo, pero se adhieren a la regular stdio funciones para la salida, para no romper la compatibilidad con todas las cosas que se espera de ellos para trabajar. Estoy realmente sólo me preguntaba si yo debe seguir con multibyte literales solo (como arriba) o si hay una razón para el uso de ancho de literales. Es difícil de explicar, y no estoy haciendo un muy buen trabajo!
  • utf8everywhere.org bastante convence de que el uso de L»» debe ser desalentado, especialmente en la plataforma Windows.
InformationsquelleAutor teppic | 2013-03-20

1 Kommentar

  1. 27
    printf("ο Δικαιοπολις εν αγρω εστιν\n");

    imprime la cadena literal (const char*, caracteres especiales son representados como multibyte caracteres). Aunque usted puede ver la salida correcta, hay otros problemas que podría estar tratando con el mismo tiempo de trabajo con caracteres no ASCII como estos. Por ejemplo:

    char str[] = "αγρω";
    printf("%d %d\n", sizeof(str), strlen(str));

    salidas 9 8, ya que cada uno de estos caracteres especiales está representada por 2 chars.

    Mientras que el uso de la L prefijo tiene el literal que consta de caracteres anchos (const wchar_t*) y %ls especificador de formato hace que estos caracteres anchos a ser convertidos a caracteres multibyte (UTF-8). Tenga en cuenta que en este caso, la configuración regional debe ser configurado correctamente de lo contrario, esta conversión puede llevar a que el resultado no es válido:

    #include <stdio.h>
    #include <wchar.h>
    #include <locale.h>
    
    int main(void)
    {
        setlocale(LC_ALL, "");
        printf("%ls", L"ο Δικαιοπολις εν αγρω εστιν");
        return 0;
    }

    pero mientras que algunas cosas podrían complicarse cuando se trabaja con distintos caracteres, las cosas podrían obtener mucho más simple y más sencillo. Por ejemplo:

    wchar_t str[] = L"αγρω";
    printf("%d %d", sizeof(str) / sizeof(wchar_t), wcslen(str));

    de salida será de 5 4 como sería natural esperar.

    Una vez que usted decide trabajar con muchas cadenas, wprintf se puede utilizar para imprimir caracteres anchos directamente. También vale la pena señalar aquí que en el caso de la consola de Windows, el modo de traducción de la stdout se debe establecer de forma explícita a uno de los Unicode modos llamando _setmode:

    #include <stdio.h>
    #include <wchar.h>
    
    #include <io.h>
    #include <fcntl.h>
    #ifndef _O_U16TEXT
      #define _O_U16TEXT 0x20000
    #endif
    
    int main()
    {
        _setmode(_fileno(stdout), _O_U16TEXT);
        wprintf(L"%s\n", L"ο Δικαιοπολις εν αγρω εστιν");
        return 0;
    }
    • Ese soy yo 🙂 wprintf convierte a multibyte demasiado, pero estoy interesado en las funciones estándar.
    • Ver mi respuesta ahora. Debe ser finalmente más satisfactorio, supongo 🙂
    • UTF-16 es no «ancho», y es lástima que un poco de mito es todavía alrededor. Hay más de 2^16 caracteres Unicode y UTF-16 codifica con un variable ancho de uno o dos de 16 bits unidades de código. Si quieres «amplia», usted tiene que recurrir a UTF-32. No vamos a entrar en esa trampa de pensar que n bit debe ser suficiente para todo el mundo, nuevo.
    • He quitado el confuso «UTF-16».
    • Gracias. Estoy trabajando fuertemente Unicode cosas relacionadas con profesionalidad, y es que es tan triste ver como mucho la mitad del horno conocimiento sobre el tema es de alrededor de. UTF-16 es un perfecto ejemplo: de manera Efectiva una codificación multibyte, con la inserción de cero bytes. Es increíble la cantidad de «soporte Unicode» el software puede estar hecho a vomitar con un poco de griego antiguo, algunos extendida CJK o uno o dos jeroglíficos. Por no hablar de la combinación de caracteres y otras sutilezas. 😉
    • Estoy impresionado reconocido que, como el griego antiguo (a menos que sea coincidencia) 🙂
    • Estoy de acuerdo con las cosas que dijo. Me encontré con problemas con funciones como strlen hace un tiempo antes de que yo sabía acerca de los distintos personajes. Para cualquier cosa interna que haría uso de la amplia cadena de funciones, pero en el momento de utilizar una amplia cadena de la función de salida en stdout, usted no puede usar ninguna de los regulares de nuevo, es por eso que no voy a usar wprintf. Espero que la respuesta es esencialmente no hay diferencia, siempre y cuando la configuración regional está establecida y no es necesario para procesar el literal de alguna manera.
    • Coincidencia, lo admito. Me acaba de nombrar a un par de alfabetos fuera del rango de 16 bits. Como para stdout ser «contaminados» por el ancho de salida, se aconseja que usted puede restablecer la amplia orientación a través de fwide( stdout, -1 ).
    • sólo puede ser utilizado para establecer la secuencia inicialmente, no se puede cambiar una vez orientado, por desgracia.
    • Dang… Nota al pie de página 287, echaba de menos eso. Bien, usted todavía puede utilizar freopen… a pesar de que parece un poco torpe.
    • no se puede hacer con stdout como lo que yo sé.
    • Así que me perdí nota de pie de página 287 del estándar C99, y te perdiste nota de pie de página 232 de la misma. 😉 Cito: «El principal uso de la función freopen es cambiar el archivo asociado con un estándar de secuencia de texto (stderr, stdin, o stdout), como los identificadores no necesita ser modificables lvalues a que el valor devuelto por la función fopen puede ser asignado.» Con algo como freopen( "test", "r", stdin ) usted obtener stdin para leer de un archivo, lo cual es útil para, por ejemplo, las pruebas de stdin-funciones de lectura.
    • eso es para la reorientación de los descriptores de archivo a un nombre de archivo, aunque? Se llamaría algo así como freopen("/tmp/output", "w", stdout); (quiero mantener stdout como stdout)
    • nombre de archivo es un puntero null, la función freopen los intentos de cambiar el modo de la secuencia para que el especificado por el modo de, como si el nombre de archivo asociado actualmente con el arroyo se había utilizado. es la aplicación definida por el cual los cambios de modo está permitido (si los hubiera), y bajo qué circunstancias.» I. e., aplicación definido, pero vale la pena intentarlo.
    • Estoy seguro de que he intentado eso, pero voy a intentarlo ahora – gracias. Si no funciona voy a publicar una nueva pregunta específicamente sobre este tema. Yo, obviamente, no funciona! En Linux, que es.
    • Ni el programa de obras. Qué gran respuesta..

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Recent Articles

Python «set» con duplicados/elementos repetidos

Hay una forma estándar de representar un "conjunto" que puede contener elementos duplicados. Como yo lo entiendo, un conjunto tiene exactamente un cero o...

Python: generador de expresión vs rendimiento

En Python, ¿hay alguna diferencia entre la creación de un generador de objetos a través de un generador de expresión versus el uso de...

Cómo exportar/importar la Masilla lista de sesiones?

Hay una manera de hacer esto? O tengo que tomar manualmente cada archivo de Registro? InformationsquelleAutor s.webbandit | 2012-10-23

no distingue mayúsculas de minúsculas coincidentes en xpath?

Por ejemplo, para el xml a continuación <CATALOG> <CD title="Empire Burlesque"/> <CD title="empire burlesque"/> <CD...