-1

I am new to C and I am writing a "get_int" script. I am implementing a while loop to check the validty of the input. If it is not a valid input (not an integer) as checked by scanf(),then we reprompt the user for it. In the case I entered a number, it did print out the value I want. However, in the case I input a character or a string, it runs into a permanent loop of printing "x:" without lettting me check using scanf() the validity of the input.

My code runs as below:

#include <stdio.h>
#include <stdbool.h>

int main (void)
{
    int x;
    while (true)
    {
        printf("x: ");
        if (scanf("%i", &x) == 1)
        {
            break;
        }
    }
    printf("x: %i\n", x);
}

Sorry. I am kinda clueless here.

  • 1
    If the input isn't read by `scanf` it stays in the input buffer. You would need to remove it or it will continue to try and fail to read it forever. – Retired Ninja Aug 14 '23 at 04:52
  • [forcing the buffer to clear in scanf](https://stackoverflow.com/questions/58895644/forcing-the-buffer-to-clear-in-scanf) shows a couple of options. – Retired Ninja Aug 14 '23 at 04:55

1 Answers1

0

scanf() fails on invalid input. Input remains in the input buffer and the subsequent scanf() will fail for the same reason. Here is one way to clear the input buffer:

#include <stdio.h>
#include <stdbool.h>

int flush() {
    for(;;) {
        int c = getchar();
        if(c == '\n' || c == EOF)
            return c;
    }
}

int main (void)
{
    int x;
    while (true)
    {
        printf("x: ");
        if (scanf("%i", &x) == 1)
        {
            break;
        } else {
            printf("clearing failed input\n");
            if(flush() == EOF)
                goto out;
        }
    }
    printf("x: %i\n", x);
out:
    return 0;
}

and example run:

x: hello world
clearing failed input
x: <ctrl-d>clearing failed input
Allan Wind
  • 23,068
  • 5
  • 28
  • 38
  • I think you still have problems when the code encounters EOF. I think you need a check like `if (c == EOF) break;` after the while loop. Often that's not necessary, but with this code, you need to test for EOF at some point after `scanf()` fails to return `1` (it could return 0 or EOF). Although it is rarely correct to use `feof()`, you could use `else if (feof(stdin)) { printf("EOF encountered\n"); break; }` before the existing `else` clause. This is correct because you already know there's a problem of some sort, unlike `while (!feof(stdin)) { … }`. – Jonathan Leffler Aug 14 '23 at 05:10
  • 1
    @JonathanLeffler You closed the issue but I did tweak the answer. One probably should check the return value from the first `scanf()` against EOF, too. The cleaner option is to read a line deal with the EOF then, and use `sscanf()` to parse input. – Allan Wind Aug 14 '23 at 05:17