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

做~自己de王妃 提交于 2021-01-29 19:11:21

问题


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?


回答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.




回答2:


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:


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


来源:https://stackoverflow.com/questions/65043036/how-to-prevent-non-numeric-input-in-c-ask-user-input-again

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!