0

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?

5
  • 2
    Use fgets to read the input. Then use sscanf to parse the string read with fgets. Check the return value of sscanf. It will be 1 if the input is a valid integer and 0 otherwise. Commented Nov 27, 2020 at 19:47
  • @kaylum Thankyou! But Ahh... can I do not use fgets? That because I have found on Youtube, if I need to use fgets, I need to declare a char array. It will affect my other function in my program... Commented Nov 27, 2020 at 20:17
  • 1
    It will affect my other function in my program. That doesn't sound like a good reason not to use fgets. Using fgets is the best way and if you think there's some problem that prevents you from doing that then please provide the exact details. I will bet that the reason is not actually valid. Commented Nov 27, 2020 at 20:18
  • 3
    Consider reading with fgets() and using strtol() to extract the value and allow you to check the next character that could not be converted. If the input was not good, it is really easy to loop and input another string. Commented Nov 27, 2020 at 20:25
  • Thanks! Let me try the fgets and improve my program first! In conclusion, it seems fgets is the best way to solve my program Commented Nov 28, 2020 at 2:44

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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

3 Comments

char buf[10]; is undersized for large good int (32-bit) which would need at least 13 for "-2147483648\n".
Input like "1x\n" or "1 2\n" and even maybe "4294967297\n" would pass here as atoi(buf) is good for good input and not informative on bad input.
You are 100% correct, but he is expecting 1 or 2. Also @andyzzsyk read up on atoi, it's awful, use strtol instead of atoi, but for the sake of simplicity I used atoi.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.