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 ...
随机推荐
- Python 爬虫练习(一) 爬取国内代理ip
简单的正则表达式练习,爬取代理 ip. 仅爬取前三页,用正则匹配过滤出 ip 地址和 端口,分别作为key.value 存入 validip 字典. 如果要确定代理 ip 是否真的可用,还需要再对代理 ...
- mysql数据库相关知识
什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的建立在计算机存储设备上的仓库.(来自:百度) 什么是sql? 结构化查询语言(Struct ...
- 流式处理的新贵 Kafka Stream - Kafka设计解析(七)
原创文章,转载请务必将下面这段话置于文章开头处. 本文转发自技术世界,原文链接 http://www.jasongj.com/kafka/kafka_stream/ Kafka Stream背景 Ka ...
- CS窗体程序数据列表分页
以前,觉得winform程序分页很无趣,也没实际意义,直到近期的项目实践中让我认识到原来winform数据列表分页也是非常有必要的,因为由于数据量过大的情况,当窗体在初始加载数据的时候如果不做条件的限 ...
- websocket(三) 进阶!netty框架实现websocket达到高并发
引言: 在前面两篇文章中,我们对原生websocket进行了了解,且用demo来简单的讲解了其用法.但是在实际项目中,那样的用法是不可取的,理由是tomcat对高并发的支持不怎么好,特别是tomcat ...
- selenium基本操作
#coding=utf-8from selenium import webdriverfrom selenium.webdriver.common.keys import Keysfrom selen ...
- C++反汇编第二讲,不同作用域下的构造和析构的识别
C++反汇编第二讲,不同作用域下的构造和析构的识别 目录大纲: 1.全局(静态)对象的识别,(全局静态全局一样的,都是编译期间检查,所以当做全局对象看即可.) 1.1 探究本质,理解构造和析构的生成, ...
- vue+echarts 动态绘制图表以及异步加载数据
前言 背景:vue写的后台管理,需要将表格数据绘制成图表(折线图,柱状图),图表数据都是通过接口请求回来的. 安装 cnpm install echarts --s (我这里用了淘宝镜像,不知道同学自 ...
- SEO是件贼有意思的事情 golang入坑系列
这两天迷上了SEO.真心看不起百度的竞价排名,但作为一个商业网站,赚钱是一件无可厚非的事情.只做活雷锋,没有大金主是做不长的.做完功课后,发现百度和google的SEO策略又不相同,几乎是无法通用.百 ...
- Retrofit网络请求库应用01
PS:什么是Retrofit? 在官方文档中有这样一句话--A type-safe HTTP client for Android and Java(一个类型安全的http client库),具体的话 ...