验证 C 中的字符输入



我有一个项目,我想验证 C 中的字符输入。我是C语言的新手,在编程方面也不是很有经验。我试图创建一个循环进行验证,但它不起作用。

#include<stdio.h>
void main(){
char input;
do {
scanf("%c", &input);
while ( (input != 'a') && (input != 'b') && (input != 'c') );
printf ("wrong input");
switch(input){
case 'a':
break;
case 'b':
break;
case 'c':
break;
} while ( input != 'c');

在 C 中获取用户输入并不困难,但您必须仔细注意正在读取的内容,以及未读stdin的内容(这会在下次输入时咬你)。使新的C程序员适合的功能之一是scanf()。它充满了许多陷阱。这里相关的陷阱是使用"%c"格式说明符和stdin中留下的任何其他无关字符。

"%c""%[..]"转换说明符(对于@chux"%n"说明符)不会忽略前导空格。这是一个问题,因为按Enter键会在stdin中生成一个'n'字符。这意味着如果用户输入'a''b''c'以外的内容,则从stdin中读取的下一个字符是'n'。除非您在下一次输入之前stdin清空'n'"%c",否则'n'字符将被视为下一个输入 - 您的代码似乎跳过下一个输入。(它没有跳过任何内容 -'n'正在等待读取 - 所以scanf()将其作为输入读取)。

若要避免此问题,可以在" %c"格式说明符之前放置一个空格字符 (space),这将导致scanf()忽略下一个非空格字符之前的任意数量的空格字符。由于'n'是空格,它将从stdin中提取并丢弃'n',从而读取输入的下一个字符。

但。。。。然后你会遇到下一个陷阱 - 如果用户滑倒并输入"de"作为输入怎么办。这使得'e'在阅读'd'stdin中未被读取的无关字符。空格不会帮助您忽略非空格字符。

有更好的方法 -- 面向线的输入

与其一次从stdin中读取一个字符,不如在接受用户输入时,最好使用fgets()或 POSIXgetline()一次读取一行。这样,给定一个大小合理的字符数组来保存行中的字符,则会消耗整行输入。stdin中不可能留下无关的字符来咬你下一次输入。如果您对用户输入的第一个字符感兴趣,只需检查数组中保存该行的第一个字符,例如array[0]或干脆*array.

所有用户输入都可以,并且应该使用面向行的输入函数。如果需要将行的一部分转换为单独的值,则可以使用sscanf()或字符串处理函数,例如strtok()等。好处是您可以分别验证输入的读取,然后验证值的转换。

如何要求某些输入

要求用户输入特定输入的方法很简单。您只需循环不断提示,读取和验证用户输入,直到用户提供请求的输入。如果提供了有效的输入,您只需break;读取循环。如果收到无效输入,您只需输出错误并再次循环,直到获得所需的输入。

您的案例的一个简短示例是:

#include <stdio.h>
#define MAXC 1024       /* if you need a constant, #define one (max chars per-line) */
int main (void) {

char line[MAXC];    /* declare buffer to hold each line of input */

while (1) {         /* loop continually until the user provides valid input */
fputs ("nenter a, b or c : ", stdout);         /* prompt for input */

if (fgets (line, MAXC, stdin) == NULL) {        /* read entire line */
puts ("(user canceled input)");             /* handle manual EOF */
return 0;
}

/* check 1st char in array to see if it is valid, if so, break loop */
if (line[0] == 'a' || line[0] == 'b' || line[0] == 'c')
break;

/* otherwise, invalid input provided, throw error -- repeat */
fputs ("  error: invalid input, not 'a', 'b' or 'c'n", stderr);
}

printf ("nyou entered: '%c'n", *line);    /* output value */
}

该方法如前所述:

  1. 循环不断,
  2. 提示输入,
  3. 读取并验证输入,允许用户通过使用 Ctrl +d(或在 Windows 上生成手动EOF(或在 Windows 上生成Ctrl + z)来取消输入,并在这样做时正常退出。
  4. 根据您的标准、'a''b''c'测试输入,如果得到良好的输入,break;读取循环,最后
  5. 在无效输入时,处理错误并重复该过程,直到获得所需的输入。

(注意:除非您在独立环境(没有任何操作系统)中对微控制器进行编程,否则main()的正确调用是int main (void)int main (int argc, char *argv[])(您将看到使用等效char **argv编写)。 参见:C11 标准 - §5.1.2.2.1 程序启动(p1)。另请参阅:main() 在 C 和 C++ 中应该返回什么?

示例使用/输出

对于你编写的任何输入例程,当你完成时 - 去尝试打破它。彻底测试它。想想用户可能做的所有愚蠢的事情,看看你的代码是否正确处理它。如果失败,请修复它并重试。例如:

$ ./bin/fgetschar_abc
enter a, b or c : My dog has fleas!
error: invalid input, not 'a', 'b' or 'c'
enter a, b or c : Cat has none!
error: invalid input, not 'a', 'b' or 'c'
enter a, b or c : Lucky cat!
error: invalid input, not 'a', 'b' or 'c'
enter a, b or c : Okay, okay!
error: invalid input, not 'a', 'b' or 'c'
enter a, b or c : b
you entered: 'b'

(尝试使用当前代码输入多个字符,看看会发生什么...

现在,您可以添加switch()语句,并确保line中唯一的字符是第一个字符(例如line[0],或简称*line)是一个'a''b''c'。如果您更喜欢使用单个字符变量而不是使用line中的第一个字符,那么只需将line中的第一个字符分配给您的变量,例如

char input = line[0];

实施switch()由您决定。如果您有任何其他问题,请告诉我。

最新更新