int flag = 0;
int price = 0;
while (flag==0)
{
printf(\"\\nEnter Product price: \");
scanf(\"%d\",&price);
if (price==0)
printf(\"input not
When you enter something that isn't a number, scanf
will fail and will leave those characters on the input. So if you enter hello
, scanf will see the h
, reject it as not valid for a decimal number, and leave it on the input. The next time through the loop, scanf
will see the h
again, so it just keeps looping forever.
One solution to this problem is to read an entire line of input with fgets
and then parse the line with sscanf
. That way, if the sscanf
fails, nothing is left on the input. The user will have to enter a new line for fgets
to read.
Something along these lines:
char buffer[STRING_SIZE];
...
while(...) {
...
fgets(buffer, STRING_SIZE, stdin);
if ( sscanf(buffer, "%d", &price) == 1 )
break; // sscanf succeeded, end the loop
...
}
If you just do a getchar
as suggested in another answer, then you might miss the \n
character in case the user types something after the number (e.g. a whitespace, possibly followed by other characters).
You should always test the return value of sscanf
. It returns the number of conversions assigned, so if the return value isn't the same as the number of conversions requested, it means that the parsing has failed. In this example, there is 1 conversion requested, so sscanf
returns 1 when it's successful.
The %d format is for decimals. When scanf fails (something other a decimal is entered) the character that caused it to fail will remain as the input.
Example.
int va;
scanf("%d",&va);
printf("Val %d 1 \n", val);
scanf("%d",&va);
printf("Val %d 2 \n", val);
return 0;
So no conversion occurs.
The scanf function returns the value of the macro EOF if an input failure occurs before any conversion. Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure
7.19.6. The scanf function - JTC1/SC22/WG14 - C
So you should note that scanf
returns its own form of notice for success
int scanf(char *format)
so you could have also did the following
do {
printf("Enter Product \n");
}
while (scanf("%d", &sale.m_price) == 1);
if(scanf("%d", &sale.m_price) == 0)
PrintWrongInput();
Also keep in the back of your head to try to stay away from scanf. scanf or scan formatted should not be used for interactive user input. See the C FAQ 12.20
It goes into an infinite loop because scanf() will not consumed the input token if match fails. scanf() will try to match the same input again and again. you need to flush the stdin.
if (!scanf("%d", &sale.m_price)) fflush(stdin);
Edit: Back when I first wrote this answer, I was so stupid and ignorant about how scanf()
worked.
scanf()
is not a broken function, if I don't know how scanf()
works and I don't know how to use it, then I probably haven't read the manual for scans()
and that cannot be scanf()
's fault.scanf()
works.When you use scanf("%d", &price)
in your code, the scanf()
tries to read in an integer
from the input, but if you enter a non numeric value, scanf()
knows it isn't the right data type, so it puts the read input back into the buffer, on the next loop cycle however the invalid input is still in the buffer which will cause scanf()
to fail again because the buffer hasn't been emptied, and this cycle goes on forever.
In order to tackle this problem you can use the return value of scanf()
, which will be the number of successful inputs read, however you need to discard the invalid inputs by flushing the buffer in order to avoid an infinite loop, the input buffer is flushed when the enter
key is pressed, you can do this using the getchar()
function to make a pause to get an input, which will require you to press the enter
key thus discarding the invalid input, note that, this will not make you press the enter
key twice whether or not you entered the correct data type, because the newline character
will still be in the buffer. After scanf()
has successfully finished reading the integer
from input, it will put \n
back into the buffer, so getchar()
will read it, but since you don't need it, it's safe to discard it:
#include <stdio.h>
int main(void)
{
int flag = 0;
int price = 0;
int status = 0;
while (flag == 0 && status != 1)
{
printf("\nEnter Product price: ");
status = scanf("%d", &price);
getchar();
if (price == 0)
printf("input not valid\n");
else
flag = 1;
}
return 0;
}
After the first number, a '\n' will be in the input buffer (the return you pressed to input the number), so in the second iteration the scanf call will fail (becouse \n isn't a number), scanf will not remove that \n from the buffer, so in the next iteration it will fail again and so on.
You can fix that by reading the '\n' with a getchar() call after scanf.
The "answers" that say it will because there is a '\n' in the buffer are mistaken -- scanf("%d", ...)
skips white space, including newlines.
It goes into an infinite loop if x
contains 0 and scanf
encounters a non-number (not just whitespace) or EOF because x
will stay 0 and there's no way for it to become otherwise. This should be clear from just looking at your code and thinking about what it will do in that case.