第8章 IO库

8.1 IO类

image.png
使用istream>>和<ifstream和istringstream都继承自istream

IO对象无拷贝无赋值

  • 形参、返回值只能是引用类型
  • IO会改变IO对象状态,也不能const

    条件状态

    image.png
    image.png

  • 确定流有效可以把流对象当条件用,实际是调用!s.fail()

也就是说good()和fail()是确定流总体有效的方法

  • iostate类型与机器无关,当作位集合使用,可以使用位运算符

image.png

  • 无参clear()清除所有错误标志位
    有参clear()设置新状态

    练习

    8.1 & 8.2

    image.png

    管理输出缓冲

    image.png
    image.png

  • cout<<endl换行后刷新

  • cout<<flush立即刷新
  • cout<<ends输出空字符后刷新
  • cout<<unitbuf每次输出后都刷新缓冲区
  • cout<

    关联输入输出流

    交互程序需要在读之前输出提示信息,应该关联;
    标准库关联了cin和cout;每次cin都会刷新输出流;
    image.png
    https://en.cppreference.com/w/cpp/io/basic_ios/tie(关于tie函数的介绍)

    8.2 文件IO

    image.png
    其他IO类型不支持这些操作

    使用文件流对象

  • ifstream in(“../string.txt”);

Clion中由于exe文件在debug文件里,debug和cpp在同一级目录,所以要写../表示上一层目录的文件
文件路径参见https://blog.csdn.net/Young__Fan/article/details/80152501

练习

8.4

image.pngimage.pngimage.png

8.5

每一行作为独立元素需要getline,而每个词单独直接流输入即可
image.pngimage.png

文件模式

image.png
image.png

  • 关于trunc模式,截断文件模式会使流丢弃文件内容,如

image.pngimage.png
会把之前的string.txt全部舍弃重写文件,因此最好加上app从末尾附加内容

8.3 string流

image.png

使用istringstream

注意书上的使用场景,需要处理一行和一行中的部分字符串时使用

练习

8.10

image.pngimage.pngimage.png

第9章 顺序容器

9.1 概述

image.png

  • 除array外,其他都是动态大小容器
  • string和vector存储空间连续
  • list和forward_list链表额外内存开销很大
  • 其他容器会保存自己的大小,size()是O(1)操作;
    但是单向链表不支持size(),会影响性能

image.png

9.2 容器库

image.png
本节介绍第一种通用操作
image.png
image.png
image.png

迭代器

image.png

  • 单向链表不支持—

image.png

  • 运算只能应用于string、vector、deque和array

迭代器范围
[begin, end)包含容器的所有元素;
end不可以在begin之前;
理想情况:

  1. begin != end则区间内有元素
  2. begin = end则区间内无元素
  3. begin可++到end,表示遍历容器

    练习

    9.4
    image.png
    9.5
    image.png
    这两个程序都有优化空间,没必要使用迭代器i,用形参begin++到end效果一样且开销更小
    9.6
    list不支持迭代器的算术运算,主要是因为list不连续存储元素,很难直接说指针大的元素就在容器的前面

    容器类型成员

    包括size_type、迭代器和const迭代器(还有反向迭代器)
    容器常用成员类型:
    image.png

    begin和end成员

    image.png

    练习

    9.9
    image.png
    解释:begin被重载是因为可能容器是const对象,而const对象只可以使用const成员,此时const的begin版本返回常迭代器
    9.10
    it1是普通迭代器,其他三个都是const迭代器

    容器定义和初始化

    image.png
    拷贝初始化容器
  • 直接拷贝要求容器和元素类型相同
  • 拷贝迭代器范围只需要元素类型可以转换过去即可
    拷贝范围都是左闭右开

构造函数

  • 如果元素类型没有默认初始化的方式,则不能只传一个大小n,还需要初始值t
  • 只有顺序容器支持seq(n)这种初始化方式

array大小固定
初始化需要指定大小
image.png
内置数组不可以复制,但是array容器、元素类型相同时就可以拷贝

练习

9.11

image.png

9.12

拷贝容器可以得到容器的所有值,但是迭代器可以灵活获取任意区间内的值

9.13

两种情形都得使用迭代器范围初始化,因为容器类型不同

赋值和swap——难点

image.png

  • 赋值将使得=左边的容器完全变为右边的副本,包括size;
  • array可以列表初始化,同类型可以拷贝
    但是不可以列表再赋值
  • assign格式相当于初始化,只是再赋值时使用,类型可以转换就可以assign

swap

  1. 对于一般容器,swap不进行任何元素移动,只是交换了容器对象内部对容器数据的引用;

(vector内部有三个指针指向自己的数据,VS下调试可看到swap后是指针的指向发生变化)
swap之后原来的迭代器、引用和指针都没有失效,还指向当初的位置,但已经属于不同的容器
image.png
image.png

  1. 但是对于array,swap会真正通过循环交换数组内元素,操作也不是O(1)复杂度;

image.pngimage.png
对比:元素移动和没有移动前后迭代器指向的地址

  1. 对string使用swap会允许迭代器、引用、指针失效
    !不是强制失效,GCC下仍然可以使用交换后的迭代器,MSVC下报错

image.pngimage.png

练习

9.14

image.png

容器大小操作

image.png
不过单向链表不支持size操作

关系运算符

  • 每种容器都支持==和!=
  • 除无序关联容器外都支持大小比较
  • 相同类型容器才可比较
    原则类似string比较

image.png
其实是使用元素的比较实现的;
如果元素没有定义比较运算则不能比较,如自定义类没有重载比较运算

练习

9.15

image.png

9.16

image.png
看错题了,题中要实现是否相等,我实现了个比大小。。

9.3 顺序容器操作