12

std::getline当它得到一个eof. 这就是我正在做的事情。

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
}

在上面的代码getline中抛出异常,因为它得到eof 如何处理这种情况?

编辑

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
坏比特:0

请注意,两者都已 设置。eofbitfailbit

也可以看看:

于 2012-08-04T11:05:44.860 回答
2

正如您所说,当流当前位于文件末尾的空白行时调用 getline 将同时设置 eofbit (因为它到达文件末尾)和 failbit (因为无法提取任何内容,甚至行分隔符) .

因此,如果您已将流设置为在设置失败位时引发异常,则在读取该空白行时会引发异常。

为了防止这种情况,您可以在调用 getline 之前查看流中的下一个字符:

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