0

私のプログラムでは、stdoutをファイル「console.txt」に出力するようにリダイレクトしました。関数は次のようにそのファイルに書き込みます。

void printToConsole(const std::string& text, const TCODColor& fc, const TCODColor& bc)
    {
        // write the string
        cout << text << "@";

        // write the two color values
        cout << static_cast<int>(fc.r) << " "
             << static_cast<int>(fc.g) << " " 
             << static_cast<int>(fc.b) << " "
             << static_cast<int>(bc.r) << " "
             << static_cast<int>(bc.g) << " " 
             << static_cast<int>(bc.b) << " " << endl;
    }

そのファイルから次のような関数を読み取ります。

    void Console::readLogFile()
    {
        ifstream log("console.txt", ifstream::in);
        if(!log.is_open())
        {
            cerr << "ERROR: console.txt not found!" << endl;
            return;
        }

        // read new input into Console
        string str;
        while(getline(log, str))
        {
            cerr << "str: " << str << endl;
            /* do stuff with str here */
        }
        cerr << endl;

        log.close();
        clearLogFile();
    }


    void Console::clearLogFile()
    {
        ofstream("console.txt", ios_base::trunc);
    }

初めてreadLogFile、すべてが正常に動作します。しかし、その後、問題が発生し始めます。console.txtの最初の行に空白の文字列として読み込まれます。私はgvimでconsole.txtを開いた状態でプログラムをステップ実行し、プログラムがどのように変化するかを監視しました。初めて正常に機能したとき、console.txtは次のようになります。

  1 moved UP.@191 191 191 0 0 0
  2 Player moved.@191 191 191 0 0 0
~
~

あるべき姿です。その後、プログラムはに移動しclearLogFile、その後、console.txtは空になります。ただし、2回目に開くとifstream、console.txtは次のようになります。

  1 ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
    ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@moved UP.@191 191 191 0 0 0
  2 Player moved.@191 191 191 0 0 0
~
~

今回getlineは、最初の行をに読み込むstrときstrは空白です。不思議なことに、 gdbで調べたところ空であることがわかったとしても、このcerr << "str: " << str << endl;行はstr「movedUP。@ 191 191 191 000」と表示されます。str

誰もがここで何が起こっているのか知っていますか?

4

1 に答える 1

0

書き込み中のルーチンは、ファイルに再書き込みする前にファイルの位置をリセットしていません。結果として、ターゲットファイルへのオフセットから始まります。

書き込みを実行した後のcout.seekp(0)は、書き込みポインターをリセットし、ファイルの先頭から書き込みを再開すると思います。

ただし、ログファイルの内容と使用方法との整合性に関しては、おそらく多くの問題が発生するでしょう。

コメントボックスでフォーマットを取得できないため、ここにコメントを追加しました...

書き込みのたびにファイルポインタをリセットすることにより、出力ファイルには1行しかありません。書き込む前に必ず読んでおく必要があります。そうしないと、新しいデータが古いデータによって上書きされたり、さらに悪いことに部分的に上書きされたりする可能性があります。

例:1を書く:

Player moved 1 2 3 4

例:書き込み2:

Player fell over

去ります:

Player fell over
3 4

書き込まれたファイルで、ライターが2回目の書き込みを行う前にリーダーがそこに到達しなかった場合。

coutを使用するよりも、明示的なファイルを使用する方がよい場合があります。または、読み取り間の読み取り位置を覚えて、次の読み取りを実行する前にそれをシークすることもできますが、ログファイルは増え続けます。

HTH

于 2010-06-25T19:52:45.287 に答える