c - 仅在 C 中接受数值
问题描述
我正在尝试读取一个仅数字的值,然后该值将执行特定的函数,具体取决于使用
switch
语句的值。
我知道我可以使用while(option < 0 || option >3 || option != 99)
,但是有解决方法吗?
个人工作:
do
{
printf("Please choose an option :\n0. Create Database\n1.Add New Student \n2. Show All Students \n3.Delete Student\n99.Exit\n");
scanf("%d", &option);
} while (!isdigit(option));
由于某种原因,这不起作用。
解决方案
您的主要问题是,如果scanf
由于某种原因(例如,如果您输入x
)未能读取任何数字,它将返回零(成功扫描的项目数),而不是填充option
,并且(这是杀手)离开输入指针在与开始之前相同的位置。
不幸的是,这意味着,当您返回获取另一个数字时,它只会尝试重新读取有问题的数据,并且可能最终进入无限循环而不允许更多输入。
该scanf
系列适用于格式化数据,没有什么比用户输入更无格式的了 :-)
您最好的选择是使用坚如磐石的输入功能进入一条线,然后检查该线以查看它是否有效。可以在这里找到这样的功能。将其纳入您的需求将为您提供以下内容:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
#include <ctype.h> // only needed for isdigit, not for above code.
int main(void) {
int option;
do {
// Only allowed up to two characters (plus '\0').
char buff[3];
int result = getLine(
"Menu\n"
" 0. Create Database\n"
" 1. Add New Student\n"
" 2. Show All Students\n"
" 3. Delete Student\n"
" 99. Exit\n"
"Please choose option: ",
buff, sizeof(buff));
// No point continuing on EOF, input stream is closed.
if (result == NO_INPUT) {
puts("\n*** End of input");
return 1;
}
// All faults just restart operation: too long, too short,
// non-digits.
if (result == TOO_LONG) continue;
if (! isdigit(buff[0])) continue;
if (buff[1] != '\0' && ! isdigit(buff[1])) continue;
// Now get the integer representation and continue unless valid.
sscanf(buff, "%d", &option);
} while (option != 99 && (option < 0 || option > 3));
printf("You chose %d\n", option);
return 0;
}
而且,是的,我知道我说过你应该检查返回值,scanf
但在我发布的代码的情况下没有必要,因为你已经确定你正在扫描的字符串是有效的一或二数字。