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

时间:2010-06-02 18:46:19

标签: c++

我正在使用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的小代码框中没有空行......) 因此,第一个文件有三行([“行A”,“行B”,“行C”]),第二个文件有四行([“行A”,“行B”,“行C”,“”] )

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

即使Python也有类似的行为(但它也给了我新行--C ++将它们删除了。)这是一个奇怪的事情,C ++预期行被终止,而不是由'\ n'分隔,我是以不同的方式喂养它?

修改

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

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

当然,YMMV关于新行是什么。

我一直认为这是两种完全不同的思想流派。我试图提出的一个更早的观点是询问C ++标准是否明确地或仅仅隐含地跟随第一个。

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

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

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

3 个答案:

答案 0 :(得分:3)

C ++标准可以说getline

  

C ++ 2003,21.3.7.9 / 5

     

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

     
      
  • 文件结尾出现在输入序列...
  •   
  • c == delim [ N.b.对于下一个可用输入字符'\n',默认分隔为c ](在这种情况下,c被提取但未被追加)
  •   
  • str.max_size()个字符存储
  •   

Bracketd编辑评论补充

用你的白话来说,getline'\n'视为终结者,而不是分隔符。

答案 1 :(得分:1)

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

为方便起见,您的编辑器在'C行'后面代表一个空行。如果你通过wc -l管道它的内容,你会发现它说3。

答案 2 :(得分:0)

当你说最后一行是空白的时候是什么意思?如果你的意思是倒数第二行以回车符/换行符结束,那么你在技术上没有最后一行,听起来像getline()的表现就像我期望的那样。

考虑你的例子:

Line A
Line B
Line C

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