0

If user enters a character instead of a number, I want to give him another option to try once more but below code prints out "Invalid. Pls enter a number." forever if user enters a character instead of a number. Why doesn't it wait for the user to enter again? (scanf part is for that I assume)

#include <stdio.h>
long get_long(void);

int main(void) {
long start;

printf("Enter a number: ");
start = get_long();

return 0;
}

long get_long(void)
{
long num = 0;   
while (scanf("%ld", &num) != 1)
{       
    printf("Invalid. Pls enter a number.");
}

return num;
}
Applik
  • 411
  • 3
  • 11

3 Answers3

0

This is a common problem with scanf. (The question has been asked many times; there are probably duplicate answers.) The problem is that when you type simething that isn't a valid number, scanf fails (and returns 0), but it leaves the unmatched input on the input stream.

You have to flush the unread input somehow. One way is like this. Write the function

void flush_one_line()
{
    int c;
    while((c = getchar()) != EOF && c != '\n')
        { /* ignore */ }
}

This function reads and discards one line of input, up to a newline. (That is, it throws away anything and everything that the previous scanf call didn't read.)

Then modify your original program like this:

while (scanf("%ld", &num) != 1)
    {
    printf("Invalid. Please enter a number.");
    flush_one_line();
    }
Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • I don't think it's the adequate solution. The flaw of your idea can be tested like that type `2323q` as input, then again type `1212q`, it returns `1212`. But input includes non-digit char ?? – Soner from The Ottoman Empire Jun 10 '18 at 13:06
  • 1
    @snr You're right. The answer I've posted is a first step, to get the OP's program working, so that after a completely non-numeric input is entered, and the "Invalid" message is printed, the user is at least given another chance, instead if seeing an infinite number of "Invalid" messages. That's the problem the OP was asking about. – Steve Summit Jun 10 '18 at 13:09
  • @snr If you really want to validate the input, pretty much the only solution is to rewrite the program completely. And the first step is not to call `scanf`, because `scanf` is basically useless. But beginning programmers are always taught to use `scanf`, and if they just want to get their program working, they're not going to want a lecture about how `scanf` is useless and they should use something completely different, that they won't understand at all at first. (But this is all very unfortunate, because `scanf` *is* useless, and you have to wean yourself from it eventually.) – Steve Summit Jun 10 '18 at 13:12
  • "but it leaves the unmatched input on the input stream" do you mean that input buffer never cleared if I enter a character in my code but if I enter a digit it is consumed? Then using scanf inside while's condition part is not useful. Am I right? – Applik Jun 10 '18 at 14:45
  • @Applik When a `scanf` format directive fails to match -- for example, when the `%d` directive encounters a non-digit, yes, the unmatched characters are left in the input buffer. Checking `scanf`'s return value is useful and quite necessary, but checking it is only half the job; you then have to clear the erroneous input out of the input buffer somehow, such as with my "flush_one_line" function. (Did you try it?) See more explanation at for example [this question](https://stackoverflow.com/questions/1716013/). – Steve Summit Jun 10 '18 at 19:52
  • @Applik But in general, no, it turns out that `scanf` is not terribly useful for doing robust user input. Its error handling is poor, as this question demonstrates. If you want to validate the user's input, and give good feedback if the user makes a mistake, and let the user try again, it's extremely difficult to do the job with `scanf` alone, or even with `scanf` plus a bunch of supporting code around it trying to clean up after it. It's usually easier to read a line of input with `fgets`, and then parse it some other way (perhaps with `sscanf`). – Steve Summit Jun 10 '18 at 19:56
-1

like this. it executes while 2 times

    int i=1;
    while (i!= 2)
    {      scanf("%ld", &num) ; 
         if(num==1)
           break;
        printf("Invalid. Pls enter a number.");
    i++;
    }
jasinth premkumar
  • 1,430
  • 1
  • 12
  • 22
-1

Your logic behind the code was flawed. What you essentially did with your code is ask the while loop to work as long as correct input isn’t made.

while(incorrect input is made) {
    print
}

Proper solution would be along the lines of

while(number of tries > 0) {
    do operations
    check for right input, if it is correct break the loop, else keep on going
    decrement number of tries by one
}
Nothing Nothing
  • 126
  • 1
  • 8
  • Limiting the number of tries does not solve the fundamental problem being asked about (which is that the original program essentially ignores all of the extra tries). – Steve Summit Jun 10 '18 at 13:04