前回の記事に引き続いて、VC++で日本語文字を扱う方法についてあれこれ調べている。調べれば調べるほど、開いてはいけない蓋を開いているような気がしてならない。
今回はUnicode文字をVC++で出力することを目指した。結論から言うと、MessageBoxを使ってポップアップを開く方法ではUnicode文字を出力できたけど、標準出力で出力する方法は最後まで分からなかった。実験環境はWindows 7 + VS 2013 Express。
Unicode文字列を用意
※はてなに貼り付けると一部の文字が数値文字参照になってしまったので、ideoneを参照してください
最初に、Shift_JISでは表せないけどUnicodeでは表せる文字列を探す。有名なのは「𠮟」という字。これは「叱」と似て非なる字。詳しくは新常用漢字が引き起こす文字コード問題 - 新常用漢字表が迫るUnicode移行、「シフトJIS」では対応不可能:ITproを参照。他にも、「〓」(ウムラウト文字)とか、怪しい顔文字「(*´ڡ`●)」「( ・ิϖ・ิ)」はShift_JISで表せない。
今回はこれらをすべてぶちこんで以下の文字列を作った。
wchar_t uni[] = L"Unicodeのテストです。𠮟〓(*´ڡ`●)( ・ิϖ・ิ) 正しく表示されるでしょうか";
このようにShift_JISで表せない文字がソースコードに入った場合、ソースコードの文字コードを変更する旨勧められるはず。指示にしたがってUTF-8 (コードページ65001)で保存した。
MessageBoxで表示→成功
この文字列をMessageBoxで表示させる。ワイド文字列を表示させたいのでMessageBoxW()を使う。
MessageBoxW(NULL, uni, uni, MB_OK);
標準出力→失敗
次に標準出力。普通にwcoutで出力。
wcout << uni << endl;
これは多分、コマンドプロンプトがShift_JISしか表示できないのが原因。なんとかできないかと思って色々調べたのだが、結局Unicodeの文字を表示できるようにする方法はわからなかった。以下は調べたことの一部。
chcpを使う
chcpコマンドを使うとUTF-8の文字が表示されるという情報があった。C++プログラムからchcp相当のことを行うにはSetConsoleOutputCP(65001);とすればよいという。しかしフォントがなくて表示されなかった。。 参照記事にはレジストリをいじる旨書かれていたがそこまでは深入りしていない。もしかしたらSetCurrentConsoleFontEx()関数を使えばフォント設定できるかもしれないけど試していない。
_setmode()を使う
意味もわからずc++ - how to properly print utf8 characters in windows console? - Stack Overflowを真似して_O_U16TEXTとか_setmode()とかいうのを使ってみた。Shift_JISで表現可能な文字のみ表示できたが、他はNG。
localeを設定する
setlocaleでUnicodeを使うように設定すればいいんじゃないの?と思い、setlocale(LC_ALL, "Japanese_Japan.65001"); とやってみたがダメ。少しでも関係のありそうなもの、例えば #pragma setlocale(".UTF-8") とか #pragma execution_character_set("utf-8") とかを訳も分からず書いてみたが、どれもうまくいかなかった。
exeを実行して > out.txtする
ダメ。コンソールと結果同じ。
今回の実験で使用したソースコード
http://ideone.com/iJCMSx:ideoneに置いた。
一部問題があるが、はてなにも貼り付ける。
#include <iostream> #include <clocale> #include <iostream> #include <Windows.h> // for MessageBoxW using namespace std; int main(int argc, char* argv[]) { wchar_t uni[] = L"Unicodeのテストです。𠮟〓(*´ڡ`●)( ・ิϖ・ิ) 正しく表示されるでしょうか"; wcout << uni << endl; MessageBoxW(NULL, uni, uni, MB_OK); return 0; }
参考
- How to create a UTF-8 string literal in Visual C++ 2008 - Stack Overflow
- gcc, VS2003, VS2005での文字列の扱いの違いが書かれているっぽい。近づく気になれない…
- Sign in to your Microsoft account
- 多分MSの人のブログ。 _O_U16TEXT とか _O_U8TEXT の解説があるが未読
- Why is the default console codepage called "OEM"? - The Old New Thing - Site Home - MSDN Blogs