1. ホーム
  2. c++

[解決済み] C++におけるファイルの終端

2022-03-07 20:27:10

質問

n×2の行列をそのままテキストファイルに保存しています。これをC++で読もうとすると

nb_try=0;
fin>>c_tmp>>gamma_tmp;
while (!fin.eof( ))      //if not at end of file, continue reading numbers
{
  // store
  cs_bit.push_back(c_tmp);
  gammas_bit.push_back(gamma_tmp);
  nb_try++;

  // read
  fin>>c_tmp;
  assert(!fin.fail( )); // fail at the nb_try=n   
  if(fin.eof( ))break;
  fin>>gamma_tmp; // get first number from the file (priming the input statement)
  assert(!fin.fail( ));    

}

最初のアサートは、nb_try==n のときに失敗し、つまり fin.fail( ) が真になります。これは、存在しない最初の数字を読み込もうとしたときに起こります。しかし、最後の数字を読み込んだ後、fin.eof( )が真にならないのはなぜでしょうか?存在しない最初の数字を読んだときだけ真になるということでしょうか?また、fin.fail()とfin.eof()が同時に真になるというのは本当でしょうか?

ありがとうございます、よろしくお願いします

解決方法は?

これは、ファイルを読み込む方法が間違っているのです。

while (!fin.eof( ))
{
      // readLine;
      // Do Stuff
}

標準的なパターンは

while(getlineOrValues)
{
    // Do Stuff
}

というわけで、あなたのコードをざっと見てみると、次のように書いた方が分かりやすいと思います。

while(fin>>c_tmp>>gamma_tmp)
{
    // loop only eneterd if both c_tmp AND gamma_tmp
    // can be retrieved from the file.

    cs_bit.push_back(c_tmp);
    gammas_bit.push_back(gamma_tmp);
    nb_try++;   
} 

問題は、EOFが真になるのは AFTER を越えて読もうとしたとき。ファイル内に読むべき文字が残っていないことと、EOFが真であることは同じではありません。しかし、EOFはまだ偽なので、コードはループに再突入します。c_tmpを読もうとすると、EOFがトリガーされ、アサートがうまくいかなくなります。

解決策は、読み取りをwhile条件として置くことです。読み込みの結果はストリームになります。しかし、ストリームが(while条件のような)ブーリアン文脈で使用される場合、それはブールのように使用できる型に変換されます(技術的にはそれはvoid*ですが、それは重要ではありません)。