【问题标题】:C program loops infinitely after scanf gets unexpected datascanf得到意外数据后C程序无限循环
【发布时间】:2015-01-27 17:56:51
【问题描述】:

我有一个程序,我希望输入整数介于 2 和 64 之间,因此我将 scanf 放入 do { ... } while 循环中。这是我最初测试的代码:

int initialBase;

do {
  printf("Initial base: ");
  scanf("%i", &initialBase);
} while (initialBase < 2 || initialBase > 64);

问题是每当输入不是一个有效的整数时,它只是无限期地输出printf 语句并且不再提示用户输入,立即淹没控制台。为什么会发生这种情况?有什么更好的方式来读取满足我想要的条件的输入?

【问题讨论】:

  • 有人愿意评论我为什么被否决吗?
  • 这并不奇怪,scanf() 就是这样工作的。
  • 嗯,为什么停止提示?
  • 因为已经有缓冲数据。 scanf 不会丢弃它,因为它无法被解析。
  • 我不是投反对票的人之一,但我怀疑你被投反对票是因为 stackoverflow.com 上有大量帖子描述了使用scanf 进行用户输入的问题。一个常见的建议是不要使用scanf,而是使用getline 或类似的东西,然后对字符串进行后解析。

标签: c scanf


【解决方案1】:

scanf()失败时,参数不会自动初始化,未初始化的值可以是任意值,所以它可能小于2或大于64没人知道。

试试这个

int initialBase;

/* some default value would be good. */
initialBase = 2;
do {
  printf("Initial base: ");
  if (scanf("%i", &initialBase) != 1)
      break;
} while ((initialBase < 2) || (initialBase > 64));

如果您输入的不是数字,检查将跳出循环,initialBase 的初始化只是一个好习惯,在您的情况下可能会阻止您描述的行为,但在这种情况下它就在那里防止在while 循环之后访问未初始化的值。

循环没有停止的原因,是因为scanf()在输入流中留下了一些不匹配的字符,并且在这些字符仍然存在时再次调用scanf()将使scanf()继续等待有效输入,但立即返回流中当前无效的输入,如果您想继续阅读,请尝试从流中读取字符,直到找到'\n',这样

int initialBase;

initialBase = 0;
do {
    printf("Initial base: ");
    if (scanf("%i", &initialBase) != 1)
    {
        while (fgetc(stdin) != '\n');
        continue;
    }
} while ((initialBase < 2) || (initialBase > 64));

【讨论】:

  • 所以基本上你是说如果用户输入“a”之类的东西,我不能继续提示有效输入?
  • @PatrickRoberts 你可以,但你必须从输入流中清除未读字符,fflush() 不是解决方案。检查我新发布的代码。
  • 除了&lt;stdio.h&gt; 之外,fgetc 还需要#include 吗?
  • 不,只有&lt;stdio.h&gt; 两个,fgetc()scanf()。使用编译器警告,它可以为您节省大量时间,例如,当您忘记 #include 时可能会发生奇怪的事情,如果您让编译器抱怨所有事情,它们可能会被阻止。
  • @PatrickRoberts 当您在堆栈溢出上发布代码时,您不应忽略初始化之类的内容,在您发布的代码中 initialBase 没有初始化,这就是我指出这一点的原因。这只是对您未来职位的建议。一个建议,发布一个带有新问题的新问题,并尝试找到重现该问题的最小可能程序。它将帮助您提高调试技能,并且更容易回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-22
  • 1970-01-01
  • 2012-04-09
  • 2013-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多