2012-02-09 2 views
2

プラットフォーム固有の機能を使用せずにUTF-8文字列を印刷することはできますか?プラットフォーム固有の機能を使用せずにUTF-8文字列を印刷する方法は?

#include <iostream> 
#include <locale> 
#include <string> 

using namespace std; 

int main() 
{ 
    ios_base::sync_with_stdio(false); 
    wcout.imbue(locale("en_US.UTF-8")); // broken on Windows (?) 

    wstring ws1 = L"Wide string."; 
    wstring ws2 = L"Wide string with special chars \u20AC"; // Euro character 

    wcout << ws1 << endl; 
    wcout << ws2 << endl; 
    wcout << ws1 << endl; 
} 

私は、このランタイムエラーを取得:

terminate called after throwing an instance of 'std::runtime_error'
what(): locale::facet::_S_create_c_locale name not valid

私はラインwcout.imbue(locale("en_US.UTF-8"));を削除した場合、私は一度だけ印刷されただけws1を取得し、。別の質問(「How can I cin and cout some unicode text?」)では

、フィリップは書いている: 『のwciNとwcoutだけで同等のC関数のように、Windows上で動作しませんが、ネイティブAPIの作品。。』 MinGWもそうですか?

ありがとうございました!

プラットフォーム:
のMinGW/GCC
のWindows 7

答えて

5

私はWindows上でmingwの環境でのgccを使用しますが、私はそれがC++のロケールをサポートしていません集めるものとされていません。

これはC++ロケールをサポートしていないので、これは実際には関係ありませんが、FYIでは、Windowsは他のほとんどのプラットフォームと同じロケール命名方式を使用しません。彼らは同様のlanguage_country.encodingを使用しますが、言語と国はコードではなく、エンコードはWindowsのコードページ番号です。ロケールは "English_United States.65001"ですが、これはサポートされている組み合わせではありません(コードページ65001(UTF-8)はロケールの一部としてサポートされていません)。

ws1だけが印刷される理由は、文字\u20ACが印刷されると、ストリームが失敗し、失敗ビットが設定されるためです。さらに何かが印刷される前にエラーをクリアする必要があります。


C++ 11には、移植可能UTF-8に対処しますいくつかのことを紹介したが、すべてがまだサポートされていない、と追加が問題を完全に解決しません。しかし、ここでの方法の物事が現在スタンドです:

char16_tchar32_tは、ネイティブ型ではなく、型定義を使用すると、標準のcodecvtファセット特殊化を使用することができるようになりますようVSでサポートされている

codecvt<char16_t,char,mbstate_t>とUTF-16またはの間で変換するのに必要とされるcodecvt<char32_t,char,mbstate_t> UTF-32、およびUTF-8(実行文字セットまたはシステムエンコーディングではなく)です。現在のVS(およびVS11DP)ではこれらの型はtypedefのみであり、テンプレートの特殊化はtypedefでは機能しませんが、コードは既に#ifdefの背後に保護されているVS 2010のヘッダーにあります。

標準では、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のコンソールモデルと標準ストリームの実装方法により、コンソール出力コードページをUTF-8に設定しても、このようにコマンドプロンプトでUnicode文字を正しく表示することはできませんSetConsoleOutputCP(CP_UTF8))。 UTF-8コードユニットは、一度に1つずつ出力され、コンソールは、各チャンク(この場合は1バイト)が完全で有効なエンコーディングになることを期待して、渡された個々のチャンクを調べます。チャンク内の不完全または無効なシーケンス(この場合はすべてのマルチバイト文字表現のすべてのバイト)は、文字列が表示されるときにU + FFFDに置き換えられます。

iostreamを使用する代わりに、C関数putsを使用してUTF-8エンコードされた文字列全体を書き出すと(コンソール出力コードページが正しく設定されている場合)、UTF-8文字列を出力して表示できますコンソールで同じcodecvtファセットがこれを行うには、いくつかの他のC++ 11 convinenceクラスで使用することができます:それはwchar_t型はUTF-16、ケースがオンであることを前提としているため

std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> convert; 
puts(convert(L"ØÀéîðüýþ\n).to_bytes().c_str()); 

以上、まだ非常にポータブルではありませんWindowsは、ほとんどの他のプラットフォームではなく、標準では必要ありません。 (実際には、UTF-16はいくつかの文字を表すために複数のコード単位を必要とし、標準では選択したエンコーディングのすべての文字を単一のwchar_tで表現できる必要があるため、技術的には適合しません。

std::wstring_convert<std::codecvt_utf8<wchar_t>,wchar_t> convert; 

以上が移植UCS-4およびUSC-2を処理するが、UTF-16を使用して、プラットフォームの基本多言語面の外側に動作しません。

あなたはwchar_tの大きさに基づいて、これらの2つの側面の間で選択するためにconditional型特性を利用し、主に働く何かを得ることができます:

std::wstring_convert< 
    std::conditional<sizeof(wchar_t)==2,std::codecvt_utf8_utf16<wchar_t>, 
             std::codecvt_utf8<wchar_t> 
    >::type, 
    wchar_t 
> convert; 

それとも、あなたの場合は、適切な型定義を定義するために、プリプロセッサマクロを使用しますコーディング標準はマクロを許可します。

+0

ありがとうございました! –

1

UTF-8のWindowsのサポートは非​​常に貧弱ですが、Windows APIを使用して行うことも可能ですが、それは楽しいものではありません。また、プラットフォーム固有の機能を使用したくないという質問もあります。

「標準C++」で行うことについては、プラットフォーム固有のコードなしでWindowsで可能かどうかはわかりません。しかし、これらのプラットフォームの詳細を抽象化し、移植可能なコードを書くことを可能にする多数のサードパーティライブラリが利用可能です。

私は最近、Boost.Localeライブラリの助けを借りて内部的にUTF-8を使用するようにアプリケーションを更新しました。 http://www.boost.org/doc/libs/1_48_0/libs/locale/doc/html/index.html

そのロケールの生成クラスを使用すると、あなたがして、すべての標準的な流れに吹き込むことができUTF-8ベースのロケールオブジェクトを生成することを可能にするなど

私はMSVCとGCC経由の両方の下で今、この権利を使用していますMinGW-w64が正常に終了しました!私は非常にあなたがそれをチェックすることをお勧めします。はい、残念ながら、それは技術的には「標準C++」ではありませんが、Boostはほとんどどこからでも利用でき、事実上の標準であるため、大きな懸念はありません。

+0

さて、私はブーストを標準の一部として考えます。 MinGW32の問題を知っていますか? –

関連する問題