Reputation: 95
this code should read a positive number and if user enter a non-numeric value, it asking him again to enter a number and wait the input to check again till entering a number
do
{
printf("Enter a positive number: ");
}
while ( (scanf("%d%c", &n,&c) != 2 || c!='\n' || n<0) ) ;
but actually when entering non-numeric it keeps doing the body of the while loop without reading the waiting to check the condition of the while loop while(scanf("%d%c", &n,&c) != 2 || c!='\n' || n<0)
when edit the condition to
int clean_stdin()
{
while (getchar()!='\n');
return 1;
}
do
{
printf("Enter a positive number: ");
}
while ( (scanf("%d%c", &n,&c) != 2 || c!='\n' || n<0) && clean_stdin() ) ;
It executes in the right way, but I don't understand why we need to add getchar()
although we already use scanf()
in the condition
Upvotes: 1
Views: 2958
Reputation: 153457
When scanf("%d%c", ...
encounters non-numeric input, the "%d"
causes the scanning to stop and the offending character to remain in stdin
for the next input function. The "%c"
does not get a chance to read that non-numeric character.
If code re-reads stdin
with the same scanf("%d%c", ...
, the same result. Some other way is needed to remove the non-numeric input. getchar()
, getch()
, etc. will read any 1 character.
Example code GetPositiveNumber()
Upvotes: 3
Reputation: 7723
See this code
#include <stdio.h>
int
main(int argc, char* argv[]) {
char c = 0;
scanf("%c", &c);
printf("%c\n", c);
scanf("%c", &c);
printf("%c\n", c);
return 0;
}
If you type over two or three characters, second call of scanf doesn't work as interructive. And getch() is not standard. Also you shouldn't call getchar() since it may block. You can use fseek.
Hack using fseek works only on Windows. :-(
#include <stdio.h>
int
main(int argc, char* argv[]) {
char c = 0;
scanf("%c", &c);
printf("%c\n", c);
fseek(stdin, 0, SEEK_END);
scanf("%c", &c);
printf("%c\n", c);
return 0;
}
#include <stdio.h>
int
main(int argc, char* argv[]) {
char buf[BUFSIZ];
char c = 0;
scanf("%c", &c);
printf("%c\n", c);
while (!feof(stdin) && getchar() != '\n');
scanf("%c", &c);
printf("%c\n", c);
return 0;
}
This works good on Windows & Linux
Upvotes: 0
Reputation: 2508
Consider using fgets to collect input. Any invalid input is already removed from the input stream making it simpler to try again.
Parse the input with sscanf or others as needed.
char input[40] = "";
int valid = 0;
int n = 0;
do {
printf ( "Enter a positive integer\n");
if ( fgets ( input, sizeof ( input), stdin)) {
int last = 0;
if ( 1 == ( valid = sscanf ( input, "%d%n", &n, &last))) {
if ( n < 0 || input[last] != '\n') {
valid = 0;//reset if negative or last is not newline
}
}
}
else {
fprintf ( stderr, "problem getting input from fgets\n");
return 0;
}
} while ( valid != 1);
Upvotes: 2
Reputation: 53006
Because scanf()
with most specifiers ignores white spaces, and you need to collect them before calling scanf()
again if a '\n'
is left in the buffer. If you don't collect them (and discard them immediately), then scanf()
will return immediately on the next call.
Upvotes: 0