说一个比较有意思的bug,我自己之前也许是上课没咋认真不知道怎么处理这个问题,也是最近才明白底层问题
代码可在devcpp运行,linux亦可
相信一定有童鞋在学校写作业的时候遇到一个问题吧,有时候使用gets()函数会出问题(莫名其妙的,有时候没问题,有时候又又有问题)
接下来用一段简单的代码模拟一下这个情景
#include<stdio.h>
#include<string.h>
int main()
{
int a=0,b=0;
char c[20];
scanf("%d",&a);
scanf("%d",&b);
//scanf("%s",c);//%s这种输入方式不会导致无法正常读取,或许是,有特殊的处理吧
//(如果缓冲区遗留空格,'\n'(输入同理) )
//getchar();//专门拿来清空缓冲区的函数,在需要读取字符前的函数
//使用这个函数准没有错(这是我的观点不代表我的立场)
fgets(c,10,stdin);//fgets()函数跟gets()函数是差不多的,我用fgets()函数
//仅仅是因为我linux的编译器不支持gets()函数(不安全,所以被禁用)
printf("%d %d %s\n",a,b,c);
return 0;
}
输入1回车2回车(此时可能你还想输入一个字符串),but直接就显示结果,小小的脑袋大大的问号是吧
(熟悉吧,哈哈哈)
//当然,如果使用另一种输入方式是没有问题的 1 2 hhh 因为读到空格gets()函数是不会退出的
问题出在输入缓冲区残留了'\n'字符,所以调用gets函数的时候首先读到的就是'\n'字符,而gets()函数读到'\n'就退出,所以也就不能输入字符串了,解决方式就是加一个getchar()函读取空缓冲区剩下的一个字符(注意我的措辞,是一个)
到这里就已经明白为什么gets()函数会"偶尔"出问题了
接下来,深入一点讨论缓冲区与getchar()函数
(1)首先说一说这个残留是怎么来的
scanf("%d",&a);这行代码只会读取一个整型数据,剩下的都会遗留在缓冲区也就是说输入110abc 那么abc就会残留在缓冲区
(2)缓冲区只会保存最近一次的输入,也就是说 1\n1\n 这样的输入(第一个\n之后就是第二次输入了,因为 \n标志着第一次输入的结束,这不难理解),缓冲区只会残留一个'\n'字符
但是如果说输入 1\n1 123\n 这个时候缓冲区残留的数据就不仅仅是一个'\n'了,还有多余的空格以及123
这有什么问题呢,这个时候一个getchar()函数可能就解决不了问题了
比如(用我代码实验的友友,请先启用我注释掉的getchar()函数 ) 输入 1\n2\n空格\n 这个时候getchar读走的就是空格,而\n还在缓冲区,也就不能正常执行了
自己实验一下就知道了,就不一一细细讨论了(熄灯了,不想干了)