C++中的getline()和文件EOF

4

这个问题困扰了我一晚上。谢谢!

这段代码会把最后一行写入文件两次。为什么?

#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
const int strSize = 1000;
int main(int argc,char *argv[])
{
    ifstream infile(argv[1]);
    if(!infile)    cerr<<"infile error!"<<endl;
    ofstream outfile(argv[2]);

    int sequenceNum = 1;
    char str[strSize];
    while(infile){
        infile.getline(str,strSize);
        if(sequenceNum>469)
            str[0] = '2';
        else if(sequenceNum>67)
            str[0] = '4';
        else if(sequenceNum>1)
            str[0] = '1';
        else
            str[0] = '3';
        outfile<<str<<endl;
        ++sequenceNum;
    }
    return 0;
}

在执行 infile.getline(str,strSize); 后,如果未修改 str,那么它将变成 NULL。但是在执行 if(sequenceNum>469) 后,str 会变成最后一行。这段代码只会写入最后一行一次。
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
const int strSize = 1000;
int main(int argc,char *argv[])
{
    ifstream infile(argv[1]);
    if(!infile)    cerr<<"infile error!"<<endl;
    ofstream outfile(argv[2]);

    int sequenceNum = 1;
    char str[strSize];
    while(infile){
        infile.getline(str,strSize);
        if(strlen(str) != 0){//The key is this sentence.
            if(sequenceNum>469)
                str[0] = '2';
            else if(sequenceNum>67)
                str[0] = '4';
            else if(sequenceNum>1)
                str[0] = '1';
            else
                str[0] = '3';
            outfile<<str<<endl;
            ++sequenceNum;
        }
    }
    return 0;
}
4个回答

10

问题在于当infile.getline读取到最后一行(即读到EOF),while(infile)仍会返回true,导致循环再次执行。然而,由于infile已经读完整个文件,infile.getline将失败,str将变为空字符串。但是,由于您的原始代码覆盖了第一个字符,它会去掉空终止符,因此它最终会重用上次的内容。

相反,您需要像这样:

while (infile.getline(str, strSize)) {
    if (sequenceNum>469)
    ...
}

2

问题在于当你读完最后一行时,infile 仍然被评估为 true。只有在尝试(并失败)读取另一行之后,它才会评估为 false;你的 for 循环是测试-读取-打印,所以它未能读取并在退出之前打印了 str 的旧内容。

改用以下代码:

while(infile.getline(str,strSize))
  ...

0

是的,它有帮助。

while(infile.getline(str,strSize)) ...


-1
从我看到的描述来看,当它在没有遇到行终止符之前到达文件末尾时,eofbit会被设置。它没有说明在这种情况下输出字符字符串的状态是什么,因此可能的实现是它可能不会被修改。
因此,在这种情况下,如果您不检查eof并只打印字符串,则它可能仍然具有先前调用后的内容。
您正在对流进行的检查不是“我是否已经到达文件结尾?”,而是“流是否仍处于有效状态?”只有在它遇到EOF然后再次尝试从中读取时才会变为无效。
因此,您可以通过检查infile.eof()来避免双行。不幸的是,您仍然会失去最后一行上的任何内容。据我所知,解决这个问题的唯一方法是要么坚持没有人在最后一行上放置任何重要字符,要么不使用getline()进行输入读取。

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