输入不匹配的字符串时,Scanf 在 while 循环中不起作用 [英] Scanf not working in while loop when nonmatching string is entered

查看:67
本文介绍了输入不匹配的字符串时,Scanf 在 while 循环中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个名为 checkType 的函数来检查用户是否输入了整数类型的有效输入.例如,如果用户输入 15,它将打印 valid,而 15c 将打印 not valid.但是,如果用户只输入像ccccc这样的字符串输入,就会导致无限循环,程序崩溃.我在下面添加了一些屏幕截图来显示输出.

I'm using a function called checkType to check whether the user has entered a valid input of integer type. For example, if the user enters 15 it will print valid and 15c will print not valid. However, if the user enters a string input only like ccccc, it results in an infinite loop and the program crashes. I have added some screenshots below to show the outputs.

int checkType(int input, char *c) {
  if (input == 2 and *c == '\n') {
    return 1;
  } else {
    return 0;
  };
}

int main(void) {
  int faces = 0;
  char c;
  int valid = 0;
  int input;

  while (valid == 0) {
    printf("Enter number of faces: ");
    input = scanf("%d%c", &faces, &c);
    valid = checkType(input, &c);
    printf(valid == 0 ? "not valid\n" : "valid\n");
  }
}

无限循环:

推荐答案

scanf() 函数系列并非真正用于输入有问题的语法.

The scanf() family of functions is not really made for input of questionable syntax.

解决问题的常用方法是以肯定会成功的方式读入所有输入,例如通过使用 fgets() 读取整行(而不是数字、类似单词的字符串或任何其他具有预期格式的内容).然后您可以尝试按照预期格式解析该行表示字符串.(您可以使用 sscanf() 进行解析尝试.)如果失败,您可以忽略它并阅读下一行,或者尝试根据相同输入的替代允许格式进行解析.

The usual approach to solve your problem is to read in all the input in a way which is sure to succeed, e.g. by reading a complete line (instead of a number, word-like string, or anything else with expected format) with fgets(). Then you can try to parse that line-representing string as by expected format. (You can use sscanf() for the parsing attempt.) If that fails you ignore it and read the next line, or try parsing according to an alternative allowed format for the same input.

相关区别在于读取整行会成功并将其从输入流中删除.与此相反,您的代码在语法失败的情况下,会在输入流中留下与预期语法不匹配的任何内容.因此,当然,它会再次使读取循环的下一次迭代失败.这就是导致无限循环的原因.

The relevant difference is that reading a whole line will succeed and remove it from the input stream. In contrast to that, your code, in case of syntax failure, leaves in the input stream whatever did not match the expected syntax. As such it will, of course, fail the next iteration of the reading loop again. That is what causes your endless loop.

详细说明:

  • 将整行读入缓冲区,
    使用 fgets() 和将字符数限制为缓冲区大小的选项
  • 此时所有行都从输入(又名标准输入,又名输入流)中删除,
    这意味着即使读取的行不匹配任何允许的格式,下一次读取也会获得新的输入,
    这是尝试使用 scanf()
  • 直接读取输入的相关区别
  • 从行缓冲区中,尝试根据允许的格式读取单独的值,
    使用 sscanf() 并检查返回值
  • 如果成功了,你的预期变量就会被填充(例如一个整数);
    您可以尝试扫描其他的、未覆盖格式的尾随输入(并继续像错误输入一样,即使行的开头与允许的格式匹配)
  • 如果不成功,请尝试不同的允许格式,
    再次使用 sscanf()
    来自同一行缓冲区,即使格式部分匹配,也不会更改
  • 如果没有允许的格式与输入匹配,则认为它不正确
  • 不正确的输入可以被忽略或可能导致程序中的致命解析错误,您的选择
  • read a whole line into a buffer,
    using fgets() and the option to restrict the number of characters to the size of the buffer
  • at this point all of the line is removed from the input (aka stdin, aka input stream),
    which means that the next read will get new input even if the read line does not match any allowed format,
    this is the relevant difference to trying to read input directly with scanf()
  • from the line buffer, attempt to read separate values according to an allowed format,
    using sscanf() and with a check of the return value
  • if successful great, you have your expected variables filled (e.g. an integer);
    you could try scanning for additional, not format-covered trailing input (and continue like for incorrect input, even if the beginning of the line matched an allowed format)
  • if not successful try a different allowed format,
    using sscanf() again,
    from the same line buffer, which is not changed, not even if a format partially matched
  • if no allowed format matches the input it is time to consider it incorrect
  • incorrect input can be ignored or can cause a fatal parsing error in your program, your choice

这篇关于输入不匹配的字符串时,Scanf 在 while 循环中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆