对scanf原理的浅层理解 (一)——标准输入缓冲区

519 阅读2分钟

c语言快忘光了,来复习下scanf的原理,有错误之处请大佬谅解并指正!

c语言初级阶段比较重要的输入输出就是标准输入输出,我的环境是vscode,#include <stdio.h>正在其中。而scanf是其中最重要的。 在我们的os内存在一块缓冲区,叫做标准输入缓冲区(其实可以理解为一块内存)

截屏2022-01-25 下午9.14.33.png 观察手册不难发现,文档是这么描述scanf的:

截屏2022-01-25 下午9.47.57.png

函数的参数是各种类型的格式控制符,scanf会对传入其中的格式控制符进行一一的匹配,直到传入的参数类型不能正确完成匹配,返回一个代表该函数成功读取到的参数个数。

那么这与前面谈到的缓冲区有什么联系呢?

例如我们写段代码:

截屏2022-01-25 下午9.59.04.png 使用scanf读入键盘输入的三个数据,每个数据用空格进行分隔,当我们输入完第三个数据的时候,我们敲击回车(换行,\n)等待结果。换行的原因是,scanf是行缓冲机制,即不论我们怎么输入,输入什么数据,数据始终还是保存在我们的缓冲区内,尚未进行真正的IO操作。而当读到了换行符时才会进行真正的IO操作。

假设我们输入的是10 c 1.5;

截屏2022-01-25 下午10.05.40.png 实际上在缓冲区内的效果是这样的:

截屏2022-01-25 下午10.07.01.png scanf的参数中第一个格式是%d,匹配整形数据10,scanf会从缓冲区中将10成功匹配上并且读走; 重点来了,第二个格式是%c,字符类型的数据。

不难理解,空格' '和换行‘\n’都是字符类型的数据。对于scanf来说,给%c进行匹配时,由于我们输入数据是用空格进行两两分隔,我们在输入时并未看到10后面有数据,但实际上我们用于分隔的空格‘ ’同样也是字符型的数据,因此此刻匹配的字符是空格‘ ’,也就是说scanf的%c,会匹配上空格。

但是值得注意的是,我们在scanf的两两格式控制中,也采用了空格,这使得我们使用这一空格“吃掉“了我们用于分隔的空格,使得接下来的‘c’可以成功匹配上%c。接下来的浮点数1.5,读取前由于空格并不是浮点数据,因此可以顺利完成匹配,浮点数匹配上1.5。

最终输出结果:

截屏2022-01-25 下午10.18.27.png

总结:当scanf进行匹配时,匹配%d整形,%f浮点数据之前,会“清空”缓冲区(实际上对于残留的空格和换行,由于无法匹配,便不予匹配,计算机术语称为阻塞,等待后来的输入)而匹配%c字符时,由于空格和换行都属于字符型,因此会对最终结果产生影响。