EOF reading one more extra

This is a discussion on EOF reading one more extra within the C++ Programming forums, part of the General Programming Boards category; I am using eof in a while loop, and it is reading in one extra time at the true end ...

  1. #1
    Registered User
    Join Date
    Jul 2003
    Posts
    27

    EOF reading one more extra

    I am using eof in a while loop, and it is reading in one extra time at the true end of file, resulting in repeated data.

    I read the other posts on this, but could not figure out how to use fgets, which is how the FAQ explains it. is fgets C++ code or C?

    in short, is there another way to check for the end of file reliably? here's my code:

    while(!fIn.eof()) {
    fIn.get(ch);
    ++x;
    }

  2. #2
    Cat
    Cat is offline
    Registered User
    Join Date
    May 2003
    Posts
    1,571
    eof() doesn't return true until you've read one bad character from the end of the file. Just do this sort of thing instead:

    Code:
    while(fIn.get(ch), !fIn.eof()) {
      ++x;
    }

  3. #3
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    Yes, there is. When you are reading a file char by char, you do not read in EOF with the last char, like you would if you were reading word by word with the >> operator. So, when reading char by char, it takes one more loop to read in EOF and that extra time through the loop causes the last char to get duplicated.

    One way to solve that problem when reading char by char is this:
    Code:
    fIn.get(ch);
    while(!fIn.eof()) {
    fIn.get(ch);
    ++x;
    }

  4. #4
    Cat
    Cat is offline
    Registered User
    Join Date
    May 2003
    Posts
    1,571
    7Stud, that doesn't work for all problems of this type; you want to do the next read just before the end of the loop for a generic case. The following could work:

    Code:
    fIn.get(ch);
    while(!fIn.eof()) {
      ++x;
      fIn.get(ch); // The last line before the end of the loop
    }
    But it's simply easier to use the comma operator in the while() loop; it saves having to duplicate the fIn.get() line, and it ensures that the check for EOF is immediately after the get(). I still prefer to use my original suggestion:

    Code:
    while(fIn.get(ch), !fIn.eof()) {
      ++x;
    }
    but that is equivalent to the modified version of your code.

    BTW, if the goal is to get the size of a file, there are a lot faster ways to do it, look for seek methods, and seek to "zero bytes before the end of the file", then use a tell method to get the current position in the file.
    Last edited by Cat; 08-04-2003 at 01:52 PM.

  5. #5
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    ...or as the faq demonstrates, you can read in the char in the while loop condition:
    Code:
    char ch;
    
    while((ch=fIn.get()) != EOF)
    {
          x++;
    }
    The idea is that when reading char by char, you need to read in the char BEFORE testing for EOF to prevent duplicating the last character.

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    Cat,

    Comparing the code you posted to my example--the only difference is the order of the lines within the loop.

    ++x;
    fIn.get(ch);

    versus

    fIn.get(ch);
    x++;

    How can that make any difference?

  7. #7
    Cat
    Cat is offline
    Registered User
    Join Date
    May 2003
    Posts
    1,571
    I know, but in any case in which the character ch was actually used, like this:

    Code:
    fIn.get(ch);
    while(!fIn.eof()) {
      cout << ch;
      fIn.get(ch); // The last line before the end of the loop
    }
    the order is important. Best to put the lines always in the proper order (even better to put the read in the condition of the while() loop). This particular example is the exception, not the rule, because he didn't use ch within the loop body, which will be rare when iterating over characters in a file.

  8. #8
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    Thanks.

  9. #9
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Originally posted by 7stud
    ...or as the faq demonstrates, you can read in the char in the while loop condition:
    Code:
    char ch;
    
    while((ch=fIn.get()) != EOF)
    {
          x++;
    }
    The idea is that when reading char by char, you need to read in the char BEFORE testing for EOF to prevent duplicating the last character.
    The FAQ does not demonstrate that, 'cos it has a bug in it ! ch must be declared as an int, not a char. To understand why, read this

    Also, when using this:
    >>while(!fIn.eof())
    what happens if you get a read error before hitting eof?
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  10. #10
    Registered User
    Join Date
    Jul 2003
    Posts
    27

    confused

    i tried these methods (at least i think i did them right), and i'm still getting the same repeat of the last result at the end. here is the code i am doing now. i want to read in every two characters and print them to the file in reverse order. i tried the following to no avail, and i also tried it with the (fIn.get(cCh)) part removed.

    Code:
    while(fIn.get(cCh), !fIn2.eof()) {
         fIn2.get(xCha);
         fIn2.get(xChb); 
    	
         fout.put(xChb);
         fout.put(xCha);
    }
    any ideas?

  11. #11
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    Gah! eof is what you test after you are done reading the file to tell if the reason you are done is because you are at the end of the file or because something else has gone wrong.
    Code:
    char ch;
    while(is.get(ch)) { 
    // ch is good here
    }
    if(!is.eof()) {
    // Bad things have happened, but every
    // ch we used was good, up until this
    // point
    }
    There are many reasons to stop reading a file, particularly popular is if the file was never properly opened in the first place. If you must test something test is.good(). iff this is true then the last read has succeded and you have valid data to work with. It's also true if the runtime thinks that the next read will work, but your computer ain't psycic, always check before you use what you have read.

  12. #12
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    keithmolo, try
    Code:
    void rev(std::istream &is, std::ostream &os) {
        char ch1;
        while(is.get(ch1)) { 
            char ch2;
            if(is.get(ch2)) os << ch2 << ch1;
            else os << ch1;
        }
    }
    If afterwords is.eof() is true, then you have reversed the entire file to os. Both have to be binary or text, if you mix them you get garbage.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with reading strings and opening files PLEASE
    By green2black in forum C Programming
    Replies: 8
    Last Post: 11-17-2008, 05:46 PM
  2. fgetc and EOF
    By pic-o-matic in forum C Programming
    Replies: 18
    Last Post: 08-29-2008, 10:08 AM
  3. How to EOF??
    By Paul22000 in forum C Programming
    Replies: 5
    Last Post: 05-08-2008, 03:55 AM
  4. EOF Explanation Anybody?
    By blackcell in forum C Programming
    Replies: 1
    Last Post: 01-29-2008, 09:09 PM
  5. Reading encrypted data from file
    By cctoombs in forum C Programming
    Replies: 2
    Last Post: 02-13-2005, 02:59 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21