最近一直在学习C语言,大学的时候没好好学,想不到10多年之后,我又开始学起来了,话说C语言确实相当有意思,至少比Python有意思。
我就写一下C语言内置的scanf函数。我的理解这是一个格式化输入的函数,用于读取信息并将信息写入指定的地址内。
常规的用法
#include <stdio.h> int main(){ int a, b; scanf("%d%d", &a, &b); return 0; }
除了%c的格式化相对特殊一点,%d,%f,%e等,scanf在读取的时候, 就以上面的程序为例子,当我们输入2[空格]3[回车]后,a与b变量就会进行赋值。
在读取的时候,由于第一个%d需要读取一个整数字符,读取的时候首先会忽悠前面所有的空白字符包括空格,回车,制表符。当读取到第一个显示字符的时候,会取匹配该字符是否为数字,如果为数字就读取,并读取下一个,一直读取到非数字字符,函数会将读取到的数字信息写入变量,然后再将读取到非数字信息重新放入文字缓存区,供后续的使用。这时第二个%d也将开始进行匹配,它读取到了第一个前面读取过并重新放入缓存区的空格,也会进行忽略,并开始读取匹配的信息,直到最后读取到回车的字符,同样的操作,复制变量,并把该回车符放入缓存区供后面的函数使用。所以如果这个时候想清空文字缓存区的数据,就需要使用getchar()函数,读取最后缓存取里面的回车字符。
但如果格式化的里面,添加了其它的参数,效果就不同了比如下面的代码
#include <stdio.h> int main(){ int a, b; a= b = -1; scanf("%daaa%d", &a, &b); printf("a = %d, b = %d ", a, b); return 0; }
我在格式话的里面插入了aaa的文字,格式化输入么,既然你定制输入要求了,那scanf内置默认的空格匹配就失效了。假如我输入[空格][制表符]1[空格]aaa3,第一个1的情况,还是跟上面我的分析一样,第二个就不一样了,你既然自定义了匹配信息,aaa,它将选择缓存区里面的aaa开头的信息,然而不幸的是,缓存区的数据是[空格]aaa,根本无法匹配上,导致第二个变量无法进行赋值。
上面的分析可能有点歧义,我这里重新再写一下,当scanf运行的时候,只要能够匹配信息,它会一直匹配下去,而且如果匹配的是%d这些数字字符,会忽略前面所有的空格字符信息
注意只有匹配到%d的字符的时候,才会刚好忽略空格字符信息,另外的字符信息出现,必须严格匹配。
所以前面的理解
输入1aaa[空格]2[回车]就可以读取到全部字符信息。
因为当1aaa匹配好的时候,虽然把空格重新放入了字符缓存区,但下一个匹配字符是%d,它可以忽略前面所有的空字符,所以自然可以实现要求。
scanf会处理掉匹配的字符信息。
假如输入
1aab[空格]2[回车]
第一个变量还是能够正常的赋值,缓存还剩下的信息为b[空格]2[回车]。
所以,当匹配%d,%f的时候,你可以假想它前面就像有一个正则的[ ' ' ']*的通配符,会默认帮你处理这些空白信息,当然你可以手工放入一个空白字符,效果还是一样的,也可以说没效果。
最后我写一些关于%c的情况,
scanf("%c", &a)
这个本来跟getchar效果一样,读取一个字符进来,并赋值给a,但有些时候,输入中,总会有一些空格或者回车的干扰,这次我就碰到了这样的问题。
#include <stdio.h> int main(){ char a, b; scanf("%c%c", &a,&b); printf("a = %c, b = %c ", a,b); return 0; }
我输入了a[空格]b[回车],b赋值到了空格,字符缓冲区剩下b与回车
在读取字符的时候,匹配不会默认帮你去掉空字符,这个时候,如果你需要匹配非空字符,可以在需要匹配的字符前面手工加上空格,自动帮你匹配去掉空字符
#include <stdio.h> int main(){ char a, b; scanf(" %c %c", &a,&b); printf("a = %c, b = %c ", a,b); return 0; }
这样就可以去掉配置字符之前的所有空白字符信息了,注意不要在最后面也添加一个空格,这样会导致按下回车的时候,缓冲取的所有字符都将被匹配完,阻塞等待新的输入,如果你输入了空白字符是没用的,因为空格可以无限匹配空白字符,只有输入一个可显示字符才会停止阻塞。
自己写了一下博客,感觉对scanf的了解基本差不多了,scanf还有返回值,应该是显示匹配的字符信息数量,我一般没用,查了很多中文资料的网站,我觉的,我这篇应该是写的最清晰的了【不要脸】
最后,说一句,人生苦短,放弃Python,C语言才是王道。