2012-09-29 24 views
7

Traté de printf con algunos caracteres acentuados como á é í ó ú:Cómo printf caracteres acentuados en ANSI C (como A E I O ú)

printf("my name is Seán\n");

El editor de texto en el DEVC++ IDE de ellos presenta unos - es decir, el código fuente se ve bien. Supongo que necesito una biblioteca que no sea stdio.h y tal vez alguna variante del printf normal.

Estoy usando IDE Bloodshed DEVC en Windows XP.

Respuesta

3

Consola de Windows generalmente se considera mal roto con respecto a las codificaciones de caracteres. Puede leer sobre este problema here, por ejemplo.

El problema es que Windows generalmente utiliza la página de códigos ANSI (que supone que está en Europa occidental o América Windows-1252), pero la consola usa la página de códigos OEM (CP850 bajo la misma suposición).

tiene varias opciones:

  • convertir el texto en CP850 antes de escribirlo (véase CharToOem()). El inconveniente es que si el usuario redirige la salida a un archivo (> file.txt) y abre el archivo con, p. Bloc de notas, lo verá mal.
  • Cambiar la página de códigos de la consola: debe seleccionar una fuente de consola TTF (Lucida Console, por ejemplo) y usar el comando chcp 1252.
  • Use el texto UNICODE y wprintf(): de todos modos, necesita la fuente de la consola TTF.
3

Quizás lo mejor es utilizar Unicode.

Así es como ...

En primer lugar, establecer manualmente su fuente de consola a "Consolas" o "Lucida Console" o el que sea True-Type fuente Unicode se puede elegir ("fuentes de trama" puede no funcionar, los aren las fuentes Unicode, aunque pueden incluir caracteres que le interesan).

A continuación, configure la página de códigos de la consola en 65001 (UTF-8) con SetConsoleOutputCP(CP_UTF8).

Luego convierta su texto a UTF-8 (si aún no está en UTF-8) usando WideCharToMultiByte(CP_UTF8, ...).

Finalmente, llame al WriteConsoleA() para enviar el texto UTF-8.

He aquí una pequeña función que hace todas estas cosas para usted, es una variante de "mejorado" de wprintf():

int _wprintf(const wchar_t* format, ...) 
{ 
    int r; 
    static int utf8ModeSet = 0; 
    static wchar_t* bufWchar = NULL; 
    static size_t bufWcharCount = 256; 
    static char* bufMchar = NULL; 
    static size_t bufMcharCount = 256; 
    va_list vl; 
    int mcharCount = 0; 

    if (utf8ModeSet == 0) 
    { 
    if (!SetConsoleOutputCP(CP_UTF8)) 
    { 
     DWORD err = GetLastError(); 
     fprintf(stderr, "SetConsoleOutputCP(CP_UTF8) failed with error 0x%X\n", err); 
     utf8ModeSet = -1; 
    } 
    else 
    { 
     utf8ModeSet = 1; 
    } 
    } 

    if (utf8ModeSet != 1) 
    { 
    va_start(vl, format); 
    r = vwprintf(format, vl); 
    va_end(vl); 
    return r; 
    } 

    if (bufWchar == NULL) 
    { 
    if ((bufWchar = malloc(bufWcharCount * sizeof(wchar_t))) == NULL) 
    { 
     return -1; 
    } 
    } 

    for (;;) 
    { 
    va_start(vl, format); 
    r = vswprintf(bufWchar, bufWcharCount, format, vl); 
    va_end(vl); 

    if (r < 0) 
    { 
     break; 
    } 

    if (r + 2 <= bufWcharCount) 
    { 
     break; 
    } 

    free(bufWchar); 
    if ((bufWchar = malloc(bufWcharCount * sizeof(wchar_t) * 2)) == NULL) 
    { 
     return -1; 
    } 
    bufWcharCount *= 2; 
    } 

    if (r > 0) 
    { 
    if (bufMchar == NULL) 
    { 
     if ((bufMchar = malloc(bufMcharCount)) == NULL) 
     { 
     return -1; 
     } 
    } 

    for (;;) 
    { 
     mcharCount = WideCharToMultiByte(CP_UTF8, 
             0, 
             bufWchar, 
             -1, 
             bufMchar, 
             bufMcharCount, 
             NULL, 
             NULL); 
     if (mcharCount > 0) 
     { 
     break; 
     } 

     if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) 
     { 
     return -1; 
     } 

     free(bufMchar); 
     if ((bufMchar = malloc(bufMcharCount * 2)) == NULL) 
     { 
     return -1; 
     } 
     bufMcharCount *= 2; 
    } 
    } 

    if (mcharCount > 1) 
    { 
    DWORD numberOfCharsWritten, consoleMode; 

    if (GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &consoleMode)) 
    { 
     fflush(stdout); 
     if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), 
         bufMchar, 
         mcharCount - 1, 
         &numberOfCharsWritten, 
         NULL)) 
     { 
     return -1; 
     } 
    } 
    else 
    { 
     if (fputs(bufMchar, stdout) == EOF) 
     { 
     return -1; 
     } 
    } 
    } 

    return r; 
} 

Después de las pruebas de esta función:

_wprintf(L"\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7" 
     L"\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF" 
     L"\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7" 
     L"\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF" 
     L"\n" 
     L"\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7" 
     L"\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF" 
     L"\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7" 
     L"\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF" 
     L"\n" 
     L"\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7" 
     L"\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF" 
     L"\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7" 
     L"\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF" 
     L"\n"); 

_wprintf(L"\x391\x392\x393\x394\x395\x396\x397" 
     L"\x398\x399\x39A\x39B\x39C\x39D\x39E\x39F" 
     L"\x3A0\x3A1\x3A2\x3A3\x3A4\x3A5\x3A6\x3A7" 
     L"\x3A8\x3A9\x3AA\x3AB\x3AC\x3AD\x3AE\x3AF\x3B0" 
     L"\n" 
     L"\x3B1\x3B2\x3B3\x3B4\x3B5\x3B6\x3B7" 
     L"\x3B8\x3B9\x3BA\x3BB\x3BC\x3BD\x3BE\x3BF" 
     L"\x3C0\x3C1\x3C2\x3C3\x3C4\x3C5\x3C6\x3C7" 
     L"\x3C8\x3C9\x3CA\x3CB\x3CC\x3CD\x3CE" 
     L"\n"); 

_wprintf(L"\x410\x411\x412\x413\x414\x415\x401\x416\x417" 
     L"\x418\x419\x41A\x41B\x41C\x41D\x41E\x41F" 
     L"\x420\x421\x422\x423\x424\x425\x426\x427" 
     L"\x428\x429\x42A\x42B\x42C\x42D\x42E\x42F" 
     L"\n" 
     L"\x430\x431\x432\x433\x434\x435\x451\x436\x437" 
     L"\x438\x439\x43A\x43B\x43C\x43D\x43E\x43F" 
     L"\x440\x441\x442\x443\x444\x445\x446\x447" 
     L"\x448\x449\x44A\x44B\x44C\x44D\x44E\x44F" 
     L"\n"); 

Y debe dar lugar a la siguiente texto en la consola:

 ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ 
ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß 
àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ 
ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩΪΫάέήίΰ 
αβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ 
АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ 
абвгдеёжзийклмнопрстуфхцчшщъыьэюя 

No conozco la codificación en el que su IDE almacena caracteres no ASCII en .c /.archivos cpp y no sé qué hace tu compilador cuando encuentra caracteres que no son ASCII. Esta parte debes averiguarlo tú mismo.

Siempre que suministre a _wprintf() texto UTF-16 codificado correctamente o llame al WriteConsoleA() con texto UTF-8 codificado correctamente, las cosas deberían funcionar.

P.S. Algunos detalles sangrientos sobre las fuentes de la consola se pueden encontrar here.

+0

El problema con esta solución es * * configurar manualmente la fuente de la consola [...] en cualquier tipo de letra True-Type Unicode que pueda elegir "*. Explicar que para un usuario final es una solución difícil de implementar. – Clifford

+0

@Clifford Y pensé que era un problema de Windows. –

0

El conjunto de caracteres Windows-1252 (también conocido como "ANSI") utilizado por el modo de consola de Windows no es el mismo que el utilizado por las aplicaciones de la GUI. Por lo tanto, la representación IDE difiere de la representación en tiempo de ejecución.

Una solución rápida y sucia, por su ejemplo es:

printf("my name is Se\xe9n\n"); 

mayoría de las soluciones a este problema son defectuosos de una manera u otra y la solución más simple para las aplicaciones de Windows que necesitan la instalación de localización multi-idioma es escríbalos como aplicaciones GUI usando Unicode.

+0

Gracias a todos los que me dieron respuestas --- Rodrego, Alexey y Clifford. Realmente aprecio el consejo. Me llevará un poco de tiempo probar las sugerencias y conocer el tema. Luego, volveré a esta pregunta en el foro para decir lo que usé, o pediré más ayuda si es necesario. Seán – sean

Cuestiones relacionadas