getline()在读完最后一行后抛出basic_ios :: clear异常

时间:2016-11-12 09:33:46

标签: c++ qt exception-handling

我正在使用qtestlib,C ++(clang LLVM 8.0版)编写文件读取的单元测试。我有以下代码逐行读取文件。

std::ifstream infile;

try {
    infile.open(path.c_str());
    std::ios_base::iostate exceptionMask = infile.exceptions() | std::ios::failbit;
    infile.exceptions(exceptionMask);

} catch (std::ios_base::failure& e) {
    // print the exception
    qDebug() << "Exception caught: " << QString::fromStdString(e.what());
}

try {
    std::string line;
    while (std::getline(infile, line)) {
        // print the line
        qDebug() << QString::fromStdString(line);
    }

} catch (std::ios_base::failure& e) {
    qDebug() << "Exception caught: " << QString::fromStdString(e.what());
}

问题

上面的代码读取文件中的所有行并打印出来。但是在打印完最后一行后,它会抛出异常并打印以下内容,

  

捕获异常:“basic_ios :: clear”

我跟着很多线程,但找不到解决方案。为什么我会收到此错误?

2 个答案:

答案 0 :(得分:1)

阅读并打印完所有行后,while (std::getline(infile, line))仍会尝试读取另一行。如果它完全失败 - 读取零字符 - 它会设置failbit以表示其失败。

错误消息的奇怪部分是,尽管名称如此,basic_ios::clear可用于设置失败位,如果您使用exceptions启用了相同的位,也会引发异常。

答案 1 :(得分:1)

查看std::getline的文档。设置标志的场景:

  

failbit

     

获得的输入无法解释为此类对象的有效文本表示。在这种情况下,    distr 保留调用前的参数和内部数据。请注意,某些 eofbit 案例也会设置 failbit

最后一句话有点模糊,但可以解释观察到的行为。

我做了一些实验并找到了模式。首先,我以这种方式纠正了您的代码:

try {
    std::string line;
    while (std::getline(infile, line)) {
        // print the line
        qDebug() << QString::fromStdString(line);
        if (infile.eof()) {
            return;
        }
    }

} catch (std::ios_base::failure& e) {
    qDebug() << "Exception caught: " << QString::fromStdString(e.what());
}

现在如果输入文件以空行结束,我会得到一个例外,如果最后一行没有以&#34; \ n&#34;结束。 return打破了循环。

如果您尝试读取已经到达流末尾的流,则设置 falbit 。 没有&#34;如果&#34;检查你是否总是这样阅读并总是得到例外。

对于最后一行空,我有一些线索,但不知道如何很好地解释它。首先要检查其他平台/编译器的行为。