【问题标题】:getline() sets failbit and skips last linegetline() 设置故障位并跳过最后一行
【发布时间】:2010-06-02 18:46:19
【问题描述】:

我正在使用std::getline() 来枚举文件中的行,它大部分都在工作。然而,这让我很好奇 - std::getline() 正在跳过我文件中的最后一行,但前提是它是空白的。使用这个最小的例子:

#include <iostream>
#include <string>

int main()
{
        std::string line;
        while(std::getline(std::cin, line))
                std::cout << "Line: “" << line << "”\n";
        return 0;
}

如果我喂它:

Line A
Line B
Line C

我把那些台词拿回来了。但是这个:

Line A
Line B
Line C
[* line is present but blank, ie, the file end is: "...B\nLine C\n" *]

(很遗憾,我在 SO 的小代码框里不能有空行...) 所以,第一个文件有三行( ["Line A", "Line B", "Line C"] ),第二个文件有四行( ["Line A", "Line B", "Line C", ""] )

这对我来说似乎是错误的 - 我有一个四行文件,使用 getline() 枚举它会留下 3。真正让我摸不着头脑的是,这正是标准所说的应该做的。 (21.3.7.9)

即使 Python 也有类似的行为(但它也给了我换行符 - C++ 将它们切断了。)这是一些奇怪的事情吗?以不同的方式喂养它?

编辑

显然,我需要在这里扩展一下。我遇到了两种确定文件中“行”是什么的哲学:

  • 行由换行终止 - 在 Linux 等系统和 vim 等编辑器中占主导地位。由于没有最终的 '\n'(vim 中的“noeol”),可能会有一个稍微“奇怪”的文件。文件末尾不可能有空行。
  • 行由换行分隔 - 在我遇到的几乎所有 Windows 编辑器中都占主导地位。每个文件都是有效的,最后一行可以为空。

当然,YMMV 关于换行符是什么。

我一直将它们视为两种完全不同的思想流派。我之前试图提出的一个观点是,询问 C++ 标准是明确还是隐含地遵循第一个标准。

因此,回到手头的问题,第二个例子,可以被认为是“A\nB\nC\n”有四行,遵循分离的哲学。现在,C++ 是否明确遵循终止的哲学,或者这只是标准的方式? (他们没有在标准中记录太多推理......)我不敢说它是明确的,因为判断你是否有 vim 所谓的 C++ 的“noeol”文件有点痛苦。 (例如,Python 会保留换行符,因此您可以这样判断)

由于 Windows 中的所有内容都遵循分离的理念,因此我正在寻找比“两个示例都有 3 行”更深入的内容。

(奇怪的是,Mac 在哪里终止或分离?)

【问题讨论】:

  • 是的,这只是解释的问题。 C++ - 和许多其他语言 - 认为行是换行符终止的,而不是换行符分隔的。令人困惑的是,例如文本编辑器通常不会——但这就是生活。
  • 从技术上讲,您没有空白的第四行。第三行仅以 '\n' 结尾,但第四行没有字符(因此没有第四行(无论您当前的文本编辑器告诉您什么))。在第四行添加一个空格,它将按预期工作。

标签: c++


【解决方案1】:

C++ 标准对getline 有这样的说法:

C++ 2003, 21.3.7.9/5

[getline(is, str, delim)] ...从is中提取字符...直到发生以下任何情况:

  • 文件结束出现在输入序列上……
  • c == delim [注意默认 delim 是 '\n'] 用于下一个可用的输入字符 c(在这种情况下,c 被提取但不附加)
  • 存储str.max_size() 字符

已添加括号编辑 cmets

用你的语言来说,getline 将'\n' 视为终止符,而不是分隔符。

【讨论】:

【解决方案2】:

我在你的两个数据集中只计算了三行。第一个数据集只是缺少第二个数据集中存在的行结束字符。

为方便起见,您的编辑器在“C 行”之后表示一个空行。如果你通过 wc -l 管它的内容,你会发现它是 3。

【讨论】:

    【解决方案3】:

    当你说最后一行是空白时,你是什么意思?如果您的意思是倒数第二行以回车/换行结束,那么从技术上讲,您没有最后一行,听起来 getline() 的行为与我预期的一样。

    考虑你的例子:

    Line A
    Line B
    Line C
    

    这实际上是以\r\n 结尾的三行,而第三行的\r\n 是将光标放在第4 行。实际上没有第 4 行。

    【讨论】:

      猜你喜欢
      • 2016-03-24
      • 2018-11-12
      • 2011-12-12
      • 1970-01-01
      • 2019-07-09
      • 2018-01-18
      • 2021-05-02
      • 2015-06-24
      • 1970-01-01
      相关资源
      最近更新 更多