[VC++] 유니코드를 표준 출력에 내보내기

  • Post author:
  • Post category:
  • Post comments:10 Comments
  • Post last modified:September 22, 2007

2007.09.27 소스 코드와 테스트 결과 모두 오류가 있어서 글을 고쳐 썼습니다. 죄송합니다.


거의 모든 문자열을 TCHAR로 선언해서 쓴다. _UNICODE가 선언되어 있으니 사실상 wchar_t 타입인 셈이다. 한데 TCHAR*이나 std::wstring에 담긴 한글 문자열을 STDOUT에 출력하려니, 잘 안 됐다. 여태까진 로그를 모조리 영어로 써놔서 몰랐는데, 한글 문자열은 아예 출력이 안 되거나 ???로 표시됐다.

구글링을 해보니 로케일 설정을 해야 한다고 했다. 로케일 설정을 크게 두 가지로 나뉜다.

setlocale(LC_ALL, "korean");
_tprintf("한글\n");

이렇게 하면 된다기에 해봤지만 신통치 않았다. MSDN 라이브러리를 뒤져보니 _wsetlocale가 있었고, 코드를 이렇게 고쳤더니 한글이 출력됐다.

_wsetlocale(LC_ALL, _T("korean"));
_tprintf("한글\n");

아싸, 해결됐다!라고 잠시 착각했지만, 곧바로 새로운 문제가 등장했다.

_wsetlocale(LC_ALL, _T("korean"));
std::wcout << _T("한글") << std::endl;

을 하니 또 한글이 안 나온다. 하여 다시금 구글링을 했다.

std::locale::global(std::locale("kor"));
std::wcout << _T("한글") << std::endl;

를 하면 된다고 하길래 해봤지만, 여전히 결과가 신통치 않았다. 이번에는

wcin.imbue( locale( "korean" ) );
wcout.imbue( locale( "korean" ) );
std::wcout << _T("한글") << std::endl;

를 해보라기에 시도했더니 한글이 출력됐다. 아싸! 또 좋아라 했지만, 이번에도 문제가 있었다.

wcin.imbue( locale("korean") );
wcout.imbue( locale("korean") );
wcout << _T("한글1") << endl;

_wsetlocale(LC_ALL, _T("korean"));
_tprintf(_T("한글2\r\n"));

wcin.imbue( locale("korean") );
wcout.imbue( locale("korean") );
wcout << _T("한글3") << endl;

_tprintf(_T("한글4\r\n"));

을 했는데 한글3만 출력이 안 되는 게 아닌가? _wsetlocale을 한번이라도 호출하면 그 시점부터 wcout이 제대로 작동하질 않았다. 이거야말로 재앙이 아닌가?

결국 정확한 원인을 찾기 귀찮은 나머지 _tprintf와 _wsetlocale은 한동안 쓰지 않기로 했다. 누구 해결책 아시는 분 안 계신가요?

Author Details
Kubernetes, DevSecOps, AWS, 클라우드 보안, 클라우드 비용관리, SaaS 의 활용과 내재화 등 소프트웨어 개발 전반에 도움이 필요하다면 도움을 요청하세요. 지인이라면 가볍게 도와드리겠습니다. 전문적인 도움이 필요하다면 저의 현업에 방해가 되지 않는 선에서 협의가능합니다.
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

10 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
rein
rein
16 years ago

제가 이리저리 해 본 결과는 ?cout과 ?printf를 *동시에 wchar로 쓸 수는 없다* 였습니다 -_-;;

log4cxx를 쓸 때도 콘솔 쪽으로 돌려놓은거랑 그냥 한글 출력시킨 것(wprintf)이 동시에 안나오는 사태가(…)

최재훈
16 years ago

역시 안 되는 건가요? 흐음……

커널0
16 years ago

wcout 에서 한글 출력이 안되고 멈추는 경우 wcout.imbue(locale(“kor”)) 을 해보세요. 보통 한글 locale은 “ko_KR”인데 wide 쪽은 kor 이 먹더군요.

제 글과 상관없이 마지막에 올려주신 코드 컴파일 해보면 (컴파일이 안되서 몇문장은 고쳤습니다;) VS2005영문에서는 한글1,2 둘다 출력이 잘됩니다.

사실더 길게썼습니다만 -_- 이멜주소 안적고 뒤로 오면 다 지워지네요;;

최재훈
16 years ago

네. 말씀하신대로 입니다. 제가 테스트하고 나서 한참 후에 글을 쓴 터라 실수한 것이 분명합니다.

마지막 테스트 케이스에 관한 부분을 고쳐 썼습니다. 결국 _wsetlocale을 호출한 다음부턴 wcout이 안 먹힌다고 보면 될 것 같습니다. korean을 kor로 바꿔서 테스트해봤는데 역시 마찬가지였구요.

iwongu
iwongu
16 years ago

예전에 저도 locale 문제 때문에 머리가 아팠던 적이 있었는데 제 문제는 error state flags와 관계가 있었습니다.

어떤 환경에서는 현재 locale에서 출력할 수 없는 문자를 만나면 error bit을 셋하는데 일단 stream이 error state가 되면 이후로는 정상적인 문자들도 출력을 안해서 발생한 현상이었죠. 그리고 cout과 wcout은 다른 stream이라 별도의 error flags를 가지고 있어서 cout은 되는데 wcout은 안되고… 등등… -_-;;

안나오는 출력앞에 wcout.clear()로 error flags를 초기화하고 한번 해보세요.

그때 썼던 글은 http://ideathinking.com/blog/?p=109 에 있습니다. ^^

최재훈
16 years ago

// 아래 코드를 실행하면,
// 한글1
// 한글2
// 1
// 0
// 1
// 1
// 한글 6
wcin.imbue( locale(“korean”) );
wcout.imbue( locale(“korean”) );
wcout << _T(”한글1”) << endl;

_wsetlocale(LC_ALL, _T(“korean”));
_tprintf(_T(”한글2rn”));

wcin.imbue( locale(“korean”) );
wcout.imbue( locale(“korean”) );

wcout << _T(”한글3”) << endl;
cout << wcout.fail() << endl;
wcout.clear();
cout << wcout.fail() << endl;

wcout << _T(”한글4”) << endl;
cout << wcout.fail() << endl;

wcin.imbue( locale(“korean”) );
wcout.imbue( locale(“korean”) );

wcout << _T(”한글5”) << endl;
cout << wcout.fail() << endl;

_tprintf(_T(”한글6rn”));

짐퀴
짐퀴
14 years ago

setlocale(LC_ALL, “”);
가 진리죠.
현재 시스템 설정 따라갑니다.

Dae Seong Bae
11 years ago
Reply to  짐퀴

진리네요 감사합니다~!

최재훈
14 years ago

오래 전에 글 써놓고 어떻게 해놨나 기억이 안 나네요. LC_ALL로 했었나? ㅎㅎ

나중에 시간 내서 다시 테스트해보겠습니다.

짐퀴
짐퀴
13 years ago

음, C++에서는 locale(”“) 를 stream에 imbue를 해주든지 global 하면 되네요.
setlocale은 C 함수라는 걸 간과하고 있었네요…
std::sync_with_stdio() 를 이용하면 어떻게든 될지도 모르겠구요.