12

std::getline throws exception when it gets an eof. this is how I am doing.

std::ifstream stream;
stream.exceptions(std::ifstream::failbit|std::ifstream::badbit);
try{
  stream.open(_file.c_str(), std::ios_base::in);
}catch(std::ifstream::failure e){
  std::cout << "Failed to open file " << _file.c_str() << " for reading" << std::endl;
}
while(!stream.eof()){
  std::string buffer = "";
  std::getline(stream, buffer);
  //process buffer
  //I do also need to maintain state while parsing
}

In the above code getline is throwing exception as it gets eof How to handle this situation ?

EDIT

std::string buffer = "";
while(std::getline(stream, buffer)){
    //also causes getline to hit eof and throw
}
4

2 に答える 2

14

コードの最初で、ストリームの例外処理をアクティブにします。

stream.exceptions(std::ifstream::failbit|std::ifstream::badbit);

これで、浮動小数点値、整数、文字列などのフォーマットされたデータの抽出が失敗した場合、フェイルビットが設定されます。

eofbitは、入力操作が最後に到達したことを示します
          入力シーケンス;
failbitは、入力操作が期待値の読み取りに失敗したことを示します
          文字、または出力操作が生成に失敗したこと
          希望の文字。

getline(stream,buffer)ファイルの終わりに達すると実際に設定されますeofbitが、目的の文字(行)を抽出できなかったため、フェイルビットも設定されます。

別のtry-catch-blockをループにラップするか、フェイルビット例外を無効にします。

例:

#include <iostream>
#include <fstream>

int main(){
  std::ifstream stream("so.cc");
  stream.exceptions(std::ifstream::failbit|std::ifstream::badbit);
  std::string str;

  try{
    while(std::getline(stream, str));
  }catch(std::ifstream::failure e){
    std::cerr << "Exception happened: " << e.what() << "\n"
      << "Error bits are: "
      << "\nfailbit: " << stream.fail() 
      << "\neofbit: " << stream.eof()
      << "\nbadbit: " << stream.bad() << std::endl;    
  }
  return 0;
}

結果:

例外が発生しました:basic_ios :: clear
エラービットは次のとおりです。
フェイルビット:1
eofbit:1
badbit:0

の両方 が設定されていることに注意してください。eofbitfailbit

参照:

于 2012-08-04T11:05:44.860 に答える
2

あなたが言ったように、ストリームが現在ファイルの終わりの空白行に配置されているときにgetlineを呼び出すと、eofbit(ファイルの終わりに達するため)とfailbit(行区切り文字さえも抽出できなかったため)の両方が設定されます。

したがって、failbitが設定されているときに例外をスローするようにストリームを設定した場合、その空白行を読み取るときに例外がスローされます。

これを防ぐには、getlineを呼び出す前に、ストリーム上の次の文字を確認します。

std::string buffer = "";
while(stream.peek() != EOF && std::getline(stream, buffer)){
    //do something with the buffer
}
于 2020-03-26T13:30:44.003 に答える