C++Primer学习笔记:第8章 IO库

  • C++语言不直接处理输入输出,而是通过一族定义在标准库中的类型来处理IO

    • iostream定义了用于读写流的基本类型
    • fstream定义了读写命名文件的类型
    • sstream定义了读写内存string对象的类型
  • 标准库使得我们能够忽略这些不同类型的流之间的差异,是通过继承机制实现的

  • 不能拷贝或者对IO对象赋值,因此也不能将形式参数或者返回类型设置为流类型,进行IO操作的函数通常是已引用方式传递和返回流,读写一个IO对象会改变其状态,因此传递和返回的引用不能是const

    strm::iostate	提供表达条件状态的完整功能
    strm::badbit	用来指出流已经崩溃
    strm::failbit	用来指出一个IO操作失败了
    strm::eofbit	用来指出流到达了文件结束
    strm::goodbit	用来指出流未处于错误状态,此值保证为零
    s.eof()			若流s的eofbit置位,返回true
    s.fail()		
    s.bad()
    s.good()		若流s处于有效状态,返回true
    s.clear()		所有条件状态复位,将流的状态设置为有效,返回void
    s.clear(flags)	根据给定的flags标志位将流s中对应条件状态位复位
    s.setstate(flags)同上
    s.rdstate()		返回流s的当前条件状态
    
    auto old_state = cin.rdstate();		//记住cin的当前状态
    cin.clear()							//使cin有效
    process_input(cin);					//使用cin
    cin.setstate(old_state);			//将cin置为原有状态
    cin.clear(cin.rdstate & ~cin.failbit & ~cin.badbit);	//复位failbit和badbit,保持eofbit不变
    
  • 通过缓冲机制,操作系统可以将程序的多个输出操作组合成单一的系统级写操作。(原因在于设备的写操作可能很耗时)

  • 导致缓冲刷新的原因:

    • 程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行
    • 缓冲区满
    • 使用操纵符endl显式刷新缓冲区
    • 在每个输出操作后,可以用操作符unitbuf设置流的内部状态,来清空缓冲区(默认情况下cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的)
    • 一个输出流可能被关联到另一个流。在这种情况下,当读写被关联的流时,关联到的流的缓冲区会被刷新
  • 除了endl外,还可以使用flushends刷新缓冲区,但是他们有不同的效果:

    cout << "hi" << endl;		//输出"hi\n"
    cout << "hi" << flush;		//输出"hi"
    cout << "hi" << ends;		//输出"hi "
    
  • 如果想在每次输出操作后都刷新缓冲区,我们可以使用unitbuf操纵符,它告诉流在接下来每次写操作后都进行一次flush操作

    cout << unitbuf;	//所有输出操作都会立即刷新缓冲区
    cout << nounitbuf;	//回到正常的缓冲方式
    
  • 调试/程序崩溃时要记得及时刷新缓冲区

  • 当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流(例如cincout)。交互式系统通常应该关联输入流和输出流。每个输入流最多关联到一个流,但多个流可以同时关联到同一个ostream

    cin.tie();				//返回cin关联的流,如果之前没有关联则返回空指针
    cin.tie(&cout);			//返回值同上,但是将cin与cout关联
    ostream *old_tie = cin.tie(nullptr);	//取消关联,同时保存关联的流的指针
    cin.tie(old_tie);		//恢复关联
    
  • 文件输入输出的流定义在头文件fstream

    fstream fstrm;
    fstream fstrm(s);		打开名为s的文件,s可以是string类型或者是一个指向C风格字符串的指针,默认的文件模式mode依赖							fstream的类型
    fstream fstrm(s, mode);
    fstrm.open(s);			打开名为s的文件,并将文件与fstrm绑定,返回void
    fstrm.close();			关闭与fstrm绑定的文件,返回void
    fstrm.is_open(s);		返回一个bool,指出与fstrm关联的文件是否打开成功且尚未关闭
    
  • 我们可以用fstream代替iostream&,即在需要接受一个iostream类型引用或者指针参数的函数可以用一个对应的fstreamsstream来调用

  • 在使用流之前检查是一个好的习惯

  • 当一个fstream对象被销毁时,close会自动被调用

  • 每个流都有一个关联的文件模式,用来指出如何使用文件

    in			以读方式打开,只可以对ifstream或fstream
    out			以写方式打开,只可以对ofstream或fstream,默认情况下,即使我们没有指定trunc,以out模式打开的文件也会被截				断,为了保留以out模式打开的文件的内容,我们必须同时指定app,或者指定infstream默认关联in和out
    app			每次操作均定位到文件末尾,只要trunc没有被设定就可以设定,包含out
    ate			打开文件后立即定位到文件末尾
    trunc		截断文件,只有当out也被设定时才能设定
    binary		以二进制方式进行IO
    
    //下面三种方式打开文件是等价的,都会截断文件
    ofstream out("file");
    ofstream out("file", ofstream::out);
    ofstream out("file", ofstream::out | ofstream::trunc);
    //为了保留文件的内容,我们必须显式指定app模式
    ofstream out("file", ofstream::app);
    ofstream out("file", ofstream::out | ofstream::app);
    
  • sstream头文件定义了三个类型来支持内存IO,这些类型可以向string写入数据,从string读取数据

  • istringstreamstring读取数据,ostringstreamstring写入数据,stringstream既可以读也可以写

    sstream strm;		
    sstream strm(s);		strm保存string类型的s的拷贝
    strm.str()				返回strm保存的string的拷贝
    strm.str(s)				将string s拷贝到strm中,返回void
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383564.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++Primer学习笔记:第7章 类

类的基本思想是数据抽象data abstraction和封装encapsulation。数据抽象是一种依赖于接口interface和实现implementation分离的编程技术 在类中&#xff0c;由类的设计者负责考虑类的实现过程&#xff0c;使用该类的程序员只需要抽象地思考类型做了什么&#xff0c;而无须了解…

每日一题:leetcode191.位1的个数

题目描述 题目分析 很自然地想到了二进制枚举&#xff0c;直接循环检查每一个二进制位。 class Solution { public:int hammingWeight(uint32_t n) {int ret 0;uint32_t t 1;for (int i 0; i < 32; i, t << 1) {if (n & t) {ret;}}return ret;} };AC之后看了…

每日一题:leetcode341.扁平化嵌套列表迭代器

题目描述 题目分析 这个题目自己大概花了一个小时&#xff0c;虽然是一遍AC&#xff0c;但是速度有点慢&#xff0c;太长时间不写代码导致自己对代码不太敏感&#xff0c;写起来慢腾腾的。 看到这个的想法就是&#xff0c;要用栈来保存列表的迭代器&#xff0c;这样将孩子列表…

每日一题:leetcode82. 删除排序链表中的重复元素 II

题目描述 题目分析 这才是正常的中等题难度嘛&#xff0c;昨天的中等题题解我半天看不懂。。。 首先&#xff0c;需要增加一个哑节点&#xff08;操作链表的常规操作&#xff09;&#xff0c;因为有可能删除首节点&#xff0c;我们不想要为首节点添加单独的逻辑。其次&#xf…

每日一题:leetcode456.132模式

题目描述 题目分析 我觉得这道题应该是我做过最难的中等题之一了&#xff0c;这是昨天的每日一题&#xff0c;但是昨天用nlogn的做法做出来以后在看题解&#xff0c;发现有些看不懂&#xff08;觉得题解有点故弄玄虚&#xff09;。然后今天中午又花了一点时间才搞懂&#xff0…

leetcode283.移动零

题目描述 题目分析 在写简单题放松&#xff0c;看到这道题第一个想法是用STL库函数&#xff0c;虽然知道大概要用双指针之类的&#xff0c;但是库函数爽哇。 class Solution { public:void moveZeroes(vector<int>& nums) {stable_sort(nums.begin(), nums.end(), …

每日一题:leetcode61.旋转链表

题目描述 题目分析 很容易发现&#xff0c;如果k是n的整数倍&#xff0c;相当于没有移动。这样直接对k%n使得k在一个可以接受的范围。 因为是顺序移动&#xff0c;各元素之间的相对位置保持不变&#xff0c;所以就想着将链表先变成一个环。然后再移动头指针&#xff0c;最后再…

每日一题:leetcode173.二叉搜索树迭代器

题目描述 题目分析 更加地觉得编程重要的不在于如何写代码&#xff0c;用什么具体的技巧&#xff0c;编码本身只是一种将思维呈现的方式&#xff0c;但是如果思维是不清晰的&#xff0c;那么就算懂得再多的编码的奇技淫巧也是没有什么帮助的。相反&#xff0c;如果有一个清晰的…

Ubuntu20.04 Clion/Pycharm/IDEA 输入中文+光标跟随解决方案

ibus输入法&#xff08;弃用&#xff09; 之前一直用的搜狗输入法&#xff0c;但是搜狗输入法无法在Jetbrains全家桶下使用&#xff0c;但是又需要输入中文&#xff0c;没有办法我只能下载了谷歌输入法&#xff0c;十分难用&#xff0c;但是也没有其他办法&#xff0c;经常到网…

leetcode11.盛最多水的容器

题目描述 题目分析 看到题目后第一个想法当然是O(n2)O(n^2)O(n2)的&#xff0c;但是数据范围是3e4&#xff0c;应该会超时&#xff0c;而且这种数据范围也不是让暴力求解的 。 相当于求解∑i<jmax((j−i)∗min(a[i],a[j]))\sum_{i<j}{max((j-i)*min(a[i],a[j]))}∑i<…

每日一题:leetcode190.颠倒二进制位

题目描述 题目分析 题目本身很简单&#xff0c;没觉得有什么技巧可以再进行优化了&#xff0c;觉得位运算是无法打乱相对顺序的&#xff0c;而这里需要进行镜像颠倒的操作。因此就踏实地写了一个循环。 在使用位运算得到每一位的时候&#xff0c;我吸取了经验&#xff0c;用一…

结构屈曲分析

结构屈曲分析主要用于判定结构受载后是否有失稳风险&#xff0c;作为工程应用&#xff0c;一般分为线性屈曲分析和非线性屈曲分析。 线性屈曲分析需要具备较多的前提条件&#xff0c;如载荷无偏心、材料无缺陷等&#xff0c;在实际工程应用中结构制作过程和加载方式很难达到线性…

每日一题:leetcode74.搜索二维矩阵

题目描述 题目分析 感觉这是一个放错标签的简单题。题目非常简单&#xff0c;思路应该很明确是二分&#xff0c;我很快写了一个&#xff08;虽然不小心把!打成调试了一会&#xff09;。 class Solution { public:bool searchMatrix(vector<vector<int>>& mat…

每日一题:leetcode90.子集贰

题目描述 题目分析 感觉这道题让自己对枚举排列有了一个更好的认识&#xff0c;感觉自己的这种思路不错。 假设没有重复元素&#xff08;退化成78.子集&#xff09;&#xff0c;我们应该怎么做&#xff1f;初始的时候幂集中只有一个空集&#xff0c;然后对每个元素&#xff0…

每日一题:leetcode1006.笨阶乘

题目描述 题目分析 因为顺序一定且没有括号&#xff0c;所以逻辑很简单。我们要顺序处理的矛盾在于&#xff0c;减号后面会再出现乘法和除法&#xff0c;我们不妨将对乘法和除法用一个临时值进行计算&#xff0c;计算结束后再合并到值里面&#xff0c;一般来讲乘法和除法的处理…

每日一题:leetcode80.删除有序数组中的重复元素贰

题目描述 题目分析 又是一道贴错标签的简单题&#xff0c;很明显的双指针&#xff0c;我的做法是用两个变量保存是否需要记录&#xff0c;官方题解的做法是直接判断&#xff0c;人家的高明一些 class Solution { public:int removeDuplicates(vector<int>& nums) {…

每日一题:leetcode81.搜索旋转排序数组Ⅱ

题目描述 题目分析 不含重复元素的题解&#xff08;leetcode33&#xff09; 这道题也是我们算法课的一道编程题&#xff0c;写完以后发现当时的思路和现在没有什么变化&#xff0c;果然是自己啊。我的想法是先判断区间整体是升序的还是旋转的&#xff0c;如果是升序的就按照正…

C++ JSON库:JSON for Morden C++

绪论 最近因为项目的需要&#xff0c;需要对JSON进行一定的数据处理&#xff0c;因为想要用C进行编码&#xff0c;便对C的JSON库进行的调研&#xff0c;发现这个库比较好用&#xff1a;JSON for Morder C。 使用指南 想要使用这个json库&#xff0c;只需要在源文件中包含jso…

Linux信号实现精确到微秒的sleep函数:通过sigsuspend函数解决时序竞态问题

原理就是先使用定时器定时&#xff0c;然后再使用pause函数或者sigsuspend函数主动阻塞挂起&#xff0c;最终恢复现场。 如果使用pause函数的话&#xff0c;优点是使用简单&#xff0c;缺点是有可能产生时序竞态&#xff0c;导致进程一直阻塞下去&#xff1a;在定时和挂起之间…

Linux创建多个子进程并通过捕获SIGCHLD信号进行非阻塞回收

我们通过fork函数创建多个子进程&#xff0c;并通过exec函数族在子进程中进行其他的工作&#xff0c;但是为了避免僵尸进程&#xff0c;我们要对子进程进行回收。常用的回收方式是wait或者waitpid进行阻塞回收&#xff0c;因为如果非阻塞回收很难把握时机&#xff0c;而阻塞回收…