繁体   English   中英

getline()设置故障位并跳过最后一行

[英]getline() sets failbit and skips last line

我正在使用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在哪里终止或分开?)

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

C ++ 2003,21.3.7.9 / 5

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

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

添加了方括号内的编辑评论

要将它放在您的母语中, getline会将'\\n'视为终止符,而不是分隔符。

在您的两个数据集中,我只计算三行。 第一个数据集只是缺少第二个数据集中存在的行尾字符。

为了方便起见,您的编辑器在“ C行”之后代表一个空行。 如果通过wc -l用管道传输内容,则会发现它显示3。

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

考虑您的示例:

Line A
Line B
Line C

这实际上是三行以\\ r \\ n结尾,第三行的\\ r \\ n是将光标置于第四行的原因。 实际上没有第四行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM