andyzzsyk
andyzzsyk

Reputation: 1

How to prevent non-numeric input in C & ask user input again

Actually, I can easily found a similar question in Google, but it still can not solve my question.

How to prevent non-numeric input in C?

The upper-link is like a similar case.

Here is my code

#include <stdio.h>
int main()
{
    int n;
    printf("Enter 1 or 2?\n");
    scanf("%d", &n);
    while(n != 1 && n != 2)
    {
      printf("Please do not enter other characters\n");
      printf("Enter 1 or 2?\n");
      scanf("%d", &n);
    }
}

I hope if users enter other numbers(e.g. 1, 45, 656), characters (e.g. a, f, u, e), or string(e.g. apple), the upper program can print out an error message and ask for user input again.

Yes! if users enter other numbers, the program can do what I want. But! if users enter other characters, string, the program will keep looping.

What should I need to add to this program?

Upvotes: 0

Views: 2147

Answers (3)

Dario Rodriguez
Dario Rodriguez

Reputation: 812

fgets is the way to do this, but wanted to post something like this to actually avoid fgets as asked. It may be of some interest. The appending part should've been delegated to some function and buffer size may've not been 10. Anyways:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define endl "\n"

int main (void)
{
    int   my_char = 0;
    short     bad = 0;
    char     text[10];

    memset (text, 0, 10);
    printf ("enter number: ");

    while ( (my_char = getchar()) )
    {
        if ( my_char < '0' || my_char > '9' )
        {
            if ( my_char != '\n' ) bad = 1;
        }
        else
        {
            size_t len = strlen (text);
            char *strtemp = malloc (len + 2);
            strcpy (strtemp, text);
            strtemp [len] = my_char;
            strtemp [len + 1] = '\0';
            strncpy (text, strtemp, 9);
            free (strtemp);
        }

        if ( my_char == '\n' )
        {
            if ( bad )
            {
                printf ("enter again (just numbers): ");
                fflush (stdout);
                bad = 0;
                memset (text, 0, 9);
            }

            else break;
        }
    }

    printf ("entered: %s"endl, text);
}

Upvotes: 0

LEF
LEF

Reputation: 198

scanf is meant for formatted input, ie: you know what input will be received, in this case the user may enter something other than an int and your program breaks down. So to deal with that unknown treat the input as a string then analyze the string. In this case you could capture the input in buf and use the function atoi to convert it to an int, like this:

#include <stdio.h>
#include <stdlib.h> /* for atoi */

int main()
{
    int n;
    char buf[10]; /* this is new */ 
    printf("Enter 1 or 2\n");
    /*scanf("%d", &n);*/
    fgets(buf, 10, stdin);
    n = atoi(buf);
    while(n != 1 && n != 2)
    {
        printf("Please do not enter other characters\n");
        printf("Enter 1 or 2?\n");
        /*scanf("%d", &n);*/
        fgets(buf, 10, stdin);
        n = atoi(buf);
    }
}   

Upvotes: 0

chux
chux

Reputation: 153338

How to prevent non-numeric input in C & ask user input again

Do not use scanf()**. Use fgets().
scanf("%d", ...) does not consume non-numeric input. Instead that offending input remains in stdio for the next scanf().

Code cannot prevent non-numeric input unless it locks the keys from being pressed. Instead, read all input, identify the non-numeric text, toss it and present the user with feedback for new input.

Make a helper function to control impact on rest of code.

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>

// return -1 on EOF
int read_int_in_range(const char *prompt, const char *reprompt, int lo, int hi) {
  if (prompt) {
    fputs(prompt, stdout);
    fflush(stdout);
  }
  char buf[100];
  while (fgets(buf, sizeof buf, stdin)) {
    char *endptr;
    errno = 0;
    long val = strtol(buf, &endptr, 10);
    // no overflow, conversion occurred, in range 
    if (errno == 0 && endptr > buf && val >= lo && val <= hi) {
      // Tolerate trailing white-space.
      while (isspace((unsigned char ) *endptr)) {
        endptr++;
      }
      // No junk after the numeric text
      if (*endptr == '\0') {
        return (int) val;
      }
    }
    if (reprompt) {
      fputs(reprompt, stdout);
      fflush(stdout);
    }
  }
  return EOF; // or `INT_MIN` or TBD code to distinguish `int` from an error.
}

Usage

const char *prompt = "Enter 1 or 2?\n";
const char *reprompt = "Please do not enter other characters\n" "Enter 1 or 2?\n";
int n = read_int_in_range(prompt, reprompt, 1, 2); 

**I recommend to not use scanf() anywhere to read user input until ones understands its weaknesses and limitations.

Upvotes: 1

Related Questions