当异常掩码未设置为eofbit时,为什么getline()会抛出“std :: ios_base :: failure”?

9
请看下面的代码:

考虑以下代码:

    ifstream in;
    try {
        in.exceptions ( ifstream::failbit | ifstream::badbit );
        in.open(pConfLocation);
    } catch ( ifstream::failure e ) {
        throw std::runtime_error("Can't open configuration file\n");
    }

    vector<string> lns;
    string s;

    in.clear();
    while ( !in.eof() ){
        getline( in, s );
        boost::algorithm::trim(s);
        lns.push_back( s+='\n');
    }

所以:

  1. 我为了try-catch块的需要设置了如下的“异常掩码”(ifstream::failbit | ifstream::badbit)。文件可以正常打开。
  2. 在while{}块中,我知道文件到达末尾时会设置eofbit。但是

异常掩码是所有流对象的内部值,指定哪些状态标志必须在设置时引发异常。

我没有设置 ifstream::eofbit,但无论如何,在运行时会出现以下错误:

terminate called after throwing an instance of 'std::ios_base::failure'
  what():  basic_ios::clear
The program has unexpectedly finished.

我不理解这种行为。我尝试在while{}之前使用in.clear(),但没有效果。clear()本身设置了goodbit,据我所知,“标志必须抛出异常”(见上面的引用),但当goodbit被设置时,并没有导致抛出任何异常...
如果删除in.clear(),则会导致无限循环。
        in.exceptions ( ifstream::failbit | ifstream::badbit );

它可行。


如何使getline()在这种情况下工作?

1个回答

8
问题出在你的输入迭代。当最后一次读取到达EOF时才设置eofbit,而不是下一次读取只读取EOF时。当后者发生时,failbit同时被设置。请参见此处的讨论。
在你的特定情况下,如果文件以换行符结束(很可能是这样),则getline()将读取换行符并返回。但是,eofbit仍未设置。接下来的getline()直接遇到EOF,根据文档,“如果函数没有提取任何元素,则调用setstate(failbit)”。

1
@Razorfever,这里没有clean()成员函数,我猜你是指clear()clear()函数会清除状态位(eofbitfailbitbadbit),但不会影响异常掩码。 - Angew is no longer proud of SO
是的,我使用了clear(),抱歉[在Q中已修复]。可能是与问题相关的最后一个问题:是否有任何方法返回到设置异常掩码之前的状态? - Razorfever
我的意思是,如果删除“in.exceptions(ifstream::failbit | ifstream::badbit)”这一行,为什么在这段代码中就不会出现任何可见的错误。 - Razorfever
1
如果没有抛出异常,最后一个getline()(设置failbit的那个)将清除s,然后你会处理一个空字符串(将"\n"推入lns),但这个空字符串从未是输入的一部分。换句话说,你得到了虚假数据。 - Angew is no longer proud of SO
2
值得一提的是正确的循环形式应该是:while (getline( in, s )) { boost::algorithm::trim(s); lns.push_back( s+='\n'); } - Robᵩ
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接