C++标准库笔记:13.10 连接Input Streams 和 Output Streams

2023-10-24 10:08

本文主要是介绍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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/274416

相关文章

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

C++作用域和标识符查找规则详解

《C++作用域和标识符查找规则详解》在C++中,作用域(Scope)和标识符查找(IdentifierLookup)是理解代码行为的重要概念,本文将详细介绍这些规则,并通过实例来说明它们的工作原理,需... 目录作用域标识符查找规则1. 普通查找(Ordinary Lookup)2. 限定查找(Qualif

java连接opcua的常见问题及解决方法

《java连接opcua的常见问题及解决方法》本文将使用EclipseMilo作为示例库,演示如何在Java中使用匿名、用户名密码以及证书加密三种方式连接到OPCUA服务器,若需要使用其他SDK,原理... 目录一、前言二、准备工作三、匿名方式连接3.1 匿名方式简介3.2 示例代码四、用户名密码方式连接4

C/C++ chrono简单使用场景示例详解

《C/C++chrono简单使用场景示例详解》:本文主要介绍C/C++chrono简单使用场景示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录chrono使用场景举例1 输出格式化字符串chrono使用场景China编程举例1 输出格式化字符串示

MySQL 表的内外连接案例详解

《MySQL表的内外连接案例详解》本文给大家介绍MySQL表的内外连接,结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录表的内外连接(重点)内连接外连接表的内外连接(重点)内连接内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,我

C++/类与对象/默认成员函数@构造函数的用法

《C++/类与对象/默认成员函数@构造函数的用法》:本文主要介绍C++/类与对象/默认成员函数@构造函数的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录名词概念默认成员函数构造函数概念函数特征显示构造函数隐式构造函数总结名词概念默认构造函数:不用传参就可以

C++类和对象之默认成员函数的使用解读

《C++类和对象之默认成员函数的使用解读》:本文主要介绍C++类和对象之默认成员函数的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、默认成员函数有哪些二、各默认成员函数详解默认构造函数析构函数拷贝构造函数拷贝赋值运算符三、默认成员函数的注意事项总结一

C/C++中OpenCV 矩阵运算的实现

《C/C++中OpenCV矩阵运算的实现》本文主要介绍了C/C++中OpenCV矩阵运算的实现,包括基本算术运算(标量与矩阵)、矩阵乘法、转置、逆矩阵、行列式、迹、范数等操作,感兴趣的可以了解一下... 目录矩阵的创建与初始化创建矩阵访问矩阵元素基本的算术运算 ➕➖✖️➗矩阵与标量运算矩阵与矩阵运算 (逐元

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

C/C++和OpenCV实现调用摄像头

《C/C++和OpenCV实现调用摄像头》本文主要介绍了C/C++和OpenCV实现调用摄像头,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录准备工作1. 打开摄像头2. 读取视频帧3. 显示视频帧4. 释放资源5. 获取和设置摄像头属性