c ++ getline()和文件EOF

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17971593/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:37:40  来源:igfitidea点击:

c++ getline() and file EOF

c++

提问by Aleeee

This problem has troubled me for a night.Thanks!

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

This code will write the last line in file twice.WHY?

此代码将在文件中写入最后一行两次。为什么?

#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;
}

After infile.getline(str,strSize);the stris NULL, if str is not modified,why is null? but after if(sequenceNum>469), the strbecome the last line.

之后infile.getline(str,strSize);strNULL,如果str没有被修改,为什么是空?但在 之后if(sequenceNum>469)str成为最后一行。

This code just write the last line only once.

这段代码只写了最后一行。

#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;
}

回答by Drew McGowen

The problem is when infile.getlinereads the last line (i.e. it reads until EOF), while(infile)will still evaluate to true, causing the loop to be run again. However, since infilehas read the entire file, infile.getlinewill fail, and strwill become an empty string. However, since your original code overwrites the first character, it gets rid of the null terminator, so it winds up reusing the contents from last time.

问题是当infile.getline读取最后一行时(即读取到 EOF),while(infile)仍然会评估为真,导致循环再次运行。但是,既然infile已经读取了整个文件,infile.getline就会失败,并且str会变成一个空字符串。但是,由于您的原始代码覆盖了第一个字符,因此它摆脱了空终止符,因此最终会重用上次的内容。

Instead, you want something like:

相反,你想要这样的东西:

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

回答by Beta

The trouble is that after you've read the last line, infilestill evaluates as true. Only after you try (and fail) to read another line will it evaluate to false; your forloop goes test-read-print, so it fails to read and prints the old contents of strbefore quitting.

问题在于,在您阅读完最后一行之后,infile仍然计算为true. 只有在您尝试(并失败)阅读另一行之后,它才会评估为 false;您的for循环进行测试读取打印,因此它无法str在退出之前读取和打印旧内容。

Try this instead:

试试这个:

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

回答by bruce

Yes, it helps

是的,它有帮助

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

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

回答by T.E.D.

From the description I'm seeing, it looks like when it reaches the end of file before hitting a line terminator, eofbitgets set. It doesn't say what the state of the output character string is in this case, so a possible implementation is that it may not be modified.

从我看到的描述来看,它看起来像在遇到行终止符之前到达文件末尾时eofbit被设置。它没有说明这种情况下输出字符串的状态,因此一个可能的实现是它可能不被修改。

So in that case, if you don't check for eof and just print the string, it may still have the contents that it had after the previous call.

因此,在这种情况下,如果您不检查 eof 并只打印字符串,它可能仍具有上次调用后的内容。

The check you are making on the stream is not "am I at the end of file?", but rather, "is the stream still in a valid state?" It only goes invalid if it hits EOF and then you attempt to read from it again.

您对流进行的检查不是“我在文件末尾吗?”,而是“流是否仍处于有效状态?” 只有当它遇到 EOF 时它才会无效,然后您尝试再次读取它。

So you could avoid the double line by checking infile.eof()instead. Unfortunately, you stilllose whatever was on that last line. To the best of my knowledge, the only way around that issue is to either insist nobody put any important characters on the last line, or to not use getline()for your input reading.

所以你可以通过检查infile.eof()来避免双线。不幸的是,您仍然会丢失最后一行的内容。据我所知,解决这个问题的唯一方法是坚持没有人在最后一行放置任何重要字符,或者不getline()用于您的输入阅读。