【问题标题】:std::getline() is not reading last line of input file that has no '\n'std::getline() 没有读取没有 '\n' 的输入文件的最后一行
【发布时间】:2024-06-10 04:30:01
【问题描述】:

试图读取/打印文件的内容,其中最后一行不以“\n”结尾。程序只是错过了这些数据

while ( !readFile.eof() ) {
    string s;
    getline( readFile, s );
    if ( readFile.eof() ) break;
  //operate on data...
    cout << s << endl;
}

【问题讨论】:

    标签: newline eof getline


    【解决方案1】:

    请参考Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?

    您需要将std::getline() 调用直接移动到while 语句中:

    string s;
    while ( getline( readFile, s ) ) {
      //operate on data...
      cout << s << endl;
    }
    

    循环将一直运行,直到到达EOF 并且没有更多数据要读取。最后一行是否用换行符分隔无关,因为std::getline() 会做正确的事情并返回最后一行的数据,即使它没有分隔。

    所以,std::getline() 实际上确实返回了最后一行,即使它没有分隔,但你只是忽略它,因为这个逻辑:

    getline( readFile, s );
    if ( readFile.eof() ) break;
    //operate on data...
    

    如果最后一行没有分隔,则提前打破你的循环,因为std::getline() 在阅读时遇到readFile 时会将eofbit 设置为EOF,但s 实际上会包含最后一行的数据,然后您将其忽略。

    通过将std::getline() 直接移动到while 语句中,它将依赖流的bool conversion operator,如果设置了eofbit 并且没有设置任何错误标志(@ 987654342@ 或 badbit),允许循环处理非定界行。当下一次循环迭代尝试读取过去的EOF 时,std::getline() 将在流上设置failbit,导致bool 运算符返回false,从而中断循环。

    【讨论】:

    • 此方法仅在最后一行数据包含'\n'时才有效
    • @RoccoRuscitti 这不是真的。如果最后一行没有换行符,std::getline() 将简单地读取直到 EOF,在流上设置eofbit,并返回它读取的任何内容。当仅设置 eofbit 时,流的 bool 运算符返回 true,因此循环不会在 EOF 本身上中断。只有当std::getline() 尝试读取过去的 EOF 时,failbit 才会被设置在流上,bool 运算符才会返回 false,从而中断循环。
    • 我希望这是真的,但我今天写的程序并没有产生这个结果,除非我使用三元条件
    • @RoccoRuscitti 请参阅我对您关于三元运算符的回答的评论。它没有做你认为它做的事
    • 我知道发生了什么:当我使用您的解决方案时,我忘记使用打印功能重新编译我的 .cpp 文件,然后我再次尝试使用三元运算符,所以它似乎不起作用,但是正如您所说,三元解决方案是具有冗余的相同解决方案
    最近更新 更多