Windows の mingw 環境で gcc を使用したことはありませんが、収集したところ、C++ ロケールをサポートしていません。
C++ ロケールをサポートしていないため、これはあまり関係ありませんが、参考までに、Windows は他のほとんどのプラットフォームと同じロケール命名スキームを使用していません。同様の language_country.encoding を使用していますが、言語と国はコードではなく、エンコーディングは Windows コード ページ番号です。したがって、ロケールは「English_United States.65001」になりますが、これはサポートされている組み合わせではありません (コード ページ 65001 (UTF-8) は、どのロケールの一部としてもサポートされていません)。
一度だけ印刷される理由ws1
は、文字\u20AC
が印刷されるときにストリームが失敗し、失敗ビットが設定されるためです。さらに何かが印刷される前に、エラーをクリアする必要があります。
C++11 では、UTF-8 を移植可能に処理するいくつかの機能が導入されましたが、まだすべてがサポートされているわけではなく、追加によって問題が完全に解決されるわけではありません。しかし、現在の状況は次のとおりです。
char16_t
とが typedef ではなくネイティブ タイプとして VS でサポートされている場合、標準の codecvt ファセットの特殊化char32_t
を使用できます。これは、それぞれ UTF-16 または UTF-32 とUTF-8 (実行文字セットまたはシステムエンコーディング)。現在の VS (および VS11DP) ではこれらの型は typedef のみであり、テンプレートの特殊化は typedef では機能しないため、これはまだ機能しませんが、コードは VS 2010 のヘッダーに既にあり、.codecvt<char16_t,char,mbstate_t>
codecvt<char32_t,char,mbstate_t>
#ifdef
標準では、サポートされているいくつかの特殊な目的の codecvt ファセット テンプレート、codecvt_utf8、および codecvt_utf8_utf16 も定義しています。前者は、使用するワイド文字型のサイズに応じて、UTF-8 と UCS-2 または UCS-4 のいずれかの間で変換し、後者は、ワイド文字のサイズに関係なく、UTF-8 と UTF-16 コード単位の間で変換します。タイプ。
std::wcout.imbue(std::locale(std::locale::classic(),new std::codecvt_utf8_utf16<wchar_t>()));
std::wcout << L"ØÀéîðüýþ\n";
これにより、wcout にアタッチされているものは何でも、UTF-8 コード単位が出力されます。出力がファイルにリダイレクトされている場合、それを開くと UTF-8 でエンコードされたファイルが表示されます。ただし、Windows のコンソール モデルと標準ストリームの実装方法が原因で、この方法ではコマンド プロンプトに Unicode 文字が正しく表示されません (コンソール出力コード ページを で UTF-8 に設定してもSetConsoleOutputCP(CP_UTF8)
) 。 . UTF-8 コード単位は一度に 1 つずつ出力され、コンソールは、渡された各チャンク (つまり、この場合は 1 バイト) が完全で有効なエンコーディングであることを期待して、渡された個々のチャンクを調べます。チャンク内の不完全または無効なシーケンス (この場合、すべてのマルチバイト文字表現のすべてのバイト) は、文字列が表示されるときに U+FFFD に置き換えられます。
iostream を使用する代わりに C 関数puts
を使用して UTF-8 でエンコードされた文字列全体を書き出す場合 (およびコンソール出力コード ページが正しく設定されている場合) は、UTF-8 文字列を出力してコンソールに表示することができます。これを行うために、同じ codecvt ファセットを他のいくつかの C++11 convinence クラスで使用できます。
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> convert;
puts(convert(L"ØÀéîðüýþ\n).to_bytes().c_str());
上記は、wchar_t が UTF-16 であると想定しているため、まだ移植性が高くありません。これは、Windows では当てはまりますが、他のほとんどのプラットフォームでは当てはまらず、標準では必要ありません。(実際、UTF-16 では一部の文字を表すために複数のコード単位が必要であり、標準では、選択したエンコーディングのすべての文字を単一の wchar_t で表現できる必要があるため、技術的に準拠していないと理解しています)。
std::wstring_convert<std::codecvt_utf8<wchar_t>,wchar_t> convert;
上記は UCS-4 と USC-2 を移植可能に処理しますが、UTF-16 を使用するプラットフォームの Basic Multilingual Plane の外では機能しません。
型特性を使用しconditional
て、サイズに基づいてこれら 2 つのファセットを選択しwchar_t
、ほとんど機能するものを取得できます。
std::wstring_convert<
std::conditional<sizeof(wchar_t)==2,std::codecvt_utf8_utf16<wchar_t>,
std::codecvt_utf8<wchar_t>
>::type,
wchar_t
> convert;
または、コーディング標準でマクロが許可されている場合は、プリプロセッサ マクロを使用して適切な typedef を定義します。