3

The following simple program would give an endless loop when the input is a character, though it meant to tell a character from a digit. How to test if scanf gets a character when it is supposed to be a digit using the return value of scanf?

#include <stdio.h>

int main() {
  int n;
  int return_value = 0;

  while (!return_value) {
    printf("Input a digit:");
    return_value = scanf("%d", &n);
  }

  printf("Your input is %d\n", n);

  return 0;
}
George
  • 3,384
  • 5
  • 40
  • 64
  • 1
    It's not an exception. It's a technical problem. – zubergu May 23 '14 at 09:42
  • read all inputs as strings, then check if string is numeric and if so, convert string to number. Use this two functions [isNumeric()](http://rosettacode.org/wiki/Determine_if_a_string_is_numeric#C) and [atof()](http://www.cplusplus.com/reference/cstdlib/atof/). – Matjaž May 23 '14 at 09:44
  • @TheDubleM Nice try! But what I really want to know is how to do the job using `scanf`. – George May 23 '14 at 09:46
  • @congliu `scanf` will read form stdin and than you have to process data you get – Matjaž May 23 '14 at 09:52
  • 2
    possible duplicate of [Why is scanf() causing infinite loop in this code?](http://stackoverflow.com/questions/1716013/why-is-scanf-causing-infinite-loop-in-this-code) – Matjaž May 23 '14 at 10:07

4 Answers4

7

As Joachim pointed in his answer that the character doesn't consumed by scanf here and lives in the buffer, on next iteration scanf again read the same character and again leave it to the buffer and so on. This results in infinite loop.

You need to consume this character before next iteration. Just place a getchar() after the line return_value = scanf("%d", &n);

return_value = scanf("%d", &n);
while(getchar() != '\n');     // will consume the charater
Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
1

You get an infinite loop because scanf doesn't consume the character, so the character will never leave the input buffer.

You can solve it by reading a line with e.g. fgets and then use sscanf on the line.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

Add second (nested loop ) loop that clears the input buffer before you try to read from it with another scanf.

I haven't done in a long time but it goes like that: #include

int main() {
  int n;
  int return_value = 0;

  while (!return_value) {
    printf("Input a digit:");
    return_value = scanf("%d", &n);
    // this loop will "eat" every character that's left in input buffer
    while(getchar() !='\n') {
    continue;
    }
  }

  printf("Your input is %d\n", n);

  return 0;
}

Basically, any function/method that clears the input buffer after fail will work the same way. Choose one you like the most.

zubergu
  • 3,646
  • 3
  • 25
  • 38
  • Edited, it's really simple but that's how I did it when I was starting with C. It's not the shortest way, but it gives you idea what's going on with buffered input and scanf. – zubergu May 23 '14 at 09:49
  • Seems like it stuck after inputting anything – George May 23 '14 at 15:05
  • 1
    oh i missed the comparison value, you compare result of getchar with new line character. Damn im C-rusty :) – zubergu May 26 '14 at 13:46
-1

You should really use TheDubleM's suggestion and check if buffer is numeric and if so use atoi on it. In what I put below you will not detect 8f8 as bad input but just read the 8.

#include <stdio.h>

int main() {
  int n;
  int return_value = 0;
  char buffer[1024];

  while (!return_value) {
    printf("Input a digit:");
    scanf("%1024s", buffer);
    return_value = sscanf(buffer, "%d", &n);
  }

  printf("Your input is %d\n", n);

  return 0;
}
Joel Dentici
  • 206
  • 2
  • 5