<!--从缓冲区到输入列表-->
程序获取输入时的过程比我们想象的复杂 我们考虑一个简单粗暴完整的程序#includeint 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'仍然留在输入列表中
所以如果程序如下
#includeint main(){ int n; char ch; scanf("%d", &n); printf("%d", n); scanf("%c", &ch); //! 不会停止等待 printf("%c", ch); return 0;}
我们仍然键入125并且回车 那么第二个scanf将不会给你输入的机会 因为缓冲区中剩余的'\n'已经足够填饱ch的肚子
再考虑下一个程序
#includeint 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; 它将清除输入列表
尽管是写给初学者的 也有点太累赘了
反正我是绝对耐不下性子读完别人写的这么长的博客 (除非像我说得这么清楚明白 呵呵哒)