In line 5 I read an integer and isint
is getting 1 if it reads an integer or 0 if it's not an integer. If isint
is 0 I have a loop asking user to give an integer and I read until the user gives an integer. I try this code giving a character instead of an integer but I have an infinite loop. The program just doesn't wait to give a new input. What's wrong with my code?
#include <stdio.h>
int main(void) {
int arg1;
//int arg2;
int attacknum = 1;
int isint = 1;
//printf("Insert argument attacks and press 0 when you have done this.\n");
printf("Attack %d\n", attacknum);
attacknum++;
printf("Give attacking argument:");
isint = scanf("%d", &arg1); //line 5
while(isint == 0){
printf("You did not enter a number. Please enter an argument's number\n");
isint = scanf("%d", &arg1);
printf("is int is %d\n", isint);
}
return 0;
}
In order to come out of the infinite loop, we can use the break statement. Let's understand through an example. In the above code, we have defined the while loop, which will execute an infinite number of times until we press the key 'n'. We have added the 'if' statement inside the while loop.
Explanation: The problem with the above code is scanf() reads an integer and leaves a newline character in the buffer. So fgets() only reads newline and the string “test” is ignored by the program.
Rule 1: scanf() is not for reading input, it's for parsing input. The first argument to scanf() is a format string, describing what scanf() should parse. The important thing is: scanf() never reads anything it cannot parse. In our example, we tell scanf() to parse a number, using the %d conversion.
This is correct, because, scanf() returns number of successfully matched and converted elements. Considering proper input in your case, every time your input passes the conversion, so you get to see the value 1.
As others have mentioned, if scanf
can't parse the input, it leaves it unscanned.
Generally scanf
is a poor choice for interactive input because of this kind of behavior, and because it doesn't match the line-at-a-time interface experienced by the user.
You are better off reading one line into a buffer using fgets
. Then parse that line using sscanf
. If you don't like the input, throw the whole line away and read another one.
Something like this:
#include <stdio.h>
int main(void)
{
char line[256];
int arg1;
int isint;
while (1) {
printf("Give attacking argument:");
fgets(line, sizeof line, stdin);
isint = sscanf(line, "%d",&arg1);
if (isint) break;
printf("You did not enter a number.Please enter an argument's number\n");
}
printf("Thanks for entering %d\n", arg1);
return 0;
}
(For production code you'll want to handle long lines, check return codes, also check for trailing garbage after the number, etc.)
Actually, an even better approach would be to not use scanf
if you just want to read an integer, and instead use strtol
. That gives you a handy pointer to the character just after the number, and you can check that it's whitespace or nul.
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