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 ...
随机推荐
- HTML5技术分享 ES2017继发与并发
大家都知道,async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了.你可以用then方法指定下一步的操作. 进一步说,async函数完 ...
- js中对节点属性的操作和对节点的操作
常用的节点属性操作方法 1.setAttribute(name,value):给某个节点添加一个属性 2.getAttribute(name):获取某个节点属性的值. 3.removeAttribut ...
- 关于xampp集成开发环境的建立与初步认识
针对于xampp集成开发环境的建立主要分大步骤: 1.把xampp的压缩包压缩到一个盘中,比如c盘:然后点击中间的那个图标开始安装,由于这个软件是配置基本已经OK了,故可以直接next ...
- 大道至简第一章Java伪代码读后感
import.java.大道至简.*; //周爱民 import.java.读后感*; public class shawanyia { //1. 编程的精义 while(山没有消失) {if(愚公没 ...
- VUE 与其他常见前端框架对比
对比其他框架(转官方文档) 这个页面无疑是最难编写的,但我们认为它也是非常重要的.或许你曾遇到了一些问题并且已经用其他的框架解决了.你来这里的目的是看看 Vue 是否有更好的解决方案.这也是我们在此想 ...
- Java编程学习技巧和方法总结
干货:必须要有反馈,不断调整,多读书,多些笔记. 解释:不练习你以为你能掌握?笑话,只有自己根据一个个小目标不断的敲,运行,给予你反馈,这样才会真的进步. 纸上谈Java,是永远停止在口. 关于笔 ...
- 手动安装lump
教你编译PHP7 (nginx+mysql+php7) PHP7正式版已经发布,性能是PHP5.6的两倍! 操作系统: CentOS Linux, 6.5 64位服务器: 阿里云空的操作系统,我们从 ...
- C++反汇编第六讲,认识C++中的Try catch语法,以及在反汇编中还原
C++反汇编第六讲,认识C++中的Try catch语法,以及在反汇编中还原 我们以前讲SEH异常处理的时候已经说过了,C++中的Try catch语法只不过是对SEH做了一个封装. 如果不懂SEH异 ...
- webpack 图片的打包
1. 在img文件夹下随便找一个小一点的图片放进去. 2.修改entry.js require('../css/index.css'); var demo1 = require('../js/demo ...
- Docker: 限制容器可用的 CPU
默认情况下容器可以使用的主机 CPU 资源是不受限制的.和内存资源的使用一样,如果不对容器可以使用的 CPU 资源进行限制,一旦发生容器内程序异常使用 CPU 的情况,很可能把整个主机的 CPU 资源 ...