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

相关文章

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝