Reputation: 145
I would like to have a better understanding of using fgets()
and stdin
.
The following is my code:
int main()
{
char inputBuff[6];
while(fgets(inputBuff, 6, stdin))
{
printf("%s", inputBuff);
}
return 0;
}
Let's say my input is aaaabbbb
and I press Enter. By using a loopcount, I understand that actually the loop will run twice (including the one I input aaaabbbb
) before my next input.
Loop 1: After I have typed in the characters, aaaabbbb\n
will be stored in the buffer of stdin
file stream. And fgets()
is going to retrieve a specific number of data from the file stream and put them in inputBuff
. In this case, it will retrieve 5 (6 - 1) characters at a time. So that when fgets()
has already run once, inputBuff
will store aaaab
, and then be printed.
Loop 2: Then, since bbb\n
are left in the file stream, fgets()
will execute for the second time so that inputBuff
contains bbb\n
, and then be printed.
Loop 3: The program will ask for my input (the 2nd time) as the file stream has reached the end (EOF
).
Question: It seems that fgets()
will only ask for my keyboard input after stdin
stream has no data left in buffer (EOF
). I am just wondering why couldn't I use keyboard to input anything in loop 2, and fgets()
just keep on retrieving 5 characters from stdin
stream and left the excess data in the file stream for next time retrieval. Do I have any misunderstanding about stdin
or fgets()
? Thank you for your time!
Upvotes: 4
Views: 6808
Reputation: 334
fgets()
does only read until either '\n'
or EOF
. Everything after that will be left in stdin
and therefore be read when you call fgets()
again. You can however remove the excess chars from stdin
by for example using getc()
until you reach '\0'
. You might want to look at the manpages for that.
Upvotes: 1
Reputation: 144740
The behavior of your program is somewhat more subtle than you expect:
fgets(inputBuff, 6, stdin)
reads at most 5 bytes from stdin
and stops reading when it gets a newline character, which is stored into the destination array.
Hence as you correctly diagnose, the first call reads the 5 bytes aaab
and prints them and the second call reads 4 bytes bbb\n
and prints them, then the third call gets an empty input stream and waits for user input.
The tricky part is how stdin
gets input from the user, also known as console input.
Both console input and stdin
are usually line buffered by default, so you can type a complete line of input regardless of the size of the buffer passed to fgets()
. Yet if you can set stdin
as unbuffered and console input as uncooked, the first fgets()
would indeed read the first 5 bytes as soon as you type them.
Console input is an intricate subject. Here is an in depth article about its inner workings: https://www.linusakesson.net/programming/tty/
Upvotes: 1
Reputation: 11921
Everything is there in manual page of fgets()
whatever you are asking. Just need to read it properly, It says
char *fgets(char *s, int size, FILE *stream);
fgets() reads in at most one less than sizecharacters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte (aq\0aq) is stored after the last character in the buffer.
If input is aaaabbbb
and in fgets()
second argument you specified size as 6
i.e it will read one less 5
character and terminating \0
will be added so first time inputBuff
holds aaaab
and since still EOF
or \n
didn't occur so next time inputBuff
holds bbb\n
as new line also get stored at last.
Also you should check the return type of fgets()
and check if \n
occurs then break the loop. For e.g
char *ptr = NULL;
while( (ptr = fgets(inputBuff, 6, stdin))!= NULL){
if(*ptr == '\n')
break;
printf("%s", inputBuff);
}
Upvotes: 1