2

テキストファイルを読み取るが、最初の行を2回読み取る単純なコードを作成しようとしています。これはこのようなものと同じくらい簡単だと思いました

    std::ifstream file;
    file.open("filename", std::ios_base::in);
    std::string line;
    std::getline(file, line);
    // process line
    file.seekg(0, ios::beg);

    while (std::getline(file, line))
    {
        // process line
    }

ただし、最初の行は 2 回処理されないため、seekg は失敗するはずです。理由はありますか?

注意: これは私が直面している問題ではなく、複数のクラス コードと複数の関数を貼り付ける必要がないように簡略化したものです。実際の問題は、ファイル ポインタが複数のクラスの複数の関数に渡されることに関係しています。最初の関数は呼び出される場合と呼び出されない場合があり、ファイルの最初の行を読み取ります。2 番目の関数はファイル全体を読み取りますが、ファイルの先頭にいることを確認するために、まず seekg を呼び出す必要があります。

上記のコードを使用して、説明を簡単にしました。

4

2 に答える 2

3

最初に戻って最初の行を 2 回読むのではなく、次のような方法でアプローチすると思います。

std::ifstream file("filename");

std::string line;

std::getline(file, line);
process(line);

do { 
    process(line);
} while (getline(file, line));

現時点では、これは がprocess変更されないことを前提としていlineます (ただし、必要に応じて、最初の呼び出し用に追加のコピーを作成するのは簡単です)。

編集:編集された回答の変更された要件を考えると、シークが本当に必要なようです。clearその場合、続行する前にストリームに最もクリーンな可能性があります。

std::getline(file, line);
process1(line);

file.seekg(0);
file.clear();

process2(file);
于 2012-06-29T15:53:15.967 に答える
2

理想的には、コードは次のようになります。

std::ifstream file("filename"); //no need of std::ios_base::in

if ( file ) //check if the file opened for reading, successfully
{
   std::string line;
   if ( !std::getline(file, line) )
   {
        std::cerr << "read error" << std::endl;
        return;
   }

   // process line

   if ( !file.seekg(0, ios::beg) )
   {
        std::cerr << "seek error" << std::endl;
        return;
   }

   while ( std::getline(file, line) )
   {
      // process line
   }
}
else
{
   std::cerr << "open error" << std::endl;
}
于 2012-06-29T15:43:38.297 に答える