20

これは私がそれをやろうとする方法です:

#include <stdio.h>
#include <windows.h>
using namespace std;

int main() {
  SetConsoleOutputCP(CP_UTF8);
   //german chars won't appear
  char const* text = "aäbcdefghijklmnoöpqrsßtuüvwxyz";
  int len = MultiByteToWideChar(CP_UTF8, 0, text, -1, 0, 0);
  wchar_t *unicode_text = new wchar_t[len];
  MultiByteToWideChar(CP_UTF8, 0, text, -1, unicode_text, len);
  wprintf(L"%s", unicode_text);
}

そしてその効果は、私たちのアスキー文字だけが表示されるということです。エラーは表示されません。ソースファイルはutf8でエンコードされています。

だから、私がここで間違っているのは何ですか?

WouterHへ:

int main() {
  SetConsoleOutputCP(CP_UTF8);
  const wchar_t *unicode_text = L"aäbcdefghijklmnoöpqrsßtuüvwxyz";
  wprintf(L"%s", unicode_text);
}
  • これも機能しません。効果は同じです。私のフォントはもちろんLucidaConsoleです。

3番目のテイク:

#include <stdio.h>
#define _WIN32_WINNT 0x05010300
#include <windows.h>
#define _O_U16TEXT  0x20000
#include <fcntl.h>

using namespace std;

int main() {
    _setmode(_fileno(stdout), _O_U16TEXT);
    const wchar_t *u_text = L"aäbcdefghijklmnoöpqrsßtuüvwxyz";
    wprintf(L"%s", u_text);
}

わかりました。何かが機能し始めますが、出力は次のとおりańbcdefghijklmno÷pqrs▀tuŘvwxyzです。

4

7 に答える 7

17

デフォルトでは、Windows のワイド プリント関数は、ASCII 範囲外の文字を処理しません。

Windows コンソールに Unicode データを取得するには、いくつかの方法があります。

  • コンソール API WriteConsoleW を直接使用します。実際にコンソールに書き込んでいることを確認し、出力が他のものにある場合は他の手段を使用する必要があります。

  • 標準出力ファイル記述子のモードを「Unicode」モードの 1 つ、_O_U16TEXT または _O_U8TEXT に設定します。これにより、ワイド文字出力関数が Unicode データを Windows コンソールに正しく出力します。コンソールを表さないファイル記述子で使用すると、バイトの出力ストリームがそれぞれ UTF-16 と UTF-8 になります。注意: これらのモードを設定すると、対応するストリームの非ワイド文字関数が使用できなくなり、クラッシュが発生します。ワイド文字関数のみを使用する必要があります。

  • 適切な関数を使用する場合、コンソール出力コードページを CP_UTF8 に設定することにより、UTF-8 テキストをコンソールに直接出力できます。などの高レベル関数のほとんどはbasic_ostream<char>::operator<<(char*)このようには機能しませんが、低レベル関数を使用するか、標準関数の問題を回避する独自の ostream を実装することができます。

3 番目の方法の問題点は次のとおりです。

putc('\302'); putc('\260'); // doesn't work with CP_UTF8

puts("\302\260"); // correctly writes UTF-8 data to Windows console with CP_UTF8 

ほとんどのオペレーティング システムとは異なり、Windows のコンソールは、バイト ストリームを受け入れる単なる別のファイルではありません。これは、プログラムによって作成および所有され、独自の WIN32 API を介してアクセスされる特別なデバイスです。問題は、コンソールへの書き込み時に、API がその API の使用で渡されたデータの範囲を正確に認識し、データが不完全である可能性があることを考慮せずにナロー文字からワイド文字への変換が行われることです。コンソール API への複数の呼び出しを使用してマルチバイト文字が渡された場合、個別に渡された各ピースは不正なエンコーディングと見なされ、そのように扱われます。

これを回避するのは簡単なはずですが、Microsoft の CRT チームはそれを問題ではないと考えていますが、コンソールで作業しているチームはおそらく気にしません.

wchar_t への変換を正しく処理する独自の streambuf サブクラスを実装することで解決できます。つまり、マルチバイト文字のバイトが別々に来る可能性があるという事実を説明し、書き込み間の変換状態を維持します (例: std::mbstate_t)。

于 2012-06-04T16:04:01.080 に答える
13

の代わりに別のトリックとして、_setmode onSetConsoleOutputCPを使用します。stdout

// Includes needed for _setmode()
#include <io.h>
#include <fcntl.h>

int main() {
    _setmode(_fileno(stdout), _O_U16TEXT);  
    wchar_t * unicode_text = L"aäbcdefghijklmnoöpqrsßtuüvwxyz";
    wprintf(L"%s", unicode_text);
    return 0;
}

への呼び出しを削除することを忘れないでくださいSetConsoleOutputCP(CP_UTF8);

于 2012-06-04T14:13:20.303 に答える
7
//Save As UTF8 without signature
#include<stdio.h>
#include<windows.h>
int main() {
  SetConsoleOutputCP(65001);
  const char unicode_text[]="aäbcdefghijklmnoöpqrsßtuüvwxyz";
  printf("%s\n", unicode_text);
}

結果:
aäbcdefghijklmnoöpqrsßtuüvwxyz

于 2013-09-28T21:15:50.060 に答える
1

次の方法で問題を解決しました。

Lucida Console はウムラウトをサポートしていないようです。たとえば、コンソールのフォントを Consolas に変更すると機能します。

#include <stdio.h>
#include <Windows.h>

int main()
{
    SetConsoleOutputCP(CP_UTF8);

    // I'm using Visual Studio, so encoding the source file in UTF-8 won't work
    const char* message = "a" "\xC3\xA4" "bcdefghijklmno" "\xC3\xB6" "pqrs" "\xC3\x9F" "tu" "\xC3\xBC" "vwxyz";

    // Note the capital S in the first argument, when used with wprintf it
    // specifies a single-byte or multi-byte character string (at least on
    // Visual C, not sure about the C library MinGW is using)
    wprintf(L"%S", message);
}

編集:愚かなタイプミスと文字列リテラルのデコードを修正しました。申し訳ありません。

于 2015-06-10T07:52:25.927 に答える
1

UTF-8 は Windows コンソールでは機能しません。限目。すべての組み合わせを試しましたが、成功しませんでした。ANSI/OEM 文字の割り当てが異なるために問題が発生するため、問題はないと言う回答もありますが、そのような回答は、7 ビットのプレーン ASCII を使用するか、同一の ANSI/OEM コード ページ (中国語、日本語) を使用するプログラマーから得られる場合があります。

UTF-16 と wide-char 関数の使用に固執するか (ただし、OEM コード ページの 256 文字に制限されます- 中国語/日本語を除く)、ソース ファイルで OEM コード ページ ASCII 文字列を使用します。

はい、それはまったく混乱です。

多言語プログラムの場合、文字列リソースを使用し、中間バッファーLoadStringOem()を使用せずに UTF-16 リソースを OEM 文字列に自動変換する関数を作成しました。WideCharToMultiByte()Windows はリソースから適切な言語を自動選択するため、ターゲットの OEM コード ページに変換可能な言語で文字列を読み込むことが期待されます。

結果として、言語の一致が検出されない場合 (つまりフォールバック) に Windows によって英語と米国が選択されるため、英語と米国の言語リソースに 8 ビットのタイポグラフィ文字 (省略記号 ... および引用符 "") を使用しないでください。例として、ドイツ語、チェコ語、ロシア語、および英語-米国のリソースがあり、ユーザーが中国語を使用している場合、テキストを見栄えよくすると、適切に作成されたタイポグラフィではなく、英語とゴミが表示されます。

現在、Windows 7 および 10 では、SetConsoleOutputCP(65001/*aka CP_UTF8*/)期待どおりに動作します。ソース ファイルは BOM なしの UTF-8 で保持する必要があります。そうしないと、文字列リテラルがコンパイラによって ANSI に再コード化されます。さらに、コンソールのフォントには必要な文字が含まれている必要があり、「Terminal」であってはなりません。残念ながら、両方の言語パックをインストールしたとしても、ウムラウトと漢字の両方をカバーするフォントは存在しないため、すべての文字形状を一度に正確に表示することはできません.

于 2017-10-05T09:18:20.693 に答える