C语言中scanf函数与输入缓冲区之间的关系
2017-09-27 23:53
246 查看
讨论下scanf函数,输入缓冲区的关系
样例来源于算法竞赛入门经典第一章实验部分的内容,经过测试发现scanf函数对于整形数据在读入时会过滤掉 空格符 、换行符 和 水平制表符。按照提示,如果b的值非法,比如说输入一个字符‘s’,那么会出现什么结果呢?void scanf_buffer(void) { int a , b; while( scanf("%d%d",&a,&b) != EOF ) printf("%d %d\n",a,b); }1
2
3
4
5
6
phase_1:输入的两个数均为合法的int型的整数,可以观察到scanf函数对于整形的读入过滤了回车符、换行符、水平制表符。第一阶段的实验结果明确。
phase_2:当按照提示,b的值在输入时指定为非法,比如说字符‘s’,观察实验结果。在这里观察到了有趣的实验结果,查资料表明这里涉及到了scanf函数的输入格式、返回值和主进程的输入缓冲区等相关内容。
1. scanf函数的读取格式控制&scanf函数的返回值
scanf函数有点意思的,scanf函数会对整形、浮点型和字符数组(字符型指针)过滤掉空格、回车符和水平制表符,对于字符型则按照读入的字符处理。scanf函数按照字符流的形式读取外部输入设备中的字符流,在本例中,过滤结束之后,还需要将字符流“1234”转化为整形1234,字符流“3.14”转化为float型的3.14等。 上面两图模拟了一个意欲顺序读入int,float,double型值的一次成功的读取过程。首先scanf函数成功得到了想要的数据,并返回了成功得到的数据的个数。简化逻辑,Keyboard中的数据以中断触发的形式被读入,经过一系列的传递,交付给了系统的输入缓冲区(这时Keyboard中已经没有了数据),然后scanf代表的user通过系统调用成功取走了Input buffer中的数据(Input buffer中数据都被取走,Input buffer为空),然后scanf函数返回值为3,ret = 3。
2. Input buffer
如果正常读取的话,也真的不好再说什么了(人家都按照你的意愿达到了你想要的结果,你还想怎样),下面通过一组数据,深入了解一下输入缓冲区。
1、从逻辑上说,输入缓冲区从标准输入或者是文件中得到数据,然后等待被应用进程取走。其必要性是为了匹配低速的输入设备与高速的CPU之间的不均衡性,从而提高系统性能。
2、为什么非法输入的时候,数据被卡在Input Buffer而不是其他地方?
注意,过程1只是简单地数据传输,不涉及类型检查,而过程2需要根据scanf函数的格式检查值是否合法,所以问题只可能出在过程2。
3、这一点比较隐晦,如图的三个变量输入的时候,scanf依然是有返回值的。鉴于scanf函数在处理时候的强次序性,scanf函数返回0代表第一个值已经非法,后面的值合法与否都不在重要了,因为越不过去第一个值;scanf函数返回1代表第一个值合法,第二个值非法,依此类推,直到scanf函数返回3意味着这一轮的数据已经读取完毕,可以进行下一轮的数据读入。
3.解决此题非法输入一直占用Input Bufffer,程序无限循环的方法
方法1:读入的时候顺带检查scanf函数的返回值是否异常,异常也可及时退出,不会一直占用Input Bufffervoid scanf_buffer() { int a , b; while( scanf("%d%d",&a,&b) != EOF && scanf("%d%d",&a,&b) == 2 ) printf("%d %d\n",a,b); }1
2
3
4
5
6
方法2:fflush(stdin)强制刷新Input Bufffer,保证输入结果的无后效性。及时偶尔的非法输入也不会使程序陷入死循环或直接退出的问题。
void scanf_buffer() { int a , b; while( scanf("%d%d",&a,&b) != EOF ){ fflush(stdin); printf("%d %d\n",a,b); } }1
2
3
4
5
6
7
8
总结:上述两种方法均可处理scanf异常读入的情况均可以,视不同的情景要求使用。方法2的鲁棒性明显显得好得多,fflush(stdin)也很有意
相关文章推荐
- C语言scanf函数输入时键盘缓冲区\n的问题
- C语言scanf函数输入时键盘缓冲区\n的问题[经典问题]
- C语言scanf函数输入时键盘缓冲区\n的问题[经典问题]
- C语言中scanf函数输入回车符的问题
- gcc c语言中scanf输入格式不正确,清空缓冲区问题
- C语言编程在Xcode中Scanf 输入跳过以及清空键盘缓冲区总结
- 关于用连续用多个scanf函数输入数据时前面的scanf函数会在缓冲区留下回车符的问题
- C语言中scanf函数输入回车符的问题
- 46 结合C语言缓冲区谈scanf()函数
- C语言中scanf函数输入回车符的问题
- 【C语言天天练(十五)】字符串输入函数fgets、gets和scanf
- 一个字符变量存储到动态分配内存引发的输入问题解决--连续输入scanf函数存在缓冲区的问题
- 【C语言天天练(十五)】字符串输入函数fgets、gets和scanf
- c语言中scanf等函数关于输入流缓冲区
- scanf输入函数与缓存的关系
- 简谈C语言中的scanf()输入函数的坑点之一
- C语言技巧【枚举作为函数变量类型】【数据输入与输出】【do while循环体内scanf函数被跳过,循环结束】【用const修饰函数的参数】
- C语言输入函数scanf()
- C语言中scanf格式化输入函数
- C语言中用scanf函数输入字符时,为什么要在输入控制符%c前面加空格?