2012-09-29 29 views
7

Próbowałem printf z niektórych akcentowane znaki takie jak á é í ó ú:Jak printf znaki akcentowane w ANSI C (jak A E I O U)

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

Edytor tekstu w DEVC++ IDE wyświetli je w porządku - tzn. kod źródłowy wygląda dobrze. Chyba potrzebuję biblioteki innej niż stdio.h i może jakiś wariant normalnego printf.

Używam IDE Bloodshed DEVC działającego pod Windows XP.

Odpowiedz

3

Konsola systemu Windows jest ogólnie uważana za poważnie uszkodzoną w odniesieniu do kodowania znaków. Możesz przeczytać na ten temat na przykład here.

Problem polega na tym, że system Windows zazwyczaj używa strony kodowej ANSI (zakładając, że znajduje się w Europie Zachodniej lub Ameryce Windows-1252), ale konsola korzysta ze strony kodowej OEM (CP850 pod tym samym założeniem).

Masz kilka opcji:

  • przekonwertować tekst do CP850 przed zapisaniem go (patrz CharToOem()). Wadą jest to, że jeśli użytkownik przekierowuje dane wyjściowe do pliku (> file.txt) i otwiera plik np. Notatnik, zobaczy to źle.
  • Zmiana strony kodowej konsoli: Musisz wybrać czcionkę konsoli TTF (na przykład Lucida Console) i użyć polecenia chcp 1252.
  • Użyj tekstu w standardzie UNICODE i wprintf(): Tak czy inaczej potrzebujesz czcionki konsoli TTF.
3

Być może najlepiej jest użyć Unicode.

Oto jak ...

Najpierw ręcznie ustawić czcionkę konsoli „Consolas” lub „Lucida Console” lub cokolwiek True-typ czcionki Unicode można wybrać („czcionki rastrowe” może nie działać, te aren • Czcionki Unicode, chociaż mogą zawierać znaki, które Cię interesują).

Następnie ustaw stronę kodową konsoli na 65001 (UTF-8) na SetConsoleOutputCP(CP_UTF8).

Następnie przekonwertuj swój tekst na kodowanie UTF-8 (jeśli nie jest jeszcze w UTF-8), używając WideCharToMultiByte(CP_UTF8, ...).

Na koniec zadzwoń pod numer WriteConsoleA(), aby wyświetlić tekst UTF-8.

Oto mały funkcja, która czyni wszystkie te rzeczy dla ciebie, to jest „ulepszone” wariant 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; 
} 

następujące testy tej funkcji:

_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"); 

i powinny powodować następujące tekst w konsoli:

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

Nie znam kodowania w którym twój IDE przechowuje znaki spoza ASCII w .c /.Pliki cpp i nie wiem, co robi twój kompilator, gdy napotkają znaki spoza ASCII. W tej części powinieneś sam się dowiedzieć.

Dopóki dostarczasz do _wprintf() poprawnie zakodowany tekst UTF-16 lub zadzwoń pod WriteConsoleA() z poprawnie zakodowanym tekstem UTF-8, rzeczy powinny działać.

P.S. Niektóre szczegóły dotyczące czcionek konsoli można znaleźć here.

+0

Problem z tym rozwiązaniem polega na tym, że * "ręcznie ustawił czcionkę konsoli na [...] dowolną czcionkę Unicode True-Type, którą można wybrać" *. Wytłumaczenie tego użytkownikowi końcowemu sprawia, że ​​jest to trudne rozwiązanie. – Clifford

+0

@ Clifford I pomyślałem, że to problem Windows. –

0

Zestaw znaków Windows-1252 (znany również jako "ANSI") używany w trybie konsoli systemu Windows to nie to samo, co aplikacje GUI. Dlatego reprezentacja IDE różni się od reprezentacji środowiska wykonawczego.

Szybkie i-brudny rozwiązanie dla przykładu jest:

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

Większość rozwiązań tego problemu są wadliwe taki czy inny sposób i najprostsze rozwiązanie dla aplikacji Windows, które wymagają rozległe lokalizacja wielu języków jest zapisz je jako aplikacje GUI, używając Unicode.

+0

Dziękuję wszystkim, którzy udzielili mi odpowiedzi --- Rodrego, Alexey i Clifford. Naprawdę doceniam tę radę. Zajmie mi to trochę czasu, aby wypróbować sugestie i porozmawiać na ten temat. Następnie powrócę do tego pytania na forum, aby powiedzieć, którego użyłem - lub w razie potrzeby poprosić o pomoc. Seán – sean