After a call to scanf("%d", &variable);
we are left with a newline hanging at the stdin, which should be cleared before a call to fgets
, or we end up feeding it a newline and making it return prematurely.
I've found answers suggesting using scanf("%*[^\n]%*c");
after the first call to scanf
to discard the newline and others suggesting using scanf("%*[^\n]\n");
. Theoretically, both should work: The first would consume everything that isn't a newline (but not including the newline itself) and then consume exactly one character (the newline). The second would consume everything that isn't a newline (not including it) and then \n
, a whitespace character, would instruct scanf
to read every whitespace characters up to the first non-whitespace character.
However, as much as I've seem those approaches working in some answers, I couldn't get them to work here (codes below).
Why neither of the scanf
approaches worked?
Tested on:
Ubuntu Linux - gcc
5.4.0
scanf("%*[^\n]\n");
approach:#include <stdio.h>
int main(int argc, char **argv){
int number;
char buffer[1024];
printf("Write number: \n");
scanf("%d", &number);
//Clearing stdin?
scanf("%*[^\n]\n");
printf("Write phrase: \n");
fgets(buffer, 1024, stdin);
printf("\n\nYou wrote:%u and \"%s\"\n", number, buffer);
return 0;
}
$ ./bug
Write number:
2
Write phrase:
You wrote:2 and "
"
scanf("%*[^\n]%*c");
approach:#include <stdio.h>
int main(int argc, char **argv){
int number;
char buffer[1024];
printf("Write number: \n");
scanf("%d", &number);
//Clearing stdin?
scanf("%*[^\n]%*c");
printf("Write phrase: \n");
fgets(buffer, 1024, stdin);
printf("\n\nYou wrote:%u and \"%s\"\n", number, buffer);
return 0;
}
$ ./bug2
Write number:
3
Write phrase:
You wrote:3 and "
"
The following approach was the only one that worked the way it was expected to:
#include <stdio.h>
int main(int argc, char **argv){
int number;
char buffer[1024];
printf("Write number: \n");
scanf("%d", &number);
//Clearing stdin!
int c;
while((c = getchar()) != '\n' && c != EOF){
//Discard up to (and including) newline
}
printf("Write phrase: \n");
fgets(buffer, 1024, stdin);
printf("\n\nYou wrote:%u and \"%s\"\n", number, buffer);
return 0;
}
$ ./notbug
Write number:
4
Write phrase:
phrase :D
You wrote:4 and "phrase :D
"
The basic problem is that the scanf pattern %[^\n]
matches ONE OR MORE characters that are not newlines. So if the next character is a newline, the pattern will fail and scanf
will return immediately without reading anything. Add a *
doesn't change that basic fact. So it turns out you can't do this with only one call, you need two:
scanf("%*[^\n]"); scanf("%*c");
Note that putting a bare newline into the scan pattern is almost always not useful -- it causes scanf to read and discard all whitespace until it sees a non-whitespace character (which will be left in the input buffer). Particularly if you try to use it in an interactive program, it will appear to hang until you enter a non-blank line.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With