Standard output으로 unicode 문자를 출력하기 (Win32 console application)
Win32 console application에서 Unicode 문자를 표준 출력을 통해 출력하려고 한다. 그러나 console window가 Unicode를 지원하지 않는 문제점이 있다. 이런 문제점을 해결하려면 locale 설정을 한 후 출력을 한다.
#include <iostream>
#include <locale>
int main(int argc, wchar_t* argv[])
{
std::wcout.imbue( std::locale("kor") ); // locale 설정.
std::wcout << L'\xBDC1' << L'\x0424' << L'\x3048' << L'\x7E6D' << std::endl;
if( std::wcout.fail() )
{
std::wcerr << L"failed : print unicode characters" << std::endl;
return 1;
}
return 0;
}
한글로 로케일을 설정했다. 이렇게 하면 Unicode 문자가 Codepage 949 문자로 변환된 다음 출력이 되게 된다.
그럼 Codepage 949로 표현하지 못하는 Unicode 문자를 출력하면 어떻게 될까?
std::wcout << L'\x0D30' << std::endl;
Codepage 949 문자로 변환이 실패해서 fail bit가 설정된다.
제길 Unicode를 제대로 출력하려면 문자의 code point를 검사해서 Unicode 문자를 표현할 수 있는 Codepage로 locale설정을 한 다음 출력해야 하나? 이쯤되면 유니코드 출력에 wcout을 포기하는게 나은 선택이 될 것이다.
다행인게 VS2005부터 Unicode 표준 출력을 지원한다.
#include <iostream>
#include <locale>
#include <io.h>
#include <fcntl.h>
int main(int argc, wchar_t* argv[])
{
_setmode(_fileno(stdout), _O_U16TEXT);
std::wcout << L'\x0D30' << std::endl;
return 0;
}
야호!!! 잘 출력된다. 그런데 좀 출력이 이상하다. fail bit를 검사해보니 한 문자를 출력할 때마다 세팅되고 있다. 물론 출력은 잘 되고 있는데 말이다.
std::wcout << L'\xBDC1';
std::wcout.clear();
std::wcout << L'\x0424';
std::wcout.clear();
std::wcout << L'\x3048';
std::wcout.clear();
std::wcout << L'\x7E6D';
std::wcout.clear();
std::wcout << L'\x0D06';
std::wcout.clear();
std::wcout << std::endl;
한 문자를 출력하고 난 뒤, 상태 비트를 매번 클리어 시켜줘야 다음 문자가 제대로 출력된다.
이것 참! 원인을 모르겠네. 이거 원인을 알아내기 전까지는 속 편히 WriteConsoleW을 써야겠다. 아님 현재 Codepage에서 다 보여줄 수 있다는 확신을 갖고 로케일 설정을 해서 쓰거나~
#include <windows.h>
#include <string>
int main(int argc, wchar_t* argv[])
{
std::wstring unicodeString = L"\xBDC1\x0424\x3048\x7E6D\x0D06";
// 문자수를 이렇게 계산하면 안 된다. UTF-16은 한 캐릭터가 2byte 혹은 4byte이다.
// 테스트니깐 뭐 어때~
const DWORD charCount = static_cast<DWORD>(unicodeString.length());
DWORD writtenCount;
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),
unicodeString.c_str(), charCount, &writtenCount, NULL);
return 0;
}
PS : 콘솔에서 폰트가 이상하게 출력되는 이유는 사용 폰트를 Arial Unicode MS를 설정해서 그렇다.
PS2 : 에잉! 제일 앞에서 U+0D30을 사용하고 뒤에서는 U+0D06을 사용했다. 출력 여부가 중요하니 그냥 넘어간다.