getline()函数设置failbit并跳过最后一行。

3
我正在使用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++则将其切掉了)。这是一种奇怪的情况,C++预期行以终止,而不是以'\n'分隔,而我却以不同的方式提供它?

编辑

显然,我需要再详细解释一下。我遇到过两种确定文件中“行”的哲学:

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

当然,换行符的定义可能因人而异。

我一直认为这两种方法是完全不同的思想。我之前提出的一个观点是询问C++标准是明确还是隐含地遵循第一种方法。

因此,回到手头的问题,第二个示例可以被视为“A\nB\nC\n”,按照分隔哲学有行。现在,C++是否明确遵循了终止哲学,还是只是标准的方式?(他们在标准中没有记录太多的推理...)我不愿意说这是明确的,因为用C++很难告诉你是否有vim称为“noeol”的文件。(例如,Python保留了换行符,因此您可以以此方式确定)

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

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


是的,这只是一种解释问题。C++和许多其他编程语言都认为行以换行符为结尾,而不是换行分隔。例如文本编辑器通常不这样做,这很令人困惑,但这就是生活。 - j_random_hacker
从技术上讲,你并没有一个空的第四行。第三行只是以 '\n' 结尾,但第四行没有任何字符(因此没有第四行(无论你当前的文本编辑器告诉你什么))。在第四行添加一个空格,它就会按预期工作。 - Martin York
请参考此帖子:https://dev59.com/OKTia4cB1Zd3GeqP-ThN - jpo38
3个回答

4
C ++标准对于getline有如下规定:

C ++ 2003,21.3.7.9/5

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

  • 输入序列上出现文件结束符…
  • c == delim [N.b. default delim is '\n'](在这种情况下,c被提取但不被附加)。
  • 存储了str.max_size()个字符。

方括号内为编辑评论

简单来说,getline'\n'视为终止符而非分隔符。


对我来说,理解这个如何回答问题并不明显。思考终止符和分隔符之间的区别很有趣。在这里发布了一个单独的帖子:https://dev59.com/OKTia4cB1Zd3GeqP-ThN - jpo38

1

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

你的编辑器为方便起见,在“C行”后表示为空行。如果你通过管道将其内容传递给wc -l,你会发现它显示为3。


0

当你说最后一行是空白的时候,你指的是什么?如果你的意思是倒数第二行以回车/换行符结束,那么你实际上没有最后一行,而且getline()的行为听起来就像我所期望的。

考虑你的例子:

Line A
Line B
Line C

这实际上是三行以 \r\n 结尾的文本,第三行的 \r\n 是将光标放在第四行的原因。实际上并没有第四行。


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