如何使getline与ios::exceptions一起玩得好?

How to make getline play nice with ios::exceptions?

提问人:scozy 提问时间:10/5/2020 更新时间:10/5/2020 访问量:295

问:

我正在尝试使用我需要能够循环使用的,但希望使用以下方法抛出异常:ifstreamgetlineios::exceptions

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::ifstream f;
    f.exceptions( std::ifstream::failbit | std::ifstream::badbit );

    try {
        f.open("data/all-patents.dat", std::ifstream::in);
    }
    catch (std::ifstream::failure e) {
        std::cout << "Caught exception opening: " << e.what() << "\n";
    }
    
    std::string l;
    while (!std::getline(f, l).eof()) {
        // do something
    }

}

但是当命中 EOF 时,它会抛出一个异常:getline

terminate called after throwing an instance of 'std::__ios_failure'
  what():  basic_ios::clear: iostream error

Program received signal SIGABRT, Aborted.
0x00007ffff7ad8615 in raise () from /usr/lib/libc.so.6

我可以通过抓住它来确认:

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::ifstream f;
    f.exceptions( std::ifstream::failbit | std::ifstream::badbit );

    try {
        f.open("data/all-patents.dat", std::ifstream::in);
    }
    catch (std::ifstream::failure e) {
        std::cout << "Caught exception opening: " << e.what() << "\n";
    }
    
    std::string l;
    try {
        while (!std::getline(f, l).eof()) {
            // do something
        }
    }
    catch (std::ifstream::failure e) {
        std::cout << "Caught exception reading: " << e.what() << "\n";
    }

}

输出:Caught exception reading: basic_ios::clear: iostream error

为什么 EOF 抛出异常,尽管我没有使用 in 的掩码?有没有办法让我继续使用,而不必将我的循环包含在 ?ifstream::eofbitios::exceptionsios::exceptionswhiletry

C++ 异常 ifstream eof getline

评论

0赞 scozy 10/5/2020
@TedLyngmo,我的理解是,我传递给的异常掩码定义了何时应该引发异常并排除异常。ios::exceptionseofbit
0赞 Ted Lyngmo 10/5/2020
"异常掩码确定流在发生错误时引发类型为失败的异常的错误状态。- 因此,您可以选择想要例外的州。
0赞 Ted Lyngmo 10/5/2020
无关:您的循环可能应该是 .我不确定你为什么最后有?while (std::getline(f, l))eof()
0赞 scozy 10/5/2020
@TedLyngmo,我测试在文件到达 EOF 时使条件为 false,因为返回 and 而不是 ..eof()whilegetlineifstreambool
0赞 Ted Lyngmo 10/5/2020
可以使用运算符 bool 在布尔上下文中进行测试,就像我展示的那样 - 这与 or 为 true 相同并返回。这通常是您想要对此类循环进行的测试。ifstreamnot f.fail()f.fail()truebadbitfailbit

答:

1赞 Ted Lyngmo 10/5/2020 #1

打开抛出异常,稍后在无法提取它将设置的任何字符时打开触发异常。failbitstd::getline(f, l)failbit

评论

1赞 scozy 10/5/2020
事实证明,点击 EOF 会同时设置 和 .我不知道。eofbitfailbit
0赞 Ted Lyngmo 10/5/2020
@scozy 它没有击中设置失败位的 EOF。按 EOF 仅设置 .它无法提取任何设置 .您可以点击 EOF 并设置提取字符。在这种情况下,将不会设置。eofbitfailbiteofbitfailbit