2016-12-12 1 views
6

wchar_t,char16_t、またはchar32_tの値を狭いostreamに入力すると、コードポイントの数値が出力されます。iostreams - `wchar_t`または` charXX_t`値を文字として出力

#include <iostream> 
using std::cout; 
int main() 
{ 
    cout << 'x' << L'x' << u'x' << U'x' << '\n'; 
} 

プリントx120120120。これは、basic_ostreamcharTの特定の組み合わせに対してoperator<<が存在するためですが、他の文字タイプには類似の演算子がないため、黙ってintに変換されて印刷されます。同様に、非狭い文字列リテラル(L"x"u"x"U"X")はサイレントvoid*に変換され、オブジェクトwstringu16stringu32string)があってもコンパイルされませんポインタ値、及び非狭い列として印刷されます。

だから、質問:文字としてではなく、コードポイントの数値として、狭いのostreamにwchar_tchar16_t、またはchar32_t値を印刷する少なくともひどいな方法は何ですか? すべて ostreamのエンコーディングで表現可能なコードポイントをそのエンコーディングに正しく変換する必要があり、コードポイントが表現できないときにエラーを報告する必要があります。 (例えば、u'…'所与とUTF-8のostreamは、3バイトのシーケンス0xE2 0x80では0xA6ストリームに書き込まなければならない;しかしu'â'所与とKOI8-R用のostreamは、エラーが報告されるべきである。)同様

どのように非狭いC文字列または文字列オブジェクトを狭いostreamに出力して、出力エンコーディングに変換できますか?

これはISO C++ 11では実行できない場合は、プラットフォーム固有の回答を取ります。

は(this questionからインスピレーションを受けている。)

+2

要するに、1)ワイドostreamを使用するか、2)ワイド文字データを自分自身の狭いエンコーディングに変換する必要があります。 ostreamはあなたのためにその変換を行うことはできません。 ['std :: wstring_convert'](http://en.cppreference。com/w/cpp/locale/wstring_convert)を使用するか、[ICONV](https://www.gnu.org/software/libiconv/)または[ICU](http://site.icu-project。 org /)。 –

答えて

2

をあなたが述べたように、狭いのostreamにはoperator<<(std::ostream&, const wchar_t)はありません。構文を使用したい場合は、wcharの処理方法をostreamに教えることができます。そのため、そのルーチンは整数への変換が必要なものよりも優れたオーバーロードとして選択されます。

あなたは冒険を感じている場合:

namespace std { 
    ostream& operator<< (ostream& os, wchar_t wc) { 
    if(unsigned(wc) < 256) // or another upper bound 
     return os << (unsigned char)wc; 
    else 
     throw your_favourite_exception; // or handle the error in some other way 
    } 
} 

それ以外の場合は、透過的にwchar_tを包含し、カスタムfriend operator<<を持っていることstructシンプルを作成し、それらを出力する前にそれにあなたのワイド文字に変換します。

編集:ようロケールにしてからオンザフライ変換を行うには、あなたは、<cwchar>から関数を使用することができます。

ostream& operator<< (ostream& os, wchar_t wc) { 
    std::mbstate_t state{}; 
    std::string mb(MB_CUR_MAX, '\0'); 
    size_t ret = std::wcrtomb(&mb[0], wc, &state); 
    if(ret == static_cast<std::size_t>(-1)) 
     deal_with_the_error(); 
    return os << mb; 
} 

がにあなたのロケールを設定することを忘れないでください。システムのデフォルト:

+0

これは、値を狭い出力エンコーディングに変換しません。それは不可欠であり、それは私がやってもらえない方法でもあります。 – zwol

+0

@zwolワイド文字をASCII以外に変換したい場合は、それを受け入れる以外にどのように変換したいのですか?次に、アクセントや何かを削除するなど、具体的にする必要があります。 –

+0

あなたの例ではこれを渡す 'x'を使います( 'L'x 'の場合、他のタイプでも同じことをする必要があります)。 –

関連する問題