概述
又到了暴露自己无知的时候,今天用了scanf结果出现了如下bug。
如果不了解scanf
的参数与返回值可以直接看这个 Microsoft Doc scanf
下面这段代码,如果输入正常整数的话,没有任何问题。但是,如果输入字符 f 会发生什么?
int main(void){
while (true) {
int num = 0;
printf("Please enter a number:");
int out = scanf("%d", &num);
printf("num is %d\n", num);
printf("out is %d\n", out);
if (num == 10) {
break;
}
}
}
不卖关子了,如果本应该输入整型,你输了字母,那么会直接进入无限循环,终端那里疯狂出现那几行printf
,而且scanf
的返回值out
会等于0
,说明没有把输入的值匹配给num
。
那么为什么会突然无限循环呢,正常情况程序下应该会在下一个scanf那里停住,然后等着我输入下一个数。
但是因为我开始输入了f
,f
进入了一个叫缓冲队列的地方,如果这个缓冲队列里面不是空的,那么它会优先把已经在里面的元素分配给num
,所以现在的情况是,缓冲队列非空,然后不断的出现scanf
,类型匹配错误,开始运行下一条代码,所以进入了死循环。
那这种情况怎么解决呢?最好的办法是不用scanf
,要不然很容易出现幺蛾子。如果但是单纯的让循环停下来,那么可以在后面加一个接受 %c
的scanf
函数,这样子缓冲队列里面的元素就有地方出来了,循环开始正常运行。
int main(void){
while (true) {
int num = 0;
char ch;
printf("Please enter a number:");
int out = scanf("%d", &num);
printf("num is %d\n", num);
printf("out is %d\n", out);
if (num == 10) {
break;
}
scanf("%c", & ch);
}
}
像上面这样子就好了。
最后补充一下scanf
的返回值
- 如果成功,返回已成功转换和分配的字段数量,注意,有可能读取很多,但只分配了一部分。
- 如果如果
format
为 空 指针,则将调用无效参数处理程序,如 参数验证中所述。 如果允许执行继续,则这些函数将返回EOF
,并将Errno
设置为EINVAL
。