8

日本語を独学するための簡単なコマンド ライン アプリを作成しようとしていますが、Unicode 文字を印刷することができないようです。私は何が欠けていますか?

#include <iostream>
using namespace std;

int main()
{
        wcout << L"こんにちは世界\n";
        wcout << L"Hello World\n"
        system("pause");
}

この例では、「続行するには何かキーを押してください」のみが表示されます。Visual C++ 2013 でテスト済み。

4

3 に答える 3

7

これは Windows では簡単ではありません。Windows コンソールにテキストを取得できたとしても、日本語の文字を表示できるように cmd.exe を構成する必要があります。


#include <iostream>

int main() {
  std::cout << "こんにちは世界\n";
}

これは、次のようなシステムで正常に機能します。

  • コンパイラのソースおよび実行エンコーディングには、文字が含まれます。
  • 出力デバイス (コンソールなど) は、コンパイラの実行エンコーディングと同じエンコーディングのテキストを想定しています。
  • 適切な文字を含むフォントが利用可能です (通常は問題ありません)。

最近のほとんどのプラットフォームは、これらすべてのエンコーディングにデフォルトで UTF-8 を使用しているため、上記のようなコードで Unicode 範囲全体をサポートできます。残念ながら、Windows はこれらのプラットフォームの 1 つではありません。

wcout << L"こんにちは世界\n";

この行では、文字列リテラル データが (コンパイル時に) ソース エンコーディングから実行全体のエンコーディングに変換され、(実行時に)wcout組み込まれているロケールを使用して wchar_t データを出力用の char データに変換します。うまくいかないのは、デフォルトのロケールが基本的なソース文字セットからの文字をサポートすることだけを必要とすることです。これには、非 ASCII 文字は言うまでもなく、すべての ASCII 文字も含まれていません。

したがって、変換はエラーにwcoutなり、悪い状態になります。wcout が再び機能する前に、エラーをクリアする必要があります。これが、2 番目の print ステートメントが何も出力しない理由です。


wcout文字を正常に変換するロケールを吹き込むことで、限られた範囲の文字でこれを回避できます。残念ながら、この方法で Unicode 範囲全体をサポートするために必要なエンコーディングは UTF-8 です。Microsoft のストリームの実装は他のマルチバイト エンコーディングをサポートしていますが、厳密には UTF-8 をサポートしていません。

例えば:

wcout.imbue(std::locale(std::locale::classic(), new std::codecvt_utf8_utf16<wchar_t>()));

SetConsoleOutputCP(CP_UTF8);

wcout << L"こんにちは世界\n";

ここでwcoutは、文字列を UTF-8 に正しく変換します。出力がコンソールではなくファイルに書き込まれた場合、ファイルには正しい UTF-8 データが含まれます。ただし、Windows コンソールは、ここで UTF-8 データを受け入れるように構成されていても、この方法で記述された UTF-8 データを受け入れません。


いくつかのオプションがあります:

  • 標準ライブラリを完全に回避します。

    DWORD n;
    WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"こんにちは世界\n", 8, &n, nullptr);
    
  • 標準コードを壊す非標準の魔法の呪文を使用します。

    #include <fcntl.h>
    #include <io.h>
    
    _setmode(_fileno(stdout), _O_U8TEXT);
    std::wcout << L"こんにちは世界\n";
    

    このモードstd::cout << "Hello, World";を設定するとクラッシュします。

  • 手動変換とともに低レベル IO API を使用します。

    #include <codecvt>
    #include <locale>
    
    SetConsoleOutputCP(CP_UTF8);
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
    std::puts(convert.to_bytes(L"こんにちは世界\n"));
    

これらの方法のいずれかを使用すると、cmd.exe はその能力を最大限に発揮して正しいテキストを表示します。つまり、判読できないボックスが表示されます。指定された文字列の 7 つの小さなボックス。

                            小さな箱

テキストを cmd.exe から notepad.exe などにコピーして、正しいグリフを表示できます。

于 2013-09-19T23:00:28.643 に答える
-1

または、Windows のロケールを日本語に変更できます。

于 2013-11-03T23:48:33.163 に答える