简体   繁体   中英

c++ getline() and file EOF

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 str is NULL , if str is not modified,why is null? but after if(sequenceNum>469) , the str become the last line.

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

The problem is when infile.getline reads the last line (ie it reads until EOF), while(infile) will still evaluate to true, causing the loop to be run again. However, since infile has read the entire file, infile.getline will fail, and str will 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.

Instead, you want something like:

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

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

Try this instead:

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

Yes, it helps

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

From the description I'm seeing, it looks like when it reaches the end of file before hitting a line terminator, eofbit gets 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.

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.

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.

So you could avoid the double line by checking infile.eof() instead. Unfortunately, you still lose 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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