我正在尝试读取仅数字值,然后将使用
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));
由于某些原因而无法使用。
isdigit
用于测试字符值,以查看它是否代表数字字符-0-9
。它不会测试option
是否为数字。您想检查scanf
的返回值以查看转换是否成功。
int option;
int status;
do {
printf("Please choose an option:\n"
"0. Create Database\n"
"1.Add New Student \n"
"2. Show All Students \n"
"3.Delete Student\n"
"99.Exit\n");
status = scanf(" %d", &option);
} while (status != 1);
您可以(并且应该)根据需要添加其他错误处理。
您的主要问题是,如果scanf
由于某种原因而无法读取任何数字(例如,如果输入x
),它将返回零(成功扫描的项目数),而不是填充option
,(这是杀手er)将输入指针与开始之前的位置相同。
不幸的是,当您返回另一个数字时,它只会尝试重新读取有问题的数据,并且可能会在无限循环中终止,而又不允许更多的输入。
scanf
系列适用于格式化数据,而且几乎没有什么[[未格式化比用户输入的要多:-)
best
赌注将是使用坚如磐石的输入函数进入一行,然后只需检查line以查看其是否有效。可以找到这种功能here。将其结合到您的需求中将为您提供类似的东西:#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
的返回值,但对于我发布的代码,则没有必要,因为此时您已经确定要扫描的字符串是有效的一位数或两位数的数字。
isdigit仅用于检查单个字符,此处不应用于从scanf获得的int值。
要存档您的要求,我们可以使用scanf
获得一个字符串,然后使用strtol转换为int,检查endptr以确认是否存在任何无效字符。代码可能会这样: int option;
char str[8];
char *endp;
do{
printf("Please choose an option :\n0. Create Database\n1.Add New Student \n2. Show All Students \n3.Delete Student\n99.Exit\n");
scanf("%7s", str);
option = strtol(str,&endp,10);
} while (*endp);