1
#include <stdio.h>

#define MAXLINE 4096

int 
main(int argc, char **argv)
{
    char           *s;
    char            buf[MAXLINE];

    s = fgets(buf, MAXLINE, stdin);    // here, if replaced with read(0, buf, MAXLINE);        

    return 0;
}

Input is:12ctrl+d

  1. fgets doesn't return until input ctrl+d again(That is: 12ctrl+dctrl+d). Why doesn't fgets return when it encounts the first EOF? It seems 12ctrl+d doesn't work.

  2. But when s = fgets(buf, MAXLINE, stdin); is replaced with read(0, buf, MAXLINE); read will return(input is also: 12ctrl+d).

Siguza
  • 21,155
  • 6
  • 52
  • 89
hel
  • 581
  • 10
  • 26
  • Because they are different functions? Why do you expect them to behave identical? – too honest for this site Feb 21 '16 at 13:45
  • 2
    I think fgets should return when encounting EOF according to manual, but inputing 12`ctrl+d` fgets doesn't return. fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an `EOF` or a newline. – hel Feb 21 '16 at 13:54
  • 1
    The standard does not specify when it does detect eof. Try redirecting `stdin` from a file in your shell and you will see different behaviour. Itr is a matter of the console buffering. – too honest for this site Feb 21 '16 at 13:57
  • According to manual, fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. **Reading stops after an EOF or a newine.** – hel Feb 21 '16 at 14:02

2 Answers2

3

Hitting CTRL+d on the terminal:

  • simply means flush all the characters in stdin (the input buffer) immediately
  • it does NOT trigger an EOF condition on stdin
    (unless the current line/buffer is co-incidentally empty.)

So hitting CTRL+D while running a program,

  • a blocked fgetc() will return if you do it twice consecutively.
    1st = flush currently buffered characters,
    2nd = flush empty buffer; i.e. EOF condition is valid for fgetc() and it returns
    .
  • a blocked fgetc() will return if you do it once on an empty-line.
    flushes an already empty stdin buffer, i.e. EOF condition is valid for fgetc() and it returns.
  • a blockedread() returns immediately as soon as the input is flushed.

Checkout the answers to this question for more details.

Community
  • 1
  • 1
TheCodeArtist
  • 21,479
  • 4
  • 69
  • 130
  • This answer is similarly wrong as the linked-to answer: there is no EOF-character. Also: which "buffer" do you mean: the buffer used by the (pseudo-) terminal driver, or stdio's buffer? – wildplasser Feb 21 '16 at 15:04
  • Thanks @wildplasser. I have updated the answer to avoid ambiguity and the incorrect terminology. I hope its very clear now. – TheCodeArtist Feb 21 '16 at 15:09
3

In common implementations fgets is based on a loop around read. If you call fgets it calls read internally. Typing 12Ctrl+D makes read return the two characters "12" to fgets. That does not yet make a full line, so fgets calls read again. Since we're reading from a terminal device, and not a file for example, read waits for you to type more data. If you type Ctrl+D again, read returns 0 characters, which fgets interprets as an end of file and returns.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
Joni
  • 108,737
  • 14
  • 143
  • 193