2014-05-18 3 views
2

약간의 측면 프로젝트를 위해서 나는 지역화 된 Windows 'CMD에서 텍스트의 문자열을 출력해야하며, 일부 문자열은 프로그램의 인수에서 읽혀집니다. 문제를 단순화하기 위해 간단한 에코 프로그램을 데모로 사용합니다.명령 줄의 로켈에 텍스트를 표시하는 방법은 무엇입니까?

C 언어로 니펫을 고려하십시오 :

#include <stdio.h> 

int main(int argc, char **argv) { 
    // Display the first argument through the standard output: 
    if (argc > 1) 
     puts(argv[1]); 
    return 0; 
} 

이 두 실행의 출력은 다음과 같습니다

$ test.exe Wilhelm 
$ Wilhelm 

$ test.exe Röntgen 
$ R÷ntgen 

당신이 ö 같은 일이 ASCII에서 될 것이라고 볼 이미 수는없는 것 올바르게 표시되어야합니다.

if (argv[1][1] == 'ö') 
    puts("It is."); 

문장이 표시되는 프로그램이 제대로 문자를 받고, 그래서 : 당신이 그런 짓을하지만 그들은 제대로 예를 들어, 프로그램에 인식하고 있습니다. 그래서

그래도, OK, wchar_t 일이 필요 될 수 있으므로 적절한 변경하고 당신은 얻을 것 _UNICODEUNICODE 정의 :

#include <stdio.h> 

int wmain(int argc, wchar_t **argv) { 
    // Display the first argument through the standard output: 
    if (argc > 1) 
     _putws(argv[1]); 
    return 0; 
} 

아직도이 테스트 프로그램의 출력이 동일한 것 .

주위를 둘러보고 문서를 읽으면서 로케일을 예를 들어 영어로 설정하는 해결 방법을 발견했습니다. 그러면 텍스트가 올바르게 표시됩니다. 나는이와 함께 종료 (wchar_t들없이) 첫 번째 버전을 수정 :

#include <stdio.h> 
#include <locale.h> 

int main(int argc, char **argv) { 
    // Get the previous locale and change to English: 
    char *old_locale = setlocale(LC_ALL, NULL); 
    setlocale(LC_ALL, "English"); 
    // Display the first argument through the standard output: 
    if (argc > 1) 
     puts(argv[1]); 
    // Restore locale: 
    setlocale(LC_ALL, old_locale); 
    return 0; 
} 

("en-US"이는 MinGW-W64에서 작동하지 않는 동안 및 Microsoft Visual C++와 "English" 작품) 이제

프로그램은 문자가 실제로 명령 행 창에 올바르게 표시되도록 인쇄 할 수 있습니다.

문제는 영어로 설정하는 것이 스페인어 시스템이나 일본어로하는 것이 가장 좋은 방법이 아니라는 것입니다. 그래서 어떤 방식 으로든 시스템에서 로케일을 얻는 방법에 대해 생각했습니다. 나는 _locale_t을 반환 _get_current_locale라는 함수를 찾았지만 내가 전혀 원하는 것을 할 수 없습니다 같다 : (A char *입니다)

_locale_t_variable->locinfo->lc_category[LC_ALL].localeNULL 것 같다.

문제는 명령 줄의 로캘에서 텍스트를 가져 오거나 표시하는 방법입니다. Windows의 CMD에서 현지화 된 텍스트를 처리하는 올바른 방법은 무엇입니까 (반드시 유니 코드가 아님)?

+0

귀하의 질문은 장점이있다. 'echo' 프로그램은 Win7 컴퓨터에서'Röntgen'을 정확하게 echo 할 수 있습니다; 그래서 당신이하려고하는 것은 분명히 가능합니다. –

+0

그러나 다시,'echo'는 MS cmd 쉘 내부에 있습니다. 셸에서 '특수'처리를 할 수 있습니다. –

+0

기본적으로 명령 프롬프트는 OEM 코드 페이지를 사용합니다. C 로켈 설정은 부적합합니다. 그러나이 코드 페이지는 변경할 수 있습니다. –

답변

0

"이 두 출력은 ..."입니다. cmd.exe을 사용하는 경우 프롬프트가 달러 기호와 비슷한 이유는 무엇입니까? 그렇게 설정 했습니까? 당신이 당신의 예상치 못한 관찰을 설명 할 수 437을의 것을 발견하는 경우

mode con cp /status 

: 당신이 정말 cmd.exe를를 사용하는 경우와 "코드 페이지"를 확인할 수 있습니다. charmap을 엽니 다.exe 그리고 당신은 당신이 염려하는 성격이 "U + 00F6 Diaresis를 가진 라틴어 소문자 O"라고 불리는 것을 알게 될 것입니다. 0xF6, × 00 여러분의 프로그램이 코드를 받게됩니다 : 당신은 코드 페이지 437을 사용하여 CLI에이 붙여 넣을 경우, 몇 가지 흥미로운 일이

될 것 유니 코드 프로그램에 전달됩니다 코드는 ... 일어난다.

코드 페이지 437에는 문자가 있지만 코드는 0x94으로 인식됩니다. CLI (에코 명령 포함)가 일부 WYSIWYG를 수행하고이 후자의 코드 (0x94)가 표시되어 stdout으로 출력됩니다.

CLI에서 문자를 클립 보드에 복사하면 "OEM text"및 0x94 코드와의 추가 연관이 있습니다. 이제

의이 1252 코드 페이지로 전환 할 수 : 당신이 문자표에서 붙여 넣을 때 CLI에,이 코드 페이지에서

mode con cp select=1252 

는 유니 코드 프로그램에 전달 된 코드에서와 동일하게 유지 이전 시나리오.

이제 관찰 한 문자는 터미널 글꼴 (코드 페이지 437과 시각적으로 유사한 글꼴)의 0xF6이므로 구분 기호가 있습니다. 에코 명령은이 코드를 stdout으로 전송합니다.

CLI에서 문자를 클립 보드에 복사하면 이전과 마찬가지로 "OEM text"및 0x94 코드와의 추가 연관이 있습니다.

당신이 의 출력 파일이 문자로 명령을 에코와 터미널 글꼴을 사용 메모장에서 파일을 열 리디렉션 경우 분할 서명을 확인할 수 있습니다. 글꼴을 Courier New으로 변경하면 유니 코드에 따라 "작은 오디세이"가 표시됩니다.

이제 437 코드 페이지로 다시 전환 : 당신이 FILE로 출력 번역되지 않은 유니 코드 시퀀스에 윈도우 유니 코드 프로그램 *을 원하는 경우에

mode con cp select=437 

, 당신이 모드를 사용 믿습니다 . 원래의 코드를 수정하려면, 당신이있을 수 있습니다 :이 예에서

#define _UNICODE 

#include <locale.h> 
#include <stdio.h> 
#include <stdlib.h> 

#include <tchar.h> 
#include <fcntl.h> 
#include <io.h> 

int __cdecl _tmain(int argc, TCHAR ** argv, TCHAR ** envp) { 
    wchar_t bom = 0xFEFF; 

    _setmode(_fileno(stdout), _O_BINARY); 

    _ftprintf(stdout, _T("%c"), bom); 
    _putts(argv[1]); 

    return EXIT_SUCCESS; 
    } 

을, 우리는에 UTF-16 문자를 쓰기 전에 UTF-16LE 바이트 순서 표시 ("BOM")를 쓰기 인수는 표준 출력입니다.이것은 CLI에서 예쁘게하지만 파일로 리디렉션 또는 (바이너리 모드에서) 파일로 직접 작업하는 경우, 결과는 당신이 원래 관심이 무엇의 라인을 따라 아마 더 있습니다

#define _UNICODE 

#ifdef _UNICODE 
#define BOM { 0xFF, 0xFE, 0, 0 } 
#else 
#define BOM { 0 } 
#endif 

#include <locale.h> 
#include <stdio.h> 
#include <stdlib.h> 

#include <tchar.h> 
#include <fcntl.h> 
#include <io.h> 

int __cdecl _tmain(int argc, TCHAR ** argv, TCHAR ** envp) { 
    /* Initialize the BOM string */ 
    static const union { 
     unsigned char bytes[sizeof (TCHAR) * 2]; 
     TCHAR c[2]; 
     } bom = BOM; 
    FILE * f; 
    TCHAR filename[] = _T("testfile.txt"); 
    int r; 
    int rc; 

    /* Assume failure */ 
    rc = EXIT_FAILURE; 

    if (argc != 2) { 
     _ftprintf(stderr, _T("Usage: %s <word>\n"), argv[0]); 
     goto err_usage; 
     } 

    f = _tfopen(filename, _T("wb")); 
    if (!f) { 
     _ftprintf(stderr, _T("Could not open file: %s\n"), filename); 
     goto err_fopen; 
     } 

    r = _ftprintf(f, _T("%s"), bom.c); 
    if (r != _tcsclen(bom.c)) { 
     _ftprintf(stderr, _T("Could not write BOM to file\n")); 
     goto err_bom; 
     } 

    r = _ftprintf(f, _T("%s"), argv[1]); 
    if (r != _tcsclen(argv[1])) { 
     _ftprintf(stderr, _T("Could not write argument to file\n")); 
     goto err_arg; 
     } 

    rc = EXIT_SUCCESS; 

    err_arg: 

    err_bom: 

    fclose(f); 
    err_fopen: 

    err_usage: 

    return rc; 
    } 

여기에 몇 가지 추가 리소스가 도움이 될 수있는 다음과 같습니다

_tfopen : http://msdn.microsoft.com/en-us/library/yeby3zcb.aspx

_ftprintf : http://msdn.microsoft.com/en-us/library/xkh07fe2.aspx

,

_setmode : 텍스트와 바이너리 스트림을 유니 코드에 대해 http://msdn.microsoft.com/en-us/library/tw4k6df8.aspx

: http://msdn.microsoft.com/en-us/library/c4cy2b8e.aspx

SBCS, MBCS, 유니 코드 기능 : http://msdn.microsoft.com/en-us/library/tsbaswba.aspx

관련 문제