如何检查和验证用户输入是两个有效选择之一
How to check and validate user input is one of two valid choices
我有以下代码要求用户输入 A 或 P。我对小时和分钟有相同类型的设置,其中小时在 1 到 12 之间,分钟在 0 到 59 之间。那部分我的代码完全有效。
我的问题是我不知道如何检查 timePeriod 变量是什么并确保它是 A 或 P 并打印一条错误消息并再次提示它是否是其他任何东西,包括小写 a 和 p .用户输入必须是大写字母,并且只能是 A 或 P。
我这里只放了功能代码。我还添加了 clean_stdin 代码,因此 getTimePeriod 中的 while 语句可能更容易理解。正如我之前所说,我在小时和分钟上都使用了类似的设置,这很有效。
char getTimePeriod(void)
{
char timePeriod, term;
while ( (((scanf("%c%c",&timePeriod,&term)!=2 || term !='\n') && clean_stdin()) || timePeriod != "A" || timePeriod != "P") && printf("Invalid value entered. Must be A or P. Please re-enter: ") );
return timePeriod;
}
int clean_stdin()
{
while (getchar()!='\n');
return 1;
}
编辑: 对于那些因为这是糟糕的代码而感到内裤扭曲的人,根据我对 C 简介的作业要求,它对我有用当然。希望这也能澄清这个问题的新手性。
另请注意
timePeriod != 'A'
不起作用。我不知道为什么,但它不起作用。
建议将用户输入与验证分开。
scanf()
尝试同时执行这两项操作。如果仅读取一行输入(fgets()
- 标准或 getline()
常见 @Jonathan Leffler)然后通过各种方式解析,则处理潜在的错误用户输入会更容易。
// return choice or EOF
int GetChoice(const char *prompt, const char *reprompt, const char *choices) {
char buf[10];
puts(prompt);
while (fgets(buf, sizeof buf, stdin)) {
buf[strcspn(buf, "\n")] = 0; // drop potential trailing \n
char *p = strchr(choices, buf[0]);
if (p && buf[1] == '[=10=]') {
// Could fold upper/lower case here if desired.
return *p;
}
puts(reprompt);
}
return EOF;
}
int timePeriod = GetChoice("TimePeriod A or P", "Try Again", "AP");
switch (timePeriod) {
case 'A' : ...
case 'P' : ...
default: ...
可以添加额外的检查。这是将其转为辅助函数的最佳部分,它可以在代码中的多个位置使用,并根据需要以本地化方式进行改进。
OP代码注释:
用户输入不符合预期,不清楚 OP 的复杂 while()
条件是否会正确清空用户的输入行。如果遇到 EOF
或者第一个 char
是 '\n'
.
肯定有问题
timePeriod != "A"
@Alan Au 所评论的不是所需的代码。将 timePeriod
与字符串 "A"
的地址进行比较。使用 timePeriod != 'A'
.
clean_stdin()
应该是 clean_stdin(void)
。它是 EOF 上的无限循环。考虑:
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
您遇到的问题在这里:
timePeriod != "A" || timePeriod != "P"
首先,如前所述,您不能将字符与字符串进行比较。您需要使用单引号而不是双引号。假设已更正,此条件将始终为真,因为 timePeriod
将始终不是 'A'
或不是 'P'
。这需要是逻辑与:
(timePeriod != 'A' && timePeriod != 'P')
另请注意,添加了一组额外的括号以确保保留 while
表达式中的运算顺序。
关于 "cute" 注释,这意味着在 while
表达式中塞进一堆语句并将正文留空会使您的代码难以阅读,因此更容易出现错误。如果你把它分解成多个语句,每个语句都做一件合乎逻辑的事情,你就更有可能自己发现这个错误。 Olaf 发表评论主要是为了警告其他看到您的代码的用户。
我有以下代码要求用户输入 A 或 P。我对小时和分钟有相同类型的设置,其中小时在 1 到 12 之间,分钟在 0 到 59 之间。那部分我的代码完全有效。
我的问题是我不知道如何检查 timePeriod 变量是什么并确保它是 A 或 P 并打印一条错误消息并再次提示它是否是其他任何东西,包括小写 a 和 p .用户输入必须是大写字母,并且只能是 A 或 P。
我这里只放了功能代码。我还添加了 clean_stdin 代码,因此 getTimePeriod 中的 while 语句可能更容易理解。正如我之前所说,我在小时和分钟上都使用了类似的设置,这很有效。
char getTimePeriod(void)
{
char timePeriod, term;
while ( (((scanf("%c%c",&timePeriod,&term)!=2 || term !='\n') && clean_stdin()) || timePeriod != "A" || timePeriod != "P") && printf("Invalid value entered. Must be A or P. Please re-enter: ") );
return timePeriod;
}
int clean_stdin()
{
while (getchar()!='\n');
return 1;
}
编辑: 对于那些因为这是糟糕的代码而感到内裤扭曲的人,根据我对 C 简介的作业要求,它对我有用当然。希望这也能澄清这个问题的新手性。
另请注意
timePeriod != 'A'
不起作用。我不知道为什么,但它不起作用。
建议将用户输入与验证分开。
scanf()
尝试同时执行这两项操作。如果仅读取一行输入(fgets()
- 标准或 getline()
常见 @Jonathan Leffler)然后通过各种方式解析,则处理潜在的错误用户输入会更容易。
// return choice or EOF
int GetChoice(const char *prompt, const char *reprompt, const char *choices) {
char buf[10];
puts(prompt);
while (fgets(buf, sizeof buf, stdin)) {
buf[strcspn(buf, "\n")] = 0; // drop potential trailing \n
char *p = strchr(choices, buf[0]);
if (p && buf[1] == '[=10=]') {
// Could fold upper/lower case here if desired.
return *p;
}
puts(reprompt);
}
return EOF;
}
int timePeriod = GetChoice("TimePeriod A or P", "Try Again", "AP");
switch (timePeriod) {
case 'A' : ...
case 'P' : ...
default: ...
可以添加额外的检查。这是将其转为辅助函数的最佳部分,它可以在代码中的多个位置使用,并根据需要以本地化方式进行改进。
OP代码注释:
用户输入不符合预期,不清楚 OP 的复杂 while()
条件是否会正确清空用户的输入行。如果遇到 EOF
或者第一个 char
是 '\n'
.
timePeriod != "A"
@Alan Au 所评论的不是所需的代码。将 timePeriod
与字符串 "A"
的地址进行比较。使用 timePeriod != 'A'
.
clean_stdin()
应该是 clean_stdin(void)
。它是 EOF 上的无限循环。考虑:
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
您遇到的问题在这里:
timePeriod != "A" || timePeriod != "P"
首先,如前所述,您不能将字符与字符串进行比较。您需要使用单引号而不是双引号。假设已更正,此条件将始终为真,因为 timePeriod
将始终不是 'A'
或不是 'P'
。这需要是逻辑与:
(timePeriod != 'A' && timePeriod != 'P')
另请注意,添加了一组额外的括号以确保保留 while
表达式中的运算顺序。
关于 "cute" 注释,这意味着在 while
表达式中塞进一堆语句并将正文留空会使您的代码难以阅读,因此更容易出现错误。如果你把它分解成多个语句,每个语句都做一件合乎逻辑的事情,你就更有可能自己发现这个错误。 Olaf 发表评论主要是为了警告其他看到您的代码的用户。