c++ - getline 设置 failbit 和 eof

标签 c++ exception getline eof

我知道这种行为的起源,因为它已经在 SO 的多个帖子中得到了很好的解释,一些值得注意的例子是:

Why is iostream::eof inside a loop condition considered wrong?

Use getline() without setting failbit

std::getline throwing when it hits eof

C++ istream EOF does not guarantee failbit?

它也包含在 std::getline standard 中:

3) If no characters were extracted for whatever reason (not even the discarded delimiter), getline sets failbit and returns.

我的问题是如何处理这种行为,您希望您的流捕获所有情况下的 failbit 异常,但到达 eof 引起的情况除外,最后一行为空的文件。有什么明显的东西是我遗漏的吗?

MWE:

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


void f(const std::string & file_name, char comment) {

std::ifstream file(file_name);
file.exceptions(file.failbit);
    try {
          std::string line;

          while (std::getline(file, line).good()) {
          // empty getline sets failbit throwing an exception
            if ((line[0] != comment) && (line.size() != 0)) {
                std::stringstream ss(line);
                // do stuff
            }
        }
    }

    catch (const std::ios_base::failure& e) {
        std::cerr << "Caught an ios_base::failure.\n"
        << "Explanatory string: " << e.what() << '\n'
        << "Error code: " << e.code() << '\n';

        }
}


int main() {

    f("example.txt", '#');
}

example.txt 是一个制表符分隔的文件,最后一行只有 \n 字符:

# This is a text file meant for testing
0   9
1   8
2   7

编辑:

while(std::getline(file, line).good()){...} 复制了问题。

最佳答案

另一种避免设置failbit 的方法是简单地重构您的if 测试以检测空行 的读取。因为在这种情况下这是你的最后一行,你可以简单地 return 以避免抛出错误,例如:

    std::ifstream file (file_name);
    file.exceptions (file.failbit);
    try {
        std::string line;

        while (std::getline(file, line)) {
            // detect empty line and return
            if (line.size() == 0)
                return;
            if (line[0] != comment) {
                std::stringstream ss(line);
                // do stuff
            }
        }
    }
    ...

您的另一种选择是检查eofbit 是否在catch 中设置。如果设置了 eofbit——读取成功完成。例如

    catch (const std::ios_base::failure& e) {
        if (!file.eof())
            std::cerr << "Caught an ios_base::failure.\n"
            << "Explanatory string: " << e.what() << '\n'
            << "Error code: " /* << e.code() */ << '\n';
    }

关于c++ - getline 设置 failbit 和 eof,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50662874/

相关文章:

c++ - 以二进制形式打印文件

C++ map 定义基础

c++ - 使用带有 split_iterator 的分类器

c++ - 按值传递 std::function<bool (int)>

c# - 向自定义异常添加额外信息

php - 使用数组检索错误消息

php - PDO "exception safety"并将其写入 PHP 日志文件

c++ - 在这种情况下使用 cin 是正确的功能吗?

编码 getline() 实现 - Valgrind 错误

c++ - 在 C++ 中逐行读取并从行中获取单词