本文主要是介绍C++标准库笔记:13.10 连接Input Streams 和 Output Streams,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
常常会需要连接两个streams:
- 你可能想在读取数据前确保屏幕上已经打印出文字(用tie函数来实现)
- 以不同的格式处理同一个stream(用共享stream缓冲区来实现,对应函数为rdbuf)
- 将标准streams重定向到其它streams
- 对同一个stream读取和改写–主要发生在file stream身上
以tie()完成”松耦合“
tie( ostream* output_strm )
函数将output stream连接到指定的stream(output或input)上。
- output stream可以被连接到output stream上,也可以被连接到input stream上。
- 同一个output stream可以被连接到多个output stream或多个input stream身上。
- 一个stream(output或input)只能连接一个output stream
缺省情况 下,标准input装置以下列方式 连接一个output stream:
std::cin.tie( &std::cout )
std::wcin.tie( &std::wcout)
这样就保证了在输入之前,一定会先清空output缓冲区,即调用output stream的flush函数。当编写以下代码运行时,总是会在屏幕上先打印出一段文字
int x = 0;
cout << "Please enter x: ";
cin >> x;
使用如下语句可删除缺省的连接
std.cin.tie( static_cast<std::ostream*>(0) )
,清除后,因为缓冲区未被flush,可能导致在输入时,屏幕上文字还未打印出的情况(注:这是我的理解,实验时没验证这个理解)。
注:flush函数是output stream才用,input stream无此函数,所以tie函数的参数是一个output stream指针。
以stream缓冲区完成”紧耦合“
同一个缓冲区被多个stream对象共享,多个不同的stream,可以有其不同的格式,格式是针对stream对象而对缓冲区没影响。
//hexout析构函数不删除构造传入的缓冲区,
//毕竟该缓冲区不是由hexout创建的
ostream hexout( cout.rdbuf() );
hexout << std::hex << std::showbase << std::uppercase;//以十六进制输出
hexout << 15 << endl;
hexout << -1 << endl;//以默认格式(十进制)输出
cout << 15 << endl;
cout << -1 << endl;
以上方法的缺点:stream对象的构造与析构会有更多的开销。同时请注意stream对象在析构时不清空缓冲区,要确保被清空,必须手动进行。
注:只有basic_istream和basic_ostream不销毁缓冲区(在类内部有一指向缓冲区的指针,在构造函数中传入此缓冲区对象地址,如cin,cout等标准对象在构造时传入全局静态的缓冲区变量地址),其它的streams都会销毁最初分配的stream缓冲区(缓冲区以类的成员对象存在,类销毁,其自然就销毁了),但它们不销毁以rdbuf()设置的缓冲区。
将标准streams重定向
c++中通过设置stream缓冲区来实现重定向到其它的stream中。
#include <iostream>
#include <fstream>int main()
{{std::ofstream file("cout.txt", std::ios::app );if ( !file ){std::cout << "open file 'cout.txt' failed" << std::endl;return -1;}file.copyfmt( std::cout );std::streambuf* oldbuf = std::cout.rdbuf( file.rdbuf() );//此句输出到文件中std::cout << "this is test" << std::endl;//此处恢复非常重要,因为file是个局部对象,当file析构时,其//相应的streambuf对象也会被析构。如果此处不恢复的话,cout将//不能再被用于输出(rdbuf已经指向一块被释放的空间),//当然也无法在程序结束时安全的销毁std::cout.rdbuf( oldbuf );}//恢复,此句输出到控制台std::cout << "this is second test" << std::endl;return 0;
}
用于读写的stream
运用同一个stream进行读写操,通常有以下三种方法:
使用fstream, `
fstream file( "example.txt", ios::in | ios::out | ios::trunc );
使用两个不同的stream对象,一个用于读,一个用于写,共享同一缓冲区。以下示例中out对象一定要同时打开读写标志位,若只打开其中一个,则读或写的操作是未定义的。
ofstream out( "example.txt", ios::in | ios::out | ios::app ); std::istream in( out.rdbuf() );
产生一个file stream的缓冲区,并将它安装至两个stream对象上(一个读,一个写)。
filebuf buffer; ostream out( &buffer ); istream in( &buffer ); buffer.open( "example.txt", ios::in | ios::out | ios::app );
以下是示例代码:
#include <iostream>
#include <fstream>using namespace std;int main()
{//方法1{fstream file( "example.txt", ios::in | ios::out | ios::trunc );if ( !file ){cout << "open file failed" << endl;return -1;}for ( int i = 1; i <= 2; ++i ){//写入一行file << i << ". line" << endl;//读取所有内容并打印出来 file.seekg( 0 );char c;while ( file.get( c ) ){cout.put( c );}cout << endl;//清除eofbit, failbitfile.clear();}}//方法2{ofstream out( "example.txt", ios::in | ios::out | ios::app );if ( !out ){cout << "open file failed" << endl;return -1;}std::istream in( out.rdbuf() );for ( int i = 1; i <= 2; ++i ){out << i << ". line" << endl;in.seekg( 0 );char c;while( in.get( c ) ){cout.put( c );}cout << endl;//清除eofbit, failbitin.clear();}}//方法3{filebuf buffer;ostream out( &buffer );istream in( &buffer );buffer.open( "example.txt", ios::in | ios::out | ios::app );if ( !buffer.is_open() ){cout << "open file failed" << endl;return -1;}for ( int i = 1; i <= 2; ++i ){out << i << ". line" << endl;in.seekg( 0 );char c;while( in.get( c ) ){cout.put( c );}cout << endl;//清除eofbit, failbitin.clear();}}return 0;
}
输出:
1. line1. line
2. line1. line
2. line
1. line1. line
2. line
1. line
2. line1. line
2. line
1. line
2. line
1. line1. line
2. line
1. line
2. line
1. line
2. line
这篇关于C++标准库笔记:13.10 连接Input Streams 和 Output Streams的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!