今天一天都被这个 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 后加上一条语句:
- fflush(stdin)。该函数会清空缓冲区中的数据,从而在下次循环 scanf 需要用户提供输出而不是到空的缓冲区中读取数据。
- getchar()。用 getchar 接受回车符,也就将其过滤掉了,也能实现上述的效果。
当 scanf 是读入整数时就不需要用上述的方法,因为此时 scanf 会默认跳过缓冲区中的所有字符,当缓冲区无整数时,则会停下来等待用户的输入。
希望本篇博客能对你有所帮助,也希望看官能动动小手点个赞哟~~。