Reputation: 35255
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?
Upvotes: 4
Views: 4176
Reputation: 791849
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.
E.g.
#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)
Upvotes: 4
Reputation: 263257
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.
Upvotes: 2
Reputation: 212248
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.
Upvotes: 6