2012-09-29 6 views
7

ANSI C (같은 é í ó ú)에서 문자를 악센트의 printf 방법 :나는 그런 <code>á é í ó ú</code> 일부 악센트 문자 <code>printf</code>에 노력

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

DEVC의 텍스트 편집기 ++ IDE 잘 그들을 표시 즉, 소스 코드가 정상적으로 보인다. 이외의 라이브러리가 필요하고 일반 printf의 변형이 필요할 것 같습니다.

Windows XP에서 실행되는 IDE Bloodshed DEVC를 사용하고 있습니다.

답변

3

Windows 콘솔은 일반적으로 문자 인코딩과 관련하여 심하게 손상된 것으로 간주됩니다. 예를 들어,이 문제에 관해서는 here을 읽을 수 있습니다.

문제는 Windows가 일반적으로 서유럽 또는 미국 Windows-1252라고 가정하는 ANSI 코드 페이지를 사용하지만 콘솔에서 OEM 가정 (동일한 가정하에 CP850)을 사용한다는 것입니다.

  • 이 그것을 쓰기 전에 CP850 텍스트를 변환 (CharToOem() 참조)

    당신은 몇 가지 옵션이 있습니다. 단점은 사용자가 출력을 파일 (> file.txt)로 재지향하고 예를 들어 파일을 여는 경우입니다. 메모장, 그는 틀린 그것을 볼 것이다.

  • 콘솔의 코드 페이지 변경 : TTF 콘솔 글꼴 (예 : Lucida Console)을 선택하고 chcp 1252 명령을 사용해야합니다.
  • UNICODE 텍스트 및 wprintf()을 사용하십시오. TTF 콘솔 글꼴이 필요합니다.
3

아마도 유니 코드를 사용하는 것이 가장 좋습니다.

여기

우선, 수동으로 콘솔 글꼴 "Consolas"또는 "루시다 콘솔"또는 중 트루 타입은 선택할 수있는 유니 코드 글꼴 ("래스터 글꼴"작동하지 않을 수 있습니다, 사람들은 때로 믿을 수를 설정하는 방법 ...입니다 유니 코드 글꼴, 당신이 관심있는 문자를 포함 할 수도 있음).

다음으로 SetConsoleOutputCP(CP_UTF8)을 사용하여 콘솔 코드 페이지를 65001 (UTF-8)로 설정하십시오.

WideCharToMultiByte(CP_UTF8, ...)을 사용하여 텍스트를 UTF-8 (아직 UTF-8이 아닌 경우)로 변환하십시오.

마지막으로 WriteConsoleA()을 호출하여 UTF-8 텍스트를 출력하십시오.

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; 
} 

시험이 기능에 따라 : 다음 초래한다

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

여기 당신을 위해 모든 일을 조금 기능이있어, 그것은 wprintf()의 "개선"변종이다 콘솔의 텍스트 :

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

인코딩을 알지 못합니다. IDE가 비 ASCII 문자를 .c /에 저장합니다.cpp 파일과 비 -ASCII 문자가 발생할 때 컴파일러에서 무엇을하는지 알 수 없습니다. 이 부분은 스스로 알아야합니다.

올바르게 인코딩 된 UTF-16 텍스트를 _wprintf()에 제공하거나 올바르게 인코딩 된 UTF-8 텍스트로 WriteConsoleA()을 호출하는 경우 모든 것이 작동합니다.

P. 콘솔 글꼴에 대한 일부 자세한 내용은 here을 참조하십시오.

+0

이 솔루션의 문제점은 * "수동으로 콘솔 글꼴을 [*] 선택할 수있는 True-Type 유니 코드 글꼴로 설정하는 것입니다. 최종 사용자에게 배포하는 것은 어려운 솔루션임을 설명합니다. – Clifford

+0

@Clifford 그리고 저는 그것이 Windows 문제라고 생각했습니다. –

0

Windows 콘솔 모드에서 사용되는 Windows-1252 ("ANSI"라고도 알려짐) 문자 집합은 GUI 응용 프로그램에서 사용되는 문자 집합과 동일하지 않습니다. 따라서 IDE 표현은 런타임 표현과 다릅니다.

당신은 예를 들면 빠른 - 및 - 더러운 솔루션입니다 :이 문제에

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

대부분의 솔루션은 어떤 식 으로든 광범위한 다중 언어 현지화가있다 필요 Windows 응용 프로그램에 대한 간단한 해결책 결함이 유니 코드를 사용하여 GUI 응용 프로그램으로 작성하십시오.

+0

나에게 준 답변 덕분에 --- Rodrego, Alexey 및 Clifford. 나는 정말로 조언을 고맙다. 제안을 시험해보고 주제를 둘러보기 위해 잠시 시간이 걸릴 것입니다. 그런 다음 포럼에서이 질문으로 돌아가서 내가 사용한 것과 말하거나 필요한 경우 더 많은 도움을 요청할 것입니다. 시안 – sean