streambuf类为缓冲区提供内存,并提供了用于填充缓冲区,访问缓冲区,刷新新缓冲区和管理缓冲区内存的类方法。
ios_base类表示流的一般特征,如是否可读,是二进制还是文本流等。
ios类基于ios_base,其中包括了一个之指向streambuf对象的的指针成员。
缓冲区介绍
输入:从磁盘上读取大量信息,将这些信息存储在缓冲区中,然后每次从缓冲区读取一个字节,到达缓冲区尾部,在从磁盘上读取另一块数据。
但是键盘每次输入一个字符时可以用不缓冲区,但是用缓冲区输入可以让程序没有传给程序之前返回并改正,c++通常是用户按下回车键刷新缓冲区,
输出:程序首先填满缓冲区,然后把整块数据给磁盘,并清空缓冲区,已备下一批输入。
对于输出屏幕,输出换行符时刷新缓冲区(也可能是其他:当输入语句到达时,他刷新缓冲区中当前所有输出)
刷新缓冲:用cout将字节发送给标准输出时由于ostram类对cout对象输出进行缓冲,输出并不会直接发送到目标地址,而是在缓冲区中,直到缓冲区填满,然后flush缓冲区,把内容发送出去并且清空缓冲,缓冲区通常为512byte或其整数倍。
对于屏幕来说,程序不必等到缓冲区填满,1.将换行符发送到缓冲区时刷新缓冲区;2.输入即将发生时刷新缓冲区。
由于程序运行时并不总是知道外部输入的进度,很难控制是不是全部清除输入缓冲区的内容。通常我们有可能只是希望放弃输入缓冲区中的一部分,而不是全部。比如清除掉当前行、或者清除掉行尾的换行符等等。但要是缓冲区中已经有了下一行的内容,这部分可能是我们想保留的。这个时候最好不要用sync()。可以考虑用ignore函数代替
cin.ignore(numeric_limits<std::streamsize>::max(),'/n');//清除当前行 cin.ignore(numeric_limits<std::streamsize>::max()); //清除cin里所有内容
numeric_limits<std::streamsize>::max()不过是climits头文件定义的流使用的最大值,你也可以用一个足够大的整数代替它。使用ignore显然能比sync()更精确控制缓冲区
cin.ignore(1024,' '),通常把第一个参数设置得足够大,这样实际上总是只有第二个参数' '起作用,所以这一句就是把回车(包括回车)之前的所以字符从输入缓冲(流)中清除出去。
flush(cout); cout<<"hello word"<<flush; cout<<"hello word"<<endl;//刷新缓冲区并插入换行符
以上三种方式均可以刷新缓冲区
但cout<<' ';只是输出换行符,不刷新缓冲区; 只代表换行的转义字符; 是C中间的格式输出换行,C++保留了下来;输出' '是实际输出了的'10',往输出流里添加了信息,所有的字符都是'xx'的形式,换行符也是,你用其它任何字符输出一下,前面都会有四个'*'填充的
程序员常常在调试时添加打印语句。这类语句应该保证‘一直’刷新流。否则,如果程序崩溃,输出可能还停留在缓冲区中,从而导致关于程序崩溃位置的错误推断
缓冲区的操作https://liam.page/2017/12/31/buffer-of-stream-in-Cpp/ https://izualzhy.cn/stream-buffer
#include <iostream> #include <sstream> #include <cstdio> using namespace std; int main() { stringstream ss; streambuf *buf=cout.rdbuf(); //使用了新的缓冲区后,字符串不会输出到屏幕,而是由stringstream管理 cout.rdbuf(ss.rdbuf()); cout<<"hello word"<<endl; printf("%s",ss.str().c_str()); cout.rdbuf(buf); cout<<"hello word"<<endl; return 0; }
基于控制台
继承关系
c++将输出看做字节流,将数值类型转换为文本形式表示的字符流(将数据内部表示(二进制形式)转换为字符字节组成的输出流)
cout:对于void*类型,打印其地址数值(一端关联显示器另一端关联程序)
cin:从非空白字符开始,到与目标类型不匹配的第一个字符之间的全部内容(一端关联键盘另一端关联程序)
cerr:关联输出设备(通常为显示器)没有缓冲区,信息直接输出到屏幕,不会等到新的换行或缓冲区满
clog:关联输出设备(通常为显示器)有缓冲区
ostream:ostream &<<使用该操作符返回一个指向该对象的引用,插入操作符的返回值是调用该操作符的对象
int a=0,sum=0; while(cin>>a) sum+=a; //输入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抽取并丢弃输入流中的换行符
char tem[60]; while(cin.get(tem,60))//空行终止 { //... } //空行不终止,因为空行不导致getline设置failbit,getline抽取换行符并丢弃 while(cin.getline(tem,60)) { //... } //空行终止 while(cin.getline(tem,60)&&tem[0]!='