<!--从缓冲区到输入列表-->
程序获取输入时的过程比我们想象的复杂 我们考虑一个简单粗暴完整的程序
#include <stdio.h>
int main(){
int n;
scanf("%d", &n);
printf("%d\n", n);
return 0;
}
程序运行到scanf()时会停止 请求外界输入
也许你输入了125然后回车了
但事实上 你从键盘上输入的是字符'1''2''5' 还有换行符'\n' (因为你键入了回车)
在你按回车键之前 字符'1''2''5'都处于一个叫做缓冲区的位置里
回车键是特殊的 它先将字符'\n'添加到缓冲区 随后便清除缓冲区 将其中的所有字符发送到一个叫做输入列表的地方
scanf函数以及其他标准输入函数便会立刻从输入列表中获取内容
上述程序按照%d的规则从输入列表中获取字符 它获取了'1''2''5' 并且将其转变为整数125 存入了变量n中
对于那些从输人列表中获取输入的函数 它们并不知道什么是整数 因为整数是编程中的概念 而无论是缓冲区还是输入列表 其中只有字符 所以“获取整数”只是从结果上看的
再多说一点 由于每个字符是一个字节 所以便有了字节流这个术语
我们继续考虑上面的程序 你要求scanf获取一个整数到n中 它完成了
但是并没有结束 因为输入列表并不干净 回车符'\n'仍然留在输入列表中
所以如果程序如下
#include <stdio.h>
int main(){
int n;
char ch;
scanf("%d", &n);
printf("%d", n);
scanf("%c", &ch); //! 不会停止等待
printf("%c", ch);
return 0;
}
我们仍然键入125并且回车 那么第二个scanf将不会给你输入的机会 因为缓冲区中剩余的'\n'已经足够填饱ch的肚子
再考虑下一个程序
#include <stdio.h>
int main(){
int n;
char ch1, ch2;
scanf("%c%d%c", &ch1, &n, &ch2);
printf("ch1 = %c\n", ch1);
printf("n = %d\n", n);
printf("ch2 = %c\n", ch2);
return 0;
}
我们的键入仍然是125回车
结果是ch1 == '1' n == 25 ch2 == '\n'
格式说明符对于scanf是十分重要的 它便是“规则” 告诉scanf如何从输入列表中获取字符 并且如何做转换
时刻记住输入列表中的内容全是字符 规律就会十分容易
还有需要注意的是 尽管输入列表中的内容都是字符 但是字符还有分类 比如空白符 数字字符 字母字符等
%d 忽略前置空白符 获取连续数字字符 直到遇上非数字字符或者输入列表尾为止
但是如果忽略到空白符之后遇到的时非数字字符 那么就直接结束
获取前的输入列表
' ' ' ' ' ' 'k' 'o' 'w' '\n'
获取后
'k' 'o' 'w' '\n'
%f 这个比较复杂 但是我们只要明白从何时开始 到何时为止即可
假如输入列表是这样
' ' ' ' '2' '.' '5' '.' '2' '1' '4' 'f' 'g' '\n'
那么%f获取后 列表变为
'.' '2' '1' '4' 'f' 'g' '\n'
%c 直接获取一个字符到目标变量 “看见什么吃什么”
由于所有输入函数都共享同一个输入列表 所以在整数和字符的混合输入中可能出错
如果你不清楚在获取一个整数以后的下一个获取是否为字符 加上下面的语句是最保险的
while(getchar() != '\n') continue;
它将清除输入列表
尽管是写给初学者的 也有点太累赘了
反正我是绝对耐不下性子读完别人写的这么长的博客 (除非像我说得这么清楚明白 呵呵哒)