问题
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