1

The following output seems to suggest that when read () is called after a getchar() it clears all the stdin. Let's say that I typed "Hello\n" :

char buff; int c; c=getchar(); printf("%c\n",c); //output H int res; res=read(0,&buff,1); //no output, it prompts !! printf("%c\n",buff); 

However if I invert the functions the behaviour is different. Let's say I type "Hello\n" again :

 char buff; int res; res=read(0,&buff,1); printf("%c\n",buff); output H int c; c=getchar(); printf("%c\n",c); output e 

Could someone explain what's going on here ? I'm using Mac OS

5
  • 3
    read is unbuffered. So it is a bad idea to mix it with buffered IO. I'd guess getchar have already got all of the input into the buffer so nothing is left to read. Commented Apr 28, 2022 at 19:51
  • 1
    You can also use setvbuf( stdin, NULL, _IONBF, 0 ); to disable buffering. Commented Apr 28, 2022 at 20:03
  • 2
    Don't mix stdio and low level syscalls on the same descriptor. Just asking for trouble. Commented Apr 28, 2022 at 20:17
  • What does the comment "no output, it prompts !!" mean? In particular, what do you mean by "it prompts"? If you are entering input interactively, I would expect read to block. If the input stream is short and closed, I would expect read to immediately return without writing to buff and the subsequent printf to invoke undefined behavior. But there's no "prompt" anywhere. Commented Apr 29, 2022 at 15:05
  • read does nothing at all with the stdin buffer. It doesn't read from that buffer, nor does it flush or fill or update it in any way. Commented Apr 29, 2022 at 15:17

2 Answers 2

2

The following output seems to suggest that when read () is called after a getchar() it clears all the stdin. Let's say that I typed "Hello\n" :

Nope. You are intermixing calls to getchar() (a high level routine that is buffer based) and read() (a low level system call that is the one that reads everything)

This is what is happening:

  • You call getchar()
    • getchar() issues a system call read() to fill up the buffer and so, to get all the available input. The input is stored in a stdio buffer and the first character of the buffer is returned by getchar(). Successive calls to getchar() will return the next characters stored in the buffer, until it is exhausted, and then a second call to read() will be made.
  • You call read() Read has nothing to return, or the next input line will be returned, as all the characters following the first in the first line are still in the stdio buffer, awaiting for a new call to fread, fgetch, etc. (you can check this by calling getchar() again and see how this is true)

If you want to intermix calls, use fread() (which knows and uses the stdio buffer as getchar()) after getchar(), but not read().

When you invert the sequence, the read() call gives you all that has been read (no buffering in read()). when you do the getchar() a second read() is made (as the buffer is empty) to fill the buffer. So you get all data (you should have got it in the first case, if you had done more getchar()s after the first read, but in the wrong order, of course)

Sign up to request clarification or add additional context in comments.

Comments

0

if you still enter Hello\n with this code you will see :

1st getchar reads 1 char from stdin where Hello\n is buffered so it remain ello\n

2nd you ask read (which is a blocking function) to read from stdin so it wait for you to input some text (lets say you type "a\n") it will give you back the 'a'

then the last getchar will read from the buffered entry in 1st step output :

 H a a e int main() { char buff; int c; c=getchar(); printf("%c\n",c); //output 'H' int res; res=read(0,&buff,1); //it prompts the lettre you just entered here 'a' printf("%c\n",buff); c=getchar(); printf("%c\n",c); //output the rest of the buffered stdin 'e' return 0; } 

Comments