1

先日、次のようなコードを書いていました。

wchar_t buffer[1024];
std::wifstream input(L"input.txt");

while (input.good())
{
    input::getline(buffer, 1024);
    // ... do stuff...
}

input.close();

への最初の呼び出しの後、正しいデータ (UTF-16 LE) バイトが含まれていることがわかりましたがgetline、 wchar_t 配列と見なされるbuffer代わりに、buffer魔法のようにバイト配列に変換されていました。私はreinterpret_cast<wchar_t *>(buffer)、私が望んでいた結果を得ました。

次にgetline... への次の呼び出しでは、バッファは再びバイト配列として認識されましたが、バイトが歪んでいました。が見られると0x31 0x00 0x32 0x00 0x33 0x00思っていたが、代わりに見た0x00 0x31 0x00 0x32 0x00 0x33

これで、文字に可変長エンコーディングが含まれている場合にどのようにゆがむかを理解できます...しかし、input.txt ファイル内のすべての文字は ASCII であるため、それぞれ 2 バイトでエンコードできます (UTF16-LE を使用)。なぜスキュー?

SOの回答者は、ストリームを次のように吹き込む必要があることを私に通知しました:

std::wifstream fin("text.txt", std::ios::binary);
// apply facet
fin.imbue(std::locale(fin.getloc(),
          new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>));

実際、これで私の問題は完全に解決されました。あなたが扱っているすべての文字が固定長エンコーディングを持っているのに、なぜ吹き込みが必要なのか理解できませんか?

次に、吹き込む 2 番目のパラメーターがメモリ リークを起こしているようです。スタックにオブジェクトを割り当て、std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>そのアドレスを imbue に渡すと、スタック変数がスコープ外になるまで (メインの右中括弧の直前)、すべてが機能しているように見えます。一部の関数が純粋仮想関数を呼び出しているというエラー メッセージが表示され、アプリケーションがクラッシュします。提供されたコードを使用し、代わりに main が戻る前にメモリで delete を呼び出すと、同じ動作が見られます。

コメントと回答をお寄せいただきありがとうございます。

4

1 に答える 1

1

ファイルには次のようなものが含まれています31 00 32 00 33 00 0A 00 34 00 ...0A改行文字です。

デフォルトのcodecvtファセットでは、各バイトが個別に Unicode に変換されます。そう31なるU+003100なるU+0000など。バイトgetlineで停止します。0A

次の呼び出しは、前の呼び出しがgetline中断されたところから続行されます。00U+0000

于 2013-11-01T01:50:45.120 に答える