Thread: EOF

  1. #1
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272

    EOF

    I've been looking for this information on the internet and i couldnt find a definitive answer.

    Can an EOF indicator occur before a \n character?

    I mean, can an input file have

    "stringEOF" this in itself, or does it always have a \n before an EOF

    "string\nEOF".

    I noticed that on WINDOWS, i cant press EOF before a \n character(or at the start of the file).

    Is that the same on UNIX Operating systems?

    If its not, then how do functions like gets() work there?

    Does it returns a NULL char for a input string like

    "stringEOF" or does it returns a pointer to "string" and the next call to gets returns a NULL because of EOF?

  2. #2
    Registered User
    Join Date
    Mar 2009
    Posts
    399
    EOF is never actually in the file; it is set by the function that does the reading when there's nothing left to read.

    Cprogramming.com FAQ > Definition of EOF and how to use it effectively

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    There is no general requirement that a file contain a '\n' character. This means, when reading a file, it is possible to encounter end of file before encountering a '\n'.

    If gets() encounters end of file, it returns NULL. So does fgets() - which is safer to use than gets().

    When gets() or fgets() are used to read input, and the last character is not a '\n', then the last line of input may be lost as the gets()/fgets() return NULL. That introduces an illusion that a '\n' is required before EOF. That behaviour is an artefact of how gets()/fgets() are specified in the C standard - specifically they look for '\n' to decide where the end of a line is - not a reflection of how data is stored in a file. Other functions in the C standard library work the same way when reading a text file.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  4. #4
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272
    When gets() or fgets() are used to read input, and the last character is not a '\n', then the last line of input may be lost as the gets()/fgets() return NULL.

    So how to avoid this issue?

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Well you could always read the man page:
    RETURN VALUES
    Upon successful completion, fgets() and gets() return a pointer to the
    string. If end-of-file occurs before any characters are read, they
    return NULL and the buffer contents remain unchanged. If an error
    occurs, they return NULL and the buffer contents are indeterminate. The
    fgets() and gets() functions do not distinguish between end-of-file and
    error, and callers must use feof(3) and ferror(3) to determine which
    occurred.

    Quzah.
    Hope is the first step on the road to disappointment.

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Tool View Post
    When gets() or fgets() are used to read input, and the last character is not a '\n', then the last line of input may be lost as the gets()/fgets() return NULL.

    So how to avoid this issue?
    Either ensure the last character in the file is a '\n' (under your control if you are writing the program that creates the file) or read the file one character at a time (eg using fgetc()) rather than using gets()/fgets().

    The key is to ensure your technique of reading your file is consistent with however the file is written. If you cannot guarantee the last character in the file is a '\n', then you should not be using gets()/fgets().
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by grumpy
    If you cannot guarantee the last character in the file is a '\n', then you should not be using gets()/fgets().
    You should not be using gets() anyway, but what is your reasoning here? Granted, this may mean that the format for reading and that for writing is slightly inconsistent, but Tool's fears are unfounded: the last line, even without a newline at the end, will not be lost.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272
    Upon successful completion, fgets() and gets() return a pointer to the
    string. If end-of-file occurs before any characters are read, they
    return NULL and the buffer contents remain unchanged. If an error
    occurs, they return NULL and the buffer contents are indeterminate. The
    fgets() and gets() functions do not distinguish between end-of-file and
    error, and callers must use feof(3) and ferror(3) to determine which
    occurred.

    It doesnt say anything about if end of file occurs AFTER some characters have been read.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Tool
    It doesnt say anything about if end of file occurs AFTER some characters have been read.
    You must have missed this statement: "Upon successful completion, fgets() and gets() return a pointer to the string."

    EDIT:
    Okay, I missed this:
    Quote Originally Posted by grumpy
    If gets() encounters end of file, it returns NULL. So does fgets() - which is safer to use than gets().

    When gets() or fgets() are used to read input, and the last character is not a '\n', then the last line of input may be lost as the gets()/fgets() return NULL. That introduces an illusion that a '\n' is required before EOF. That behaviour is an artefact of how gets()/fgets() are specified in the C standard - specifically they look for '\n' to decide where the end of a line is - not a reflection of how data is stored in a file. Other functions in the C standard library work the same way when reading a text file.
    Unfortunately, grumpy has fed you misinformation. Refer to the C standard in context:
    Quote Originally Posted by C99 Section 7.19.7.2
    Code:
    #include <stdio.h>
    char *fgets(char * restrict s, int n, FILE * restrict stream);
    Description
    The fgets function reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a new-line character (which is retained) or after end-of-file. A null character is written immediately after the last character read into the array.

    Returns
    The fgets function returns s if successful. If end-of-file is encountered and no characters have been read into the array, the contents of the array remain unchanged and a null pointer is returned. If a read error occurs during the operation, the array contents are indeterminate and a null pointer is returned.
    So, fgets() reads until a newline character or EOF is detected. Once characters are read, EOF does not mean failure, no more than detecting a newline means failure. It just means that there is no more input to read. You can ignore this whole business of the possible loss of the last line when EOF is reached since it will not happen.
    Last edited by laserlight; 02-21-2010 at 07:44 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I think they are "losing a line" because they're just checking for NULL and ending.
    Code:
    while( fread( ... ) != NULL )
    {
        copybuffersomeplace( buf );
    }

    Quzah.
    Hope is the first step on the road to disappointment.

  11. #11
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272
    Quote Originally Posted by quzah View Post
    I think they are "losing a line" because they're just checking for NULL and ending.
    Code:
    while( fread( ... ) != NULL )
    {
        copybuffersomeplace( buf );
    }

    Quzah.

    I checked with K&R. Line cannot be lost because fgets looks like this in the library:

    Code:
    char *fgets(char *s, int n, FILE *iop)
    {
         register int c;
         register char *cs;
         
         cs = s;
         while(--n > 0 && (c = getc(iop)) != EOF)
              if((*s++ = c) == '\n')
                    break;
         *cs = '\0';
         return (c == EOF && cs == s) ? NULL : s;
    }
    Notice the return conditions; c == EOF && cs == s. Meaning that it has to be a begining of the string. If some chars have been allready readen in the buffer, it will return the string not NULL.

  12. #12
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by Tool View Post
    I checked with K&R. Line cannot be lost because fgets looks like this in the library:
    I didn't say it was lost. I said you think it's lost because you're probably using a loop like the above, and not checking outside of the loop. Clearly you do not understand the above loop, which as I've said, is why you think you're losing data.


    Quzah.
    Hope is the first step on the road to disappointment.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by quzah
    I said you think it's lost because you're probably using a loop like the above, and not checking outside of the loop. Clearly you do not understand the above loop, which as I've said, is why you think you're losing data.
    I note that that loop uses fread rather than fgets, but even if we change it to use fgets, I do not see why the last line might be lost (or even appear lost). If a null pointer is returned, it means that either no characters has been read yet EOF was reached (thus the last line was read on the previous iteration, so checking the read buffer outside of the loop is not useful), or there was a read error (in which case you cannot continue reading anyway).

    As far as I can tell, this subtopic of the possible loss of the last line is due to misinformation and has no basis in fact, as long as you are using a standard conforming standard library implementation, and assuming that there is no read error that causes the reading to stop before completion. Tool's question about this is not based on the observation that data was lost, but is a reaction to the misinformation.
    Last edited by laserlight; 02-22-2010 at 07:01 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by laserlight View Post
    I note that that loop uses fread rather than fgets, but even if we change it to use fgets, I do not see why the last line might be lost (or even appear lost). If a null pointer is returned, it means that either no characters has been read yet EOF was reached (thus the last line was read on the previous iteration, so checking the read buffer outside of the loop is not useful), or there was a read error (in which case you cannot continue reading anyway).
    Yeah that was a typo/being tired on my part (fread vs fgets). I read it to be that it would return NULL if it hit EOF before it hit \n for some reason. I don't know why, tired I guess. I guess I was thinking along the lines of "how to count the number of lines in a file" issue where you're just checking for \n and the \n isn't the last character in the file issue.


    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. while ((c = getchar()) != EOF), AND cntrl z
    By Roger in forum C Programming
    Replies: 8
    Last Post: 10-21-2009, 09:25 PM
  2. EOF or not EOF?
    By CornedBee in forum Linux Programming
    Replies: 2
    Last Post: 09-14-2007, 02:25 PM
  3. EOF messing up my input stream?
    By Decrypt in forum C++ Programming
    Replies: 4
    Last Post: 09-30-2005, 03:00 PM
  4. whats the deal with EOF really ???
    By gemini_shooter in forum C Programming
    Replies: 7
    Last Post: 03-06-2005, 04:04 PM
  5. files won't stop being read!!!
    By jverkoey in forum C++ Programming
    Replies: 15
    Last Post: 04-10-2003, 05:28 AM