【问题标题】:Scanf doesn't take input after submitting non numbers提交非数字后,Scanf 不接受输入
【发布时间】:2020-03-21 07:42:12
【问题描述】:

有人可以帮我理解为什么如果第一个输入是“K”,那么 scanf 不会要求我提交第二个输入?

int n=0;
scanf("%d",&n);
scanf("%d",&n);

就好像它从其他地方获得了输入!在这种情况下,n 的值是多少?

【问题讨论】:

  • 在调用函数时总是检查返回值。 scanf 将在无法解析输入时立即停止。返回值告诉您有多少项目scanf 成功匹配。不匹配的输入留在流中,与不匹配的说明符关联的变量不会改变。
  • 这就是为什么scanf() 返回一个告诉你它是否成功的值。这也是为什么使用scanf() 读取输入是一个非常糟糕的主意的原因 - 如果输入不是预期的,您的输入流将处于不确定状态。
  • 请有人帮我理解为什么... 因为scanf 是一个设计非常非常糟糕,几乎没用的函数。我鼓励所有 C 程序员要么根本不使用它,要么在最初几周将它用于非常简单的东西,然后毕业到更好的东西。在你使用它的最初几周内,只给它完美的输入;当输入不匹配时,甚至不要试图弄清楚它做了什么(更不用说让它表现得更优雅了)。
  • @SteveSummit,你能说明哪些功能更好地使用而不是scanf()

标签: c input int scanf c99


【解决方案1】:

如果我们检查 scanf() 返回值,它显示为 0

#include <stdio.h>

int main(int argc, char **argv)
{

    int n=0;
    int retvalue=0;

    retvalue = scanf("%d",&n);
    printf("first scanf() return: %d\n", retvalue);

    retvalue = scanf("%d", &n);
    printf("seconf scanf() return: %d\n", retvalue);

    return 0;
}

scanf()opengroup 网站上的文档

这些函数应返回成功匹配的数量和 分配的输入项; 如果提前发生,这个数字可以为零 匹配失败。

当您输入一个字符值,并且 scanf() 函数设置为 mach/accept "%d"(十进制数)时,它会失败。

[评论后编辑]

如果第一个 scanf() 与格式规范不匹配,则输入不会被消耗并保留在输入缓冲区中。

换句话说,不匹配的字符保留在输入缓冲区中,第二个scanf() 将其用作输入,同样第二个也失败。

警告

fflush(stdin) 解决这种不当行为,但不要使用,因为 stdin 上的 fflush() 会导致未定义的行为。

[编辑2]

在这种情况下,getchar() 调用将消耗stdin 中的剩余缓冲区。

int n=0;
int retvalue=0;

retvalue = scanf("%d",&n);
printf("first scanf() return: %d\n", retvalue);

if(!retvalue)
    getchar();

retvalue = scanf("%d", &n);


printf("seconf scanf() return: %d\n", retvalue);

if(!retvalue)
    getchar();   

【讨论】:

  • 我认为 OP 理解为什么第一个 scanf 失败。根本问题是为什么 second scanf also 在没有提示用户的情况下失败。
  • “标准输入上的 fflush() 导致未定义的行为”与“fflush(stdin) 解决这种不当行为”相矛盾。正确的说法是,fflush(stdin) 是由 Microsoft 的“C”实现(例如它)定义的,用于从输入流中删除已接收但未处理的字符,但未由 C 标准定义,因此不能用于可移植行为。无论如何,建议人们使用fflush(stdin) 是一个坏主意,因为它不可移植。通过在每次失败 scanf 之后执行 getchar()(并测试 EOF),然后重试 scanf,可以便携地丢弃不需要的输入。
  • 谢谢,@EricPostpischil 相关评论:stackoverflow.com/questions/2979209/…
  • 我不认为想要丢弃输入缓冲区通常是一个错误。如果确定用户输入了不可接受的内容,则丢弃他们当前输入的所有内容,告知他们问题,然后征求新的输入是有意义的。
  • @EsmaeelE 是的,通常想要丢弃输入是错误的。通常这意味着您正在使用scanf,并且它已经“卡住”了错误的输入。但是,说真的:解决这个问题的正确方法是首先不要使用scanfscanf 是一个很差的功能。对于“玩具”程序和完美的输入来说,它可能勉强够用,但试图很好地处理错误输入是它根本无法做到的许多事情之一。 (你可以试试,但总会得到不满意的结果,而且麻烦多于值得。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-24
  • 2011-01-09
  • 2019-07-10
  • 1970-01-01
相关资源
最近更新 更多