0

I have the following code to ask a user for input (lowWarp). The input must be from 1.0 to 10.0. If I enter, say, 0.2, it allows me to attempt entering another value. However, if I enter something like 1/2 or asdf it starts endlessly looping. How do I prevent this and instead allow a proper value to be entered?

while (badData == true)
{
    printf("Enter the low warp factor; warp factor = \n");
    scanf_s("%f", &lowWarp);
    if (lowWarp < 1.0 || lowWarp > 10.0) //Determines if number is between 1.0 - 10.0
    {
        badData = true;
        printf("Invalid input! Range is 1.0 - 10.0.\n");
        lowWarp = 0.0;
    }
    else
    {
        badData = false;
    }
} 
  • 2
    Read input using `fgets()` and then parse it. – chux - Reinstate Monica Jan 20 '16 at 16:55
  • Possible duplicate of [Input validation using scanf()](http://stackoverflow.com/questions/15228388/input-validation-using-scanf) – perror Jan 20 '16 at 16:56
  • 2
    For interactive sessions always *read a whole line*. – Karoly Horvath Jan 20 '16 at 16:57
  • the `scanf_s()` will NEVER input the alpha char(s) when using '%f' (it will consume any white space) Strongly suggest checking the returned value (not the parameter value) to assure the operation was successful. (in this case the returned value should be 1.) When the returned value is not 1, clean the stdin with something like: `int ch; while( (ch = getchar()) != EOF && '\n' != ch );` – user3629249 Jan 21 '16 at 22:32

3 Answers3

1

scanf() wouldn't discard invalid input. So it's read again and again and results in an infinite loop. You can read a line using fgets() and parse it using sscanf():

   char line[1024];
   float lowWarp;

   fgets(line, sizeof line, stdin);

   if(sscanf(line, "%f", &lowWarp) != 1) {
     /* invalid */
   }
P.P
  • 117,907
  • 20
  • 175
  • 238
0

You could use the function isdigit(). If you do, take a look at the return value and use that for your checking.

Ben Love
  • 468
  • 9
  • 15
0

scanf_s("%f", &lowWarp); does not consume bad input as it repetitively looks for valid numeric input. Result: infinite loop when "asdf" entered and scanf_s() called again.

As good code that handles evil things a user may enter needs a number of tests, might as well make a helper function.

// 0:success or EOF
int Read_float(const char *prompt, float *dest, float min, float max) {
  for (;;) {
    char buf[100];
    fputs(prompt, stdout);
    fflush(stdout);
    if (fgets(buf, sizeof buf, stdin) == NULL) {
      return EOF;
    }
    char *endptr;
    double y = strtod(buf, &endptr);
    if (buf == endptr || *endptr != '\n') {
      continue; // only \n entered or invalid `chars` entered
    }
    if (y >= min && y <= max) {
     *dest = (float) y;
     return 0; // success
    }
  }
}  

float lowWarp;
if (Read_float("Enter the low warp factor; warp factor = \n", 
    &lowWarp, 1.0f, 10.0f) == EOF) {
  Handle_EOF();
}

float highWarp;
if (Read_float("Enter the high warp factor; warp factor = \n", 
    &highWarp, 10.0f, 100.0f) == EOF) {
  Handle_EOF();
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • As I am new to C, I am struggling to understand I3x's solution let alone the complexity of your code. I thank you immensely for your input and will spend the day on google reviewing your solution. – Chandler Pavia Jan 20 '16 at 17:27