Change this:
fgets(loop, 4, stdin);
to this:
fgets(loop, 5, stdin);
after, of course, setting the size of your buffer to 5, like this char loop[5]= "yes";
, in order to store the 3 characters of the word "yes", the newline fgets()
will read (since it's reading lines, right?), and the string NULL-terminator (as you already know).
To explain the behavior of your code, you have to understand @DavidBowling's comment:
Note that by using fgets(loop, 4, stdin);
, the newline is left in the input stream when "yes" is entered, so the next input call picks up this newline character.
Use this program to demonstrate that:
#include<stdio.h>
#include<string.h>
int main()
{
char loop[4]= "yes";
while(strcmp(loop,"yes")==0)
{
printf("Do you want to continue? [yes|no]: ");
fgets(loop, 4, stdin);
printf("|%s|\n",loop); // I surrounded the output, in order to catch the newline
}
return 0;
}
Output:
Do you want to continue? [yes|no]: yes
|yes|
Do you want to continue? [yes|no]: |
|
which shows that the newline character is left in the Standard Input (STDIN) buffer, and gets consumed with the second call to fgets()
. From the reference of the method:
Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.
A terminating null character is automatically appended after the characters copied to str.
Let's see what happens, step-by-step:
You type yes, and then hit Enter, which makes the Standard Input buffer look like this:
------------------
| y | e | s | \n |
------------------
and now the first call to fgets(loop, 4, stdin);
gets executed, which means that the method will try to read 3 (4 - 1) characters from STDIN. It reads y
, e
and s
, moves them from STDIN's buffer to your program's buffer you declared, named loop
, and then appends the string NULL terminator.
Now the STDIN buffer is:
------------------
| \n | | | |
------------------
and before the user has a chance to input, fgets(loop, 4, stdin);
is going to be executed (it's the method's duty to do so, since they are data waiting in STDIN's buffer to be consumed - if there were no data, then the method would patiently wait for the user to input something...).
Now, it copies the newline character into loop
, stops there, since now the STDIN buffer is empty, and eventually appends a string NULL terminator to loop
(at index 1).
and now the STDIN buffer is empty:
-----------------
| | | | |
-----------------
since there was no more input by the user - the code's flow moved after the while loop, since the loop's condition evaluated to false, when loop
was a string with the newline character as its first character.
PS: Removing trailing newline character from fgets() input.