当前位置: 代码迷 >> 综合 >> while 循环中“scanf 被跳过”或者“无限循环一个输入”或者“scanf 死循环”的 bug 总结
  详细解决方案

while 循环中“scanf 被跳过”或者“无限循环一个输入”或者“scanf 死循环”的 bug 总结

热度:56   发布时间:2023-11-22 08:48:52.0

今天一天都被这个 bug 烦到头疼。我的 GetScoreData 函数中是从文本中读取一大串的输入。但是 debug 的过程中发现,只要是输入 1 以外的任何数,循环都能正常进行,每次都会停下来等我重新输入。独独只有输入 1 的情况下, 会无限循环 1 中的内容且我根本无法输入。debug 显示 choice 的值也始终为 1,于是我判定是 GetScoreData 函数中出了问题。

int main()
{
    ......while (1){
    scanf("%d", &choice);switch(choice) // 根据用户输入进入不同的模块{
    case 1:GetScoreData();break;case 2:CountTotalScore();break;}printf("\n请输入您的选择(1-9):\n");}......
}

我的 GetScoreData 函数的主体代码是这样的:

void GetScoreData()
{
    fropen("input.txt", "r", stdin);.........fclose(stdin);
}

使用 fropen 函数的原因在于PAT算法笔记总结(一)第 17 点中讲到的那样,能够省去重复的复制粘贴测试数据的过程。但是在此处,由于不知名的原因,它会使得 main 函数中的 scanf 不停地得到来自其他地方的输出,从而使得 GetScoreData 函数被无限执行。也由此产生了 scanf 函数被跳过的现象。我把这两段代码删去后,程序就恢复了正常,果然还是不能偷懒,脚踏实地才是真呐…

网上也有其他的 while 中 scanf 被跳过或者只执行一次的 bug,我这个算是意外之外的 bug。这里把网上的该 bug 总结一下,我提取出所有该问题的主体代码如下:

while (1)
{
    ...scanf("%c", &c);... // 后面的语句是判定字符变量 c
}

这个问题主要表现为:无限循环。其原因在于,计算机的输入首先是进入到缓冲区中的。当你输入字符 a + 回车 之后,你的 a 被读取给了 字符变量 c,回车符则留在了缓冲区中。第一个循环执行完之后,scanf 会首先进入缓冲区读取数据,发现读取到的是回车符,而判断语句中没有针对回车符的分支,于是会进入下次循环。下次循环又读取到回车符,于是又进入下下次循环,从而出现死循环的 bug。解决办法有两个,都是在 scanf 后加上一条语句:

  1. fflush(stdin)。该函数会清空缓冲区中的数据,从而在下次循环 scanf 需要用户提供输出而不是到空的缓冲区中读取数据。
  2. getchar()。用 getchar 接受回车符,也就将其过滤掉了,也能实现上述的效果。

当 scanf 是读入整数时就不需要用上述的方法,因为此时 scanf 会默认跳过缓冲区中的所有字符,当缓冲区无整数时,则会停下来等待用户的输入。


希望本篇博客能对你有所帮助,也希望看官能动动小手点个赞哟~~。

  相关解决方案