如果C在古代
输入的“帝王既视感”
scanf
从键盘输入到scanf
读取的整个流程:当我们按下键盘上的任何按键的时候,对应按键的符号都会以字符的形式按照先来后到的原则依次整齐的排列在内存的缓冲区中,等待scanf
的"临幸";当输入字符后键盘按下回车键的,这时候就相当于管家通知scanf
,告诉它,可以去"选妃"了,然后scanf
就进入内存缓冲区取数据,从前往后依次"选",由于从键盘输入的都是从全国各地征集过来的(键盘输入的都是字符型),所以需要对它们进行一定的培训和装饰(将键盘输入的合法字符转换成我们需要的类型,比如scanf("%d", &a)
,就将内存中的字符转换成了十进制的数字);scanf
从花名册(内存缓冲区)选取妃子的时候,遇到歪瓜裂枣会(空格、制表符\t
和换行符\n
)会跳过,直到选到自己满意的为止,最终,那些被跳过的妃子和被选中的妃子都会在花名册中被除名(系统将跳过和取出的数据从缓冲区释放掉),那剩下的妃子呐?别着急,剩下的妃子会在花名册中存留,等到scanf
的下一次"选妃"(未被跳过或取出的数据,系统会将它一直放在缓冲区中,直到下一个 scanf
来获取)。不过这里得注意,输送来的"妃子"得符合scanf
的胃口,如果上来的妃子就不符合scanf
的胃口,那么scanf
就会龙颜大怒,不选了(比如scanf("%d", &a)
,希望输入的是十进制整数,但是输入了a
字母,那么scanf
直接从缓冲区跳出,进行输出,输出的是一个未初始化的数),但是,这个妃子并不会从花名册中抹除,而是继续留在花名册中,等待别的scanf
临幸。
注:如果遇到不挑剔的scanf
,不管是歪瓜裂枣还是倾国倾城都会被选入宫中,只要是女的就行(scanf("%c", &a)
,任何数据都会被当作一个字符,不管是数字还是空格、回车、Tab 键它都会取回,因为键盘输入的数据最原始的就是字符型的)
scanf
类说明符:
类型 | 合格的输入 | 参数的类型 |
---|---|---|
%a、%A | 读入一个浮点值(仅 C99 有效)。 | float * |
%c | 单个字符:读取下一个字符。如果指定了一个不为 1 的宽度 width,函数会读取 width 个字符,并通过参数传递,把它们存储在数组中连续位置。在末尾不会追加空字符。 | char * |
%d | 十进制整数:数字前面的 + 或 - 号是可选的。 | int * |
%e、%E、%f、%F、%g、%G | 浮点数:包含了一个小数点、一个可选的前置符号 + 或 -、一个可选的后置字符 e 或 E,以及一个十进制数字。两个有效的实例 -732.103 和 7.12e4 | float * |
%i | 读入十进制,八进制,十六进制整数 。 | int * |
%o | 八进制整数。 | int * |
%s | 字符串。这将读取连续字符,直到遇到一个空格字符(空格字符可以是空白、换行和制表符)。 | char * |
%u | 无符号的十进制整数。 | unsigned int * |
%x、%X | 十六进制整数。 | int * |
%p | 读入一个指针 。 | |
%[] | 扫描字符集合 。 | |
%% | 读 % 符号。 |
总:int scanf(const char *format, ...)
函数从花名册选妃(标准输入流 stdin 读取输入),并根据喜好选择(根据提供的 format 来浏览输入)。
getchar()
getchar()
也可以挑选妃子,但是其每次只能挑选一个,并且只能是字符类型的。
char a;
a = getchar();
//类似于
char a;
scanf("%c", &a);
总:int getchar(void)
函数也从花名册选妃(从 stdin 读取一个字符),不管是啥歪瓜裂枣都接受,反正就是只有一个,不要白不要。
gets()
gets()
比getchar()
进阶了一些,可以挑选多个妃子(实际上是读取一整行的字符),但是它没有那么挑剔,只有遇到歪瓜裂枣中的换行符\n
才会离开。
注:由于gets()不检查字符串的大小,必须遇到换行符或文件结尾才会结束输入,因此容易造成缓存溢出的安全性问题,导致程序崩溃,可以使用fgets()
代替。
char str[80];
gets(str);
//实际效果等同于:
char str[80];
scanf("%[^n]"