简体   繁体   中英

What happens when fgets encounters EOF in the middle of an input?

The man page says:

fgets() return s on success, and NULL on error or when end of file occurs while no characters have been read.

I wrote a small C file which calls fgets to test its behavior. I particularly wanted to see what happens when EOF occurs after some characters have been inputted. I used the eof key combination (Ctrl+D) on bash. I had to press Ctrl+D twice for fgets to return. It printed out the characters inputted until I pressed Ctrl+D twice. Pressing Ctrl+D once after some characters had been inputted had no effect at all. If I inputted some characters after this they were stored in the passed array. Why does fgets behave this way?

The behavior you describe has nothing to do with fgets. The shell does not close the input stream until you press ctrl-D the 2nd time.

You should find that if the input ends after at least some characters were read but before a newline is encountered that fgets returns non-null (a pointer to the supplied buffer) and the supplied buffer won't contain a newline but will be null terminated.

This is just what the documentation for fgets says.

Eg

#include <stdio.h>

int main(void)
{
    char buffer[200];

    char* ret = fgets(buffer, sizeof buffer, stdin);

    printf("exit code = %p\n", (void*)ret);

    if (ret != 0)
    {
        printf("read code = %s<--END\n", buffer);
    }

    return 0;
}

output:

$ printf "no newline here->" | ./a.out
exit code = 0x7fff6ab096c0
read code = no newline here-><--END

or:

$ printf "newline here->\nmore text\n" | ./a.out
exit code = 0x7fff6f59e330
read code = newline here->
<--END

on no input:

$ printf "" | ./a.out
exit code = (nil)

It's just like reading from text file stored on disk that doesn't happen to have a new-line character at the end of the last line. The C standard 's description of fgets() specifies what it does, including in this case:

char *fgets(char * restrict s, int n, FILE * restrict stream);

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.

fgets() can give you a string without a new-line if the input line is too long to fit, or if there's no new-line before end-of-file.

When you're reading from a disk file, an end-of-file condition occurs when you reach the end of the file. When you're reading from an interactive device such as a keyboard, the way an end-of-file condition is triggered is not specified by the C standard. On Unix-like systems, it's triggered by typing Control-D at the beginning of a line, or by typing Control-D twice in the middle of a line (though the control character can be reconfigured).

Whether this is even possible depends on the implementation.

C99 7.19p2 says:

A text stream is an ordered sequence of characters composed into lines, each line consisting of zero or more characters plus a terminating new-line character. Whether the last line requires a terminating new-line character is implementation-defined.

Unix-like systems generally don't require the trailing new-line character.

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