Chandler Pavia
Chandler Pavia

Reputation: 21

How to check for correct data input in C

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;
    }
} 

Upvotes: 0

Views: 112

Answers (3)

chux
chux

Reputation: 153338

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();
}

Upvotes: 0

P.P
P.P

Reputation: 121347

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 */
   }

Upvotes: 1

Ben Love
Ben Love

Reputation: 468

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

Upvotes: 0

Related Questions