前言
上一期小编介绍了printf()
与scanf()
,但是通过各位读者的反馈以及我近几天刷题中遇到的问题我觉得上期对scanf()的介绍还不够完善,需要对scanf()进行必要的补充说明。
一、scanf本质上是如何输入数据的?
上期介绍了输入缓冲区
的概念,当我们通过输入数据后必须敲(回车),这样数据才会成功来到输入缓冲区(包括回车\n),接下来就是scanf()在缓冲区中按照指定格式提取所需数据。
二、scanf()提取%d数据的潜规则
1、%d前的“吃空白”行为
我们先看下面这个例子:
#include<stdio.h> int main() { int a = 0; int b = 0; scanf("%d%d",&a,&b); printf("a=%d\n",a); printf("b=%d\n",b); return 0; }
像%d%d这种格式说明符挨着的,中间没有任何分隔符,我们应该怎么输入?
如果两个整形符紧挨着的话,默认在输入数据时中间可以以任何空白字符作为分隔标志(包括-空格、回车符-\n、水平制表符-\t)并且不限数量。因此在我们输入紧挨着的整形数据时常常使用这种方法,使我们输入更加灵活。
那么这其中的原理又是什么呢?
原理:像%d这种输入,默认会把缓冲区中数字之前的空格和回车全部丢弃掉
也就是说:当我们输入%d这类整形数据时,当我们键入数据后,scanf()在提取整形数据时会自动 “吃掉“%d前所有的空白字符(包括-空格、回车符-\n、水平制表符-\t)直到提取到%d类型的整形数据。例如上述代码,我按照下图输入,依旧可以正常给变量赋值,能正确输出:👇
笔者在输入时,在数字1前敲了多个空格和制表符以及1个回车,在数字2前也是如此:
2、%d后追加(空白字符)产生的“吃空白”行为
原理:当参数为"%d "的时候,此时没有处理到结尾,scanf()会认为你要继续进行输入。然而你输入了空格或者回车,scanf()认为他们是分隔符,于是“吃空白”吃掉了。换句话来说,scanf()依旧在等待你的输入, 只有当你输入不是空白的字符以后,scanf()才会用它与参数字符串里面的空格比较。
也就是说:如果%d后面加上空格,在%d的匹配工作结束后,%d后面的空白字符开始工作,空白字符表示会“吃掉”所有%d之后的空白字符,也就是会丢弃缓冲区中%d后的所有空格、水平制表符和换行符,因此无论我们输入多少次回车都会被%d后的空白字符“吃掉”。如果此时想要停下来,这时候就需要输入一个非空白字符就能使空格吃空白的工作停下来。
但是这样做的话,很可能会产生bug,就是第二个非空白字符会被留在缓冲区中,下次输入时就会被读取,比如下面这种情况:(输入错位,产生bug)
因此不建议大家在%d后面追加(空白字符)容易产生bug,这些会产生歧义的代码尽量不要再工程中出现
总结
以上就是我对上期scanf()的一些补充,由于笔者学识尚浅,加之篇幅有限,如有不当之处,欢迎诸位指点。