5

Visual Studio C++ 2008 (Express) を使用しています。以下のコードを実行すると、wostream (std::wcoutとの両方std::wfstream) は最初の非 ASCII 文字 (この場合は中国語) に遭遇した時点で出力を停止します。プレーン ASCII 文字は正常に印刷されます。ただし、デバッガーでwstringは、実際には s に漢字が適切に入力されており、output << ...が実際に実行されていることがわかります。

Visual Studio ソリューションのプロジェクト設定は、「Unicode 文字セットを使用する」に設定されています。std::wostreamASCII 範囲外の Unicode 文字を出力できないのはなぜですか?

void PrintTable(const std::vector<std::vector<std::wstring>> &table, std::wostream& output) {
    for (unsigned int i=0; i < table.size(); ++i) {
        for (unsigned int j=0; j < table[i].size(); ++j) {
            output << table[i][j] << L"\t";
        }
        //output << std::endl;
    }
}


void TestUnicodeSingleTableChinesePronouns() {
    FileProcessor p("SingleTableChinesePronouns.docx");
    FileProcessor::iterator fileIterator;
    std::wofstream myFile("data.bin", std::ios::out | std::ios::binary);
    for(fileIterator = p.begin(); fileIterator != p.end(); ++fileIterator) {
        PrintTable(*fileIterator, myFile);
        PrintTable(*fileIterator, std::wcout);
        std::cout<<std::endl<<"---------------------------------------"<<std::endl;
    }
    myFile.flush();
    myFile.close();
}
4

2 に答える 2

3

デフォルトでは、 std::wcout および std::wofstream が特定の操作に使用するロケールは "C" ロケールであり、ASCII 以外の文字 (または C++ の基本文字セット外の文字) をサポートする必要はありません。使用する文字をサポートするロケールに変更します。

Windows で行う最も簡単な方法は、残念ながらレガシー コードページを使用することですが、それは避けるべきです。従来のコードページは悪いニュースです。代わりに、UTF-8、UTF-16 など、Unicode を使用する必要があります。また、コンソールへの書き込みが他の種類の出力ストリームへの書き込みと大きく異なる Windows の不幸なコンソール モデルを回避する必要があります。コンソールを具体的に処理する独自の出力バッファーを見つけるか作成する必要がある場合があります (または、Microsoft に修正を依頼するバグを報告することもできます)。

コンソール出力の例を次に示します。

#include <Windows.h>

#include <streambuf>
#include <iostream>

class Console_streambuf
    : public std::basic_streambuf<wchar_t>
{
    HANDLE m_out;
public:
    Console_streambuf(HANDLE out) : m_out(out) {}

    virtual int_type overflow(int_type c = traits_type::eof())
    {
        wchar_t wc = c;
        DWORD numberOfCharsWritten;
        BOOL res = WriteConsoleW(m_out, &wc, 1, &numberOfCharsWritten, NULL);
        (void)res;
        return 1;
    }
};

int main() {
    Console_streambuf out(GetStdHandle(STD_OUTPUT_HANDLE));
    auto old_buf = std::wcout.rdbuf(&out);
    std::wcout << L"привет, 猫咪!\n";
    std::wcout.rdbuf(old_buf); // replace old buffer so that destruction can happen correctly. FIXME: use RAII to do this in an exception safe manner.
}

次のようなファイルに UTF-8 出力を行うことができます (ただし、VS2008 が codecvt_utf8_utf16 をサポートしているかどうかはわかりません)。

#include <codecvt>
#include <fstream>

int main() {
    std::wofstream myFile("data.bin", std::ios::out | std::ios::binary);
    myFile.imbue(std::locale(myFile.getloc(),new std::codecvt_utf8_utf16<wchar_t>));

    myFile << L"привет, 猫咪!";
}
于 2012-07-23T18:30:53.997 に答える
0

次のヘッダー ファイルをインクルードします。

#include <locale>

main の先頭に、次の行を追加します。

std::locale::global(std::locale("chinese"));

これは、適切なロケールを設定するのに役立ちます。

于 2012-07-23T14:19:12.970 に答える