C语言未提供输入/输出关键字,其输入和输出是通过标准函数库来实现的。C语言通过scanf函数读取键盘输入,键盘输入又被称为标准输入。当scanf函数读取标准输入时,如果还没有输入任何内容,那么scanf函数会卡住(阻塞)。
一个小栗子
但C语言的scanf函数有一个小小的Bug:在读取字符变量(char型)输入时,会产生“垃圾”。来看一个小栗子:
#include<stdio.h>int main(){int i;char c;scanf("%d", &i);printf("i=%d\n", i);scanf("%c", &c);printf("c=%c\n", c);return 0;}
执行输入10,然后回车,运行结果如下图:
变量c读了个寂寞?
为什么第二个scanf函数不会被阻塞呢?其实是因为scanf函数读取了缓冲区里的’\n’,即scanf(“%c”,&c)实现了读取,只不过读了个换行而已,所以不会阻塞。
缓冲区原理
行缓冲:在这种情况下,我们输入的字符先存在缓冲区里,当在输入遇到换行符时,才执行真正的I/O操作。
scanf函数在读取整型、浮点型、字符串时,会忽略’\n’(回车符)、空格符等字符(忽略指的是scanf函数在执行时会首先删除这些字符,然后再阻塞),scanf函数匹配一个字符时,会在缓冲区删除对应的字符。而在读取字符型时,不会忽略任何字符,所以scanf(“%c”, &c)读取了还在缓冲区中残留的’\n’。
多种类型混合输入
由上面的例子可以看出:当我们让scanf函数一个读取多种数据类型且含有字符类型时,一定要各位小心!那如果就是读完整型读字符型可咋整呢?很简单,只需在%d和%c之间加入一个空格即可。该空格可以消耗掉回车。
#include<stdio.h>int main(){int i;char c;scanf("%d %c", &i, &c);//这里多了个小空格哦~printf("i=%d\n", i);printf("c=%c\n", c);return 0;}

scanf的返回值
返回值为整型,正常情况下返回成功匹配数据的个数(一个都没匹配则返回0),在Visual Studio中,如果在行首按三次 Ctrl+Z,会返回EOF(EOF就是-1)。
