getchar() 、 scanf() 、流与缓冲区
C中的缓冲区一直是debug的重灾区,今天在写一个命令行界面的时候又遇到了这个问题,所以来总结一波。
两函数的不同之处
scanf() 会把 stdinBuff 中的特定格式数据取出,非特定格式数据则会留在stdinBuff 中,比如 while(){ scanf("%c", ); } ,当你输入一个字符串+ 回车的时候,它先存入 stdinBuff 中,之后按char类型从 stdinBuff 取出每个字符,然后在把最后一个输入的 \n 留在 stdinBuff 中;当你输入一个字符+回车,多次输入的时候,它会把每次输入中的\n都留在 stdinBuff 中。
getchar() 会把 stdinBuff 中的第一个字符取出,而把输入的其余数据放入 stdinBuff 中。
两函数的相同之处
都可以从流或者缓冲区中读取数据。当 stdinBuffer 不被置为NULL时,stdin 输入流中数据将存入 stdinBuffer 中,scanf 与 getchar 会优先从stdinBuff 中读取数据;当 stdinBuffer 被置为NULL时,scanf getchar 将从 stdin 输入流中读取数据。
流是什么?具有缓冲功能吗?
流是File *类型对象,它的底层实现是 fopen 等c库函数,并且 scanf 将读取输入流中 \n 之前的数据,所以 stdin 输入流具有和缓冲区一样的缓冲功能。如果想读写数据而不占用空间去缓存它们,则是用 read write 这样的系统调用,因为它们是以字节为单位进行读写而不是以 \n 为读写的结束标志,这样的机制决定了它们直接操作数据而无需将数据缓存。
那么如何清理 stdinBuff中的残余数据呢?
1、getchar() 去吸收 stdinBuff 中的残余数据。[推荐使用]
2、Windows下有C库函数 fflush(stdin) ,但是要注意这个函数很依赖编译器。
3、由于LInux无法用 fflush(stdin) 刷新stdin的缓冲区,所以可利用 setbuf(stdin, NULL) 置 stdin 的 Buffer 为NULL以达到刷新 stdinBuffer 的目的,但是这样也会带来问题:pointer of stdinBuffer 指向了NULL,相当于stdin的缓冲区不存在了,以后都只能从 istream 输入流(类似先进先出的字节队列)中读数据,这不是我们想要的目的,虽然可以清除当前 stdinBuffer 的数据,但是以后读数据都必须从 istream 输入流中读取,有点儿大财小用的意味,而且,从 istream 输入流中读入,输入流 stdin 是行缓冲,本身也会缓存数据(注意,\n也会被存储),而不会立刻丢掉之前存储的数据,这样的结果是你的程序中 gechar() 还是会自动读取到你不想要的数据如 "\n" ,综上所述我并不推荐用 setbuf() 去“刷新”缓冲区。
那么如何清理 stoutBuff 中的残余数据呢?
C库函数 printf( "\n") 以刷新 stdinBuff。它的机制是:标准输出流 stdout 的缓冲区是以 \n 标志的,它会将 \n 与之前的数一并取出存入 stdout 而后打印在屏幕上,如果缓冲区不存在 \n ,由于流也拥有缓冲功能,则会"慢一拍"再显示在屏幕上,具体情况是当程序移交给操作系统时流中的数据将会全部打印到屏幕上,然后清空流中数据并关闭。
题外话
额外说一句,如果在C++中, cin.get() 可以只读入一个字符而避免读入 \n ,这样就不用纠结在缓冲区问题上了,或者使用 <ifstream> 的 flush(stdin) 或者是 cin.clear()方法以刷新输入流。
getchar() 、 scanf() 、流与缓冲区的更多相关文章
- scanf函数读取缓冲区数据的问题
标准I\O的缓冲类型 标准I\O根据不同的应用需求,提供了全缓冲.行缓冲.无缓冲三种缓冲方式. 全缓冲:只有当划定的缓冲区被填满或者数据读取至末尾时,才开始执行I\O操作(执行系统提供的read\wr ...
- JAVA之旅(二十五)——文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine
JAVA之旅(二十五)--文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine 我们继续IO上个篇 ...
- Java精选笔记_IO流(字符输入输出流、字符文件输入输出流、字符流的缓冲区)
字符流 Reader是字符输入流的基类,用于从某个源设备读取字符 Writer是字符输出流,用于向某个目标设备写入字符 字符流操作文件 字符输入流FileReader,通过此流可以从关联的文件中读取一 ...
- cin.get()、流和缓冲区
大家好,这是我在CSDN的第一篇博客.我是一名学习GIS专业的大学生.我从小开始喜欢编程,可是到现在编程水平却长进不大,依然是菜鸟一个.究其原因,虽然这些年乱七八糟的东西学过不少,但是总的来说还是基础 ...
- IO 流之字符流的缓冲区
缓冲区的出现提高了对数据的读写效率 对应类: BufferedWriter BufferedReader 缓冲区需要结合流才可以使用, 对流的功能进行了增强, 即对流的操作起到装饰作用 使用缓冲区实现 ...
- getchar,scanf以及缓冲区
getchar()是stdio.h中的库函数,它的作用是从stdin流中读入一个字符,也就是说,如果stdin有数据的话不用输入它就可以直接读取了.getch()和getche()是conio.h中的 ...
- 关于cin,getchar(),scanf()的注意事项(转)
问题描述一:(分析scanf()和getchar()读取字符) scanf(), getchar()等都是标准输入函数,一般人都会觉得这几个函数非常简单,没什么特殊的.但是有时候却就是因为使用这些 ...
- DirectSound学习(二)--流式缓冲区
使用流式缓冲方式播放波形音频文件比较复杂,主要原因是在只有一个缓冲区提供给用户的前提下,这个缓冲区在提供给声卡播放数据的同是还需要用户不断的定时向其中写入数据.要注意从缓冲区这时是一个环形缓冲区,声音 ...
- getchar(),scanf(),gets(),cin,输入字符串
#include<iostream>#include<stdio.h>#include<string.h>#include<string>using n ...
随机推荐
- Maven工程下报错:The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
Maven工程下,webapp下面新建index.jsp文件,报如下错误. 原因很简单,没有安装如下maven依赖包: <dependencies> <!-- JSP相关 --> ...
- 二维,多维数组排序array_multisort()函数的使用
对于数组的排序,很很多方法:随便百度了一下 sort() - 以升序对数组排序 rsort() - 以降序对数组排序 asort() - 根据值,以升序对关联数组进行排序 ksort() - 根据键, ...
- 一位有着工匠精神的博主写的关于IEnumerable接口的详细解析
在此,推荐一位有着工匠精神的博主写的一篇关于IEnumerable接口的深入解析的文章:http://www.cnblogs.com/zhaopei/p/5769782.html#autoid-0-0 ...
- VMWare安装Win10虚拟机
这两天突发奇想安了个win10虚拟机,在安装的过程中还遇到了不少麻烦,所以在此与大家分享下. 首先我们用VMWare12来安装,VMWare已经更新到14但是不太稳定,所以为了保险起见还是用12吧. ...
- BootStra相关脚本引用说明
先看一个简单的模板(DOCTYPE是html5的文档类型) <!DOCTYPE html> <html lang="zh-CN"> <head> ...
- Angular自定义组件实现数据双向数据绑定
学过Angular的同学都知道,输入框通过[(ngModel)]实现双向数据绑定,那么自定义组件能不能实现双向数据绑定呢?答案是肯定的. Angular中,我们常常需要通过方括号[]和圆括号()实现组 ...
- Scala入门系列(一):基础语法
Scala基础语法 Scala与JAVA的关系 Scala是基于Java虚拟机,也就是JVM的一门编程语言,所有Scala的代码都需要经过编译为字节码,然后交由Java虚拟机来运行. 所以Scala和 ...
- 天梯赛 L2-020. 功夫传人 BFS
L2-020. 功夫传人 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 一门武功能否传承久远并被发扬光大,是要看缘分的.一般来 ...
- linux运维、架构之路-Zabbix监控应用及分布式
一.Zabbix监控集群应用 1.监控端口 net.tcp.listen[port] 检查 TCP 端口 是否处于侦听状态.返回 0 - 未侦听:1 - 正在侦听 net.tcp.port[<i ...
- 前端chrome浏览器调试
引言 "工欲善其事,必先利其器" 恩,这句话我觉得说的特别有道理,举个例子来说吧,厉害的化妆师都有一套非常专业的刷子,散粉刷负责定妆,眼影刷负责打眼影,各司其职,有了专业的工具才能 ...