streambuf类为缓冲区提供内存,并提供了用于填充缓冲区,访问缓冲区,刷新新缓冲区和管理缓冲区内存的类方法。

ios_base类表示流的一般特征,如是否可读,是二进制还是文本流等。

ios类基于ios_base,其中包括了一个之指向streambuf对象的的指针成员。

缓冲区介绍

输入:从磁盘上读取大量信息,将这些信息存储在缓冲区中,然后每次从缓冲区读取一个字节,到达缓冲区尾部,在从磁盘上读取另一块数据。

   但是键盘每次输入一个字符时可以用不缓冲区,但是用缓冲区输入可以让程序没有传给程序之前返回并改正,c++通常是用户按下回车键刷新缓冲区,

输出:程序首先填满缓冲区,然后把整块数据给磁盘,并清空缓冲区,已备下一批输入。

   对于输出屏幕,输出换行符时刷新缓冲区(也可能是其他:当输入语句到达时,他刷新缓冲区中当前所有输出)

刷新缓冲:用cout将字节发送给标准输出时由于ostram类对cout对象输出进行缓冲,输出并不会直接发送到目标地址,而是在缓冲区中,直到缓冲区填满,然后flush缓冲区,把内容发送出去并且清空缓冲,缓冲区通常为512byte或其整数倍。

  对于屏幕来说,程序不必等到缓冲区填满,1.将换行符发送到缓冲区时刷新缓冲区;2.输入即将发生时刷新缓冲区。

  由于程序运行时并不总是知道外部输入的进度,很难控制是不是全部清除输入缓冲区的内容。通常我们有可能只是希望放弃输入缓冲区中的一部分,而不是全部。比如清除掉当前行、或者清除掉行尾的换行符等等。但要是缓冲区中已经有了下一行的内容,这部分可能是我们想保留的。这个时候最好不要用sync()。可以考虑用ignore函数代替

  1. cin.ignore(numeric_limits<std::streamsize>::max(),'/n');//清除当前行
  2. cin.ignore(numeric_limits<std::streamsize>::max()); //清除cin里所有内容

numeric_limits<std::streamsize>::max()不过是climits头文件定义的流使用的最大值,你也可以用一个足够大的整数代替它。使用ignore显然能比sync()更精确控制缓冲区

cin.ignore(1024,'\n'),通常把第一个参数设置得足够大,这样实际上总是只有第二个参数'\n'起作用,所以这一句就是把回车(包括回车)之前的所以字符从输入缓冲(流)中清除出去。

  1. flush(cout);
  2. cout<<"hello word"<<flush;
  3. cout<<"hello word"<<endl;//刷新缓冲区并插入换行符

以上三种方式均可以刷新缓冲区

但cout<<'\n';只是输出换行符,不刷新缓冲区;\n只代表换行的转义字符;\n是C中间的格式输出换行,C++保留了下来;输出'\n'是实际输出了的'\10',往输出流里添加了信息,所有的字符都是'\xx'的形式,换行符也是,你用其它任何字符输出一下,前面都会有四个'*'填充的

程序员常常在调试时添加打印语句。这类语句应该保证‘一直’刷新流。否则,如果程序崩溃,输出可能还停留在缓冲区中,从而导致关于程序崩溃位置的错误推断

缓冲区的操作https://liam.page/2017/12/31/buffer-of-stream-in-Cpp/   https://izualzhy.cn/stream-buffer

  1. #include <iostream>
  2. #include <sstream>
  3. #include <cstdio>
  4. using namespace std;
  5.  
  6. int main()
  7. {
  8. stringstream ss;
  9. streambuf *buf=cout.rdbuf();
  10. //使用了新的缓冲区后,字符串不会输出到屏幕,而是由stringstream管理
  11. cout.rdbuf(ss.rdbuf());
  12. cout<<"hello word"<<endl;
  13.  
  14. printf("%s",ss.str().c_str());
  15.  
  16. cout.rdbuf(buf);
  17. cout<<"hello word"<<endl;
  18. return ;
  19. }

基于控制台

继承关系

c++将输出看做字节流,将数值类型转换为文本形式表示的字符流(将数据内部表示(二进制形式)转换为字符字节组成的输出流)

cout:对于void*类型,打印其地址数值(一端关联显示器另一端关联程序

cin:从非空白字符开始,到与目标类型不匹配的第一个字符之间的全部内容(一端关联键盘另一端关联程序

cerr:关联输出设备(通常为显示器)没有缓冲区,信息直接输出到屏幕,不会等到新的换行或缓冲区满

clog:关联输出设备(通常为显示器)有缓冲区

ostream:ostream &<<使用该操作符返回一个指向该对象的引用,插入操作符的返回值是调用该操作符的对象

  1. int a=,sum=;
  2. while(cin>>a)
  3. sum+=a;
  4. //输入1 2 3 4 5 6c 60

由于输入缓冲,在用户键入回车之前不会发送给程序,但是循环在了对字符c出停止了处理,导致cin>>a返回alse,终止循环

状态流

  cin或cout对象包含一个描述状态流的数据成员(继承于ios_base)被定义为iostate,是bitmask类型,由eofbit,badbit,failbit,每一位可以是1(设置)0(清除)

clear:将状态设置为他的参数,默认0清楚全部状态;clear(eofbit),eofbit被设置,其他清除

setstate:setstate(eofbit)只设置eofbit,不影响其他位

get()与getline():get将换行符留在流中,getline抽取并丢弃输入流中的换行符

  1. char tem[];
  2. while(cin.get(tem,))//空行终止
  3. {
  4. //...
  5. }
  6.  
  7. //空行不终止,因为空行不导致getline设置failbit,getline抽取换行符并丢弃
  8. while(cin.getline(tem,))
  9. {
  10. //...
  11. }
  12. //空行终止
  13. while(cin.getline(tem,)&&tem[]!='\0')
  14. {
  15. //...
  16. }

I/O异常

  exceps()返回一个为字段,包含三位:eofbit,failbit,badbit。修改流状态后,clear()函数将当前流状态与exceps()的返回值比较,如果返回值中某一位被设置,当前流转态位对应位也被设置,则clear()引发ios_base::failure异常,exceptions()返回good不会引发异常,ios_base::failure从exception类派生,因此包含一个what()函数。

  1. #include <iostream>
  2. #include <exception>
  3. using namespace std;
  4.  
  5. int main()
  6. {
  7. cin.exceptions(ios_base::failbit);
  8.  
  9. int a=,sum=;
  10. try
  11. {
  12. while(cin>>a)
  13. sum+=a;
  14. }
  15. catch(ios_base::failure &bf)
  16. {
  17. cout<<bf.what()<<endl;
  18. }
  19.  
  20. cout<<"last input:"<<a<<endl;
  21. cout<<"sum:"<<sum<<endl;
  22. return ;
  23. }
  1. #include <iostream>
  2. #include <exception>
  3. #include <fstream>
  4. using namespace std;
  5.  
  6. //filebuf in;
  7. //istream i(&in);
  8. int main()
  9. {
  10. int a=,sum=;
  11. while(cin>>a)//只有状态流良好(所有为都被清楚)的情况下,while或if才返回true
  12. sum+=a;
  13.  
  14. cout<<"last input:"<<a<<endl;
  15. cout<<"sum:"<<sum<<endl;
  16.  
  17. if(cin.fail()&&!cin.eof())
  18. {
  19. cin.clear();
  20. while(!isspace(cin.get()))//get提供不跳过空白字符读的功能
  21. continue;
  22. }
  23. else
  24. {
  25. cout<<" i cannot go on"<<endl;
  26. exit();
  27. }
  28. cout<<"now input a new number:";
  29. cin>>a;
  30.  
  31. return ;
  32. }

cin.get(char &):到达文件末尾(真正的文件末尾,或键盘仿真文件末尾---win下ctrl+z---UNIX下ctrl+d,都不会给参数赋值,返回eof

cin.get():返回int类型的值,后不能跟抽取操作符,如:cin.get().get()>>c;

基于文件

继承关系

程序写入文件

  1. 创建一个ofstream对象管理输出流
  2. 将对象与特定的文件关联
  3. 用cout的方式使用该对象
  4. 使用colse()显示关闭文件的链接;(对象过期时(程序中止))文件的链接会自动关闭
    1. #include <iostream>
    2. #include <fstream>
    3. using namespace std;
    4.  
    5. int main()
    6. {
    7. ofstream of;
    8. of.open("1.txt");
    9. //ofstream of("1.txt");//也可以用构造函数
    10.  
    11. of<<"ds";
    12. of.close();//关闭文件将刷新缓冲区,确保文件被更新
    13. return ;
      }

读取文件

  1. 创建一个ifstream对象管理输出流
  2. 将对象与特定的文件关联
  3. 用cin的方式使用该对象
  4. 使用colse()显示关闭文件的链接;(对象过期时(程序中止))文件的链接会自动关闭
    1. #include <iostream>
    2. #include <fstream>
    3. using namespace std;
    4.  
    5. int main()
    6. {
    7. ifstream fin;
    8. fin.open("1.txt");
    9. //ifstream fin("1.txt");//也可以用构造函数,可以用is_open()检查是否打开成功,若成功流状态为0
    10.  
    11. string s;
    12. fin>>s;
    13. cout<<s<<endl;
    14.  
    15. fin.close();//只是断开文件的链接,对象与他的缓冲区仍然存在
    16. return ;
    17. }

当文件流作为类成员时,其初始化只能是初始化列表方式,即构造对象时文件,不能在构造函数体中进行操作,否则文件打开失败。

文本文件与二进制文件

  文本文件:

    所有内容都储存为文本,如:以文本格式存储123456,将存储6个字符,计算机内部将浮点数转为字符格式,这是<<插入操作符的工作;写文本文件时,linux,UNIX。dos c++自动将换行符转为回车和换行;读文本文件时,将本地的换行符转为c++格式;macintosh c++将换行转为回车。

  二进制文件:

    计算机不存储字符,而存储64位double;字符的二进制和文本表示一样(字符的ASCII二进制表示);较为精确,二进制保存数据更快,不需要转换,占用空间小,可大量存储;但二进制对于换行符,有歧义。二进制与文本文件的末未检测方式也不同。

  二进制和文本模式的区别:
  在windows系统中,文本模式下,文件以"\r\n"代表换行。若以文本模式打开文件,并用fputs等函数写入换行符"\n"时,函数会自动在"\n"前面加上"\r"。即实际写入文件的是"\r\n" 。
  在类Unix/Linux系统中文本模式下,文件以"\n"代表换行。所以Linux系统中在文本模式和二进制模式下并无区别

  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4.  
  5. struct Stu
  6. {
  7. int age;
  8. double weight;
  9. }stu;
  10.  
  11. int main()
  12. {
  13. ofstream of;
  14. of.open("1.txt");
  15.  
  16. //到达stu的结构地址,并且将6个字节复制到与of相关的文件中,用write函数可以以二进制形式存储数据
  17. of.write((char *)&stu,sizeof(stu));
  18. of.close();//关闭文件将刷新缓冲区,确保文件被更新
  19.  
  20. //将文件中的sizeof(stu)个字节复制到结构体中
  21. ifstream fin("1.txt");
  22. fin.read((char *)&stu,sizeof(stu));
  23. return ;
  24. }

基于字符串的I/O

继承关系

  1. #include <iostream>
  2. #include <sstream>
  3. using namespace std;
  4.  
  5. int main()
  6. {
  7. ostringstream os;
  8. string s("");
  9. os<<s;
  10. cout<<os.str()<<endl;
  11.  
  12. ostringstream _os;
  13. _os<<os.str();
  14. cout<<_os.str()<<endl;//让_os从os中提取数据,str()成员函数的使用可以让istringstream对象返回一个string字符串
  15.  
  16. return ;
  17. }

清空stringstream对象中的内容

  1. vector<string> s(v.size(),"");//确定字符串数组的大小
  2. stringstream ss;
  3. for(int i=;i<v.size();++i)
  4. {
  5. ss<<v[i];
  6. s[i]=ss.str();
  7. ss.str(""); //清空stringstream对象中的内容,clear()只是清空了流的状态
  8. }

c++中的流的更多相关文章

  1. [Node.js] Node.js中的流

    原文地址:http://www.moye.me/2015/03/29/streaming_in_node/ 什么是流? 说到流,就涉及到一个*nix的概念:管道——在*nix中,流在Shell中被实现 ...

  2. 理解Java中字符流与字节流的区别

    1. 什么是流 Java中的流是对字节序列的抽象,我们可以想象有一个水管,只不过现在流动在水管中的不再是水,而是字节序列.和水流一样,Java中的流也具有一个“流动的方向”,通常可以从中读入一个字节序 ...

  3. .NET客户端下载SQL Server数据库中文件流保存的大电子文件方法(不会报内存溢出异常)

    .NET客户端下载SQL Server数据库中文件流保存的大电子文件方法(不会报内存溢出异常) 前段时间项目使用一次性读去SQL Server中保存的电子文件的文件流然后返回给客户端保存下载电子文件, ...

  4. 谈一谈Java8的函数式编程(二) --Java8中的流

    流与集合    众所周知,日常开发与操作中涉及到集合的操作相当频繁,而java中对于集合的操作又是相当麻烦.这里你可能就有疑问了,我感觉平常开发的时候操作集合时不麻烦呀?那下面我们从一个例子说起. 计 ...

  5. Java中IO流的总结

    有关Java中IO流总结图 流分类 按方向分 输入流 输出流 按单位分 字节流 字符流 按功能分 节点流 处理流(过滤流) 其他 所有的流继承与这四类流:InputSteam.OutputStream ...

  6. java中有关流操作的类和接口

    一.java操作l流有关的类和接口 1.File 文件类 2.RandomAccessFile 随机存储文件类 3.InputStream 字节输入流 4.OutputStream 字节输出流 5.R ...

  7. ASP.NET Core SignalR中的流式传输

    什么是流式传输? 流式传输是这一种以稳定持续流的形式传输数据的技术. 流式传输的使用场景 有些场景中,服务器返回的数据量较大,等待时间较长,客户端不得不等待服务器返回所有数据后,再进行相应的操作.这时 ...

  8. node.js中stream流中可读流和可写流的使用

    node.js中的流 stream 是处理流式数据的抽象接口.node.js 提供了很多流对象,像http中的request和response,和 process.stdout 都是流的实例. 流可以 ...

  9. Java中IO流中的装饰设计模式(BufferReader的原理)

    本文粗略的介绍下JavaIO的整体框架,重在解释BufferReader/BufferWriter的演变过程和原理(对应的设计模式) 一.JavaIO的简介 流按操作数据分为两种:字节流与字符流. 流 ...

  10. mongoose中的流查询stream query

    mongoose中的流查询stream query,功能类似于php中的mysql_fetch_array,每次从集合中获取一条记录(文档) var cursor = Person.find({ oc ...

随机推荐

  1. C#下实现的基础K-MEANS多维聚类

    资源下载 #本文PDF版下载 C#下实现的基础K-MEANS多维聚类PDF #本文代码下载 基于K-Means的成绩聚类程序 前言 最近由于上C # 课的时候,老师提到了-我们的课程成绩由几个部分组成 ...

  2. 秒杀多线程第三篇 原子操作 Interlocked系列函数

    上一篇<多线程第一次亲密接触 CreateThread与_beginthreadex本质区别>中讲到一个多线程报数功能.为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是 ...

  3. hdu-3276-dp+二分+单调队列

    Star Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  4. 基础最短路(模板 dijkstra)

    Description 某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多 ...

  5. 合法的MAC地址

    以太网的地址为48位,由ieee统一分配给网卡制造商,每个网卡的地址都必须是全球唯一的.共6个字节的长度 字节 5 4 3 2 1 0  位 47..40 39..32 31..24 23..16 1 ...

  6. C/S架构系统自动化测试入门

    所谓C/S架构即Client/Server(客户端/服务器架构).虽然近年来C/S架构产品越来越少,大有被B/S(Browser/Server 浏览器/服务器)架构超越的趋势,但C/S还是有B/S不可 ...

  7. glusterfs分布式存储

    一,分布式文件系统理论基础 1.1 分布式文件系统出现 计算机通过文件系统管理,存储数据,而现在数据信息爆炸的时代中人们可以获取的数据成指数倍的增长,单纯通过增加硬盘个数来扩展计算机文件系统的存储容量 ...

  8. CDMA LTE FAQ2

    1.UE等级 LTE CAT4,应该指的是LTE Category4,字面意思是LTE的ue-Category设置为4.ue-Category指的是UE的接入能力等级.也就是UE能够支持的传输速率的等 ...

  9. 根据ip,实现地址信息查询接口

    偶然发现的360搜索的ip查询接口,记录下: 接口地址:https://m.so.com/position 使用方式1:传ip 如访问https://m.so.com/position?ip=47.1 ...

  10. 使用MyEclipse开发Java EE应用:EJB项目开发初探(上)

    你开学,我放价!MyEclipse线上狂欢继续!火热开启中>> [MyEclipse最新版下载] 一.MyEclipse EJB开发工具 Enterprise Java Beans (EJ ...