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 the stack
        char str[256];
        while(!log.eof())
        {
            log.getline(str, 256);
            cerr << "str: " << str << endl;
            stk.push(static_cast<string>(str));
            // stk is a std::stack<std::string> member of the class this function
            // belongs to.
        }
        cerr << endl;

        /* Do some stuff with str and stk here */

        log.close();
        clearLogFile();
    }

    void Console::clearLogFile()
    {
        FILE* log;
        log = fopen("console.txt", "w");
        fclose(log);
    }

多くの場合、console.txtがreadLogFile呼び出されると空になります。while(!log.eof())その場合、ループは実行されないと思いますが、実行されます。ファイルには常に少なくとも1行、場合によっては2行の余分な空白行があり、入力がファイルから読み取られるとき、入力行は2つの空白行の間に挟まれます。この関数を数回呼び出した後、while(!log.eof())ループは無限ループに入り、ファイルから空白行を引き出します。プログラムの一般的な実行は次のようになります。

str: 

str: Player moved.@191 191 191 0 0 0
str: 

str: 
str: Player moved.@191 191 191 0 0 0 
str: 

str: // there should be a 'Player moved.' line in here
str:

str: // here as well
str:

str: // also here
str:

str: 
str: Player moved.@191 191 191 0 0 0 
str: 

str:
str:
str:
str:
str:
str:
(onto infinite loop)

誰かが私がここで間違っていることを見ることができますか?

編集:Amardeepが提案したように、私はwhile(!log.eof())ループをループに変更しましたdo{...}while(!log.fail);。これにより、無限ループの問題は修正されましたが、無関係な行は修正されませんでした。プログラムは以前と同じように動作しますが、一度無限ループに入った場合を除いて、次のように、入力を読み取る必要がある空白行のみを読み取ります。

str:

str:

str:

str: 
(etc.)
4

2 に答える 2

1

ファイルを読み取るための標準的なアンチパターン。

    while(!log.eof())
    {
        log.getline(str, 256);
        cerr << "str: " << str << endl;
        stk.push(static_cast<string>(str));
        // stk is a std::stack<std::string> member of the class this function
        // belongs to.
    }

これを試して:

    while(log.getline(str, 256))
    {
        cerr << "str: " << str << endl;
        stk.push(string(str));
    }

getline()メソッドがストリームへの参照を返すため、これは機能します。

ストリームがブールコンテキストで使用されると、ブールに変換されます(実際にはそうではありませんが、初心者にとっては同様です)。読み取り後もストリームが良好な状態にある場合(つまり、読み取りが機能した場合)、ストリームはtrueに変換されます。ストリームが悪い状態にある場合(つまり、読み取りが失敗した場合)、falseに変換されます。したがって、読み取りが機能した場合、ループに入ります。読み取りが失敗した場合(おそらくEOLが読み取られたため)、ループは開始されません。

読み取り(getline())後にeof()をテストしなかったため、バージョンが失敗したことに注意してください。これは、最後の適切な読み取りでEOFまでのすべての文字が読み取られるためです。ただし、これはeofフラグが設定されていないことを意味します。EOFフラグが設定されるのは、実際にEOFを超えて読み取ろうとするまでです(これは、最後の読み取り後に他のすべての文字を読み取った後に何かを読み取った場合にのみ発生します)。

PS。ストリームから文字列に読み込む無料の関数があります。

std::string line;
std::getline(log, line);
于 2010-06-24T20:42:13.923 に答える
1

読み取りを試みるまで、eof()ステータスは設定されません。読み取りループを変更してgetline()を実行し、eof()に依存するのではなく、fail()ステータスを確認する必要があります。これは、ファイルを読み取ろうとして失敗する可能性のあるさまざまなことをカバーしていません。

于 2010-06-24T19:09:36.563 に答える