C++Primer5th 第十七章 标准库特殊设施

    技术2023-04-07  89

    第十七章 标准库特殊设施 17.1 tuple类型 17.1.1 定义和初始化tuple 访问tuple的成员关系和相等运算符 17.1.2 使用tuple返回多个值 17.2 bitset类型 17.2.1 定义和初始化bitset 用unsigned值初始化bitset从一个string初始化bitset 17.2.2 bitset操作 提取bitset的值bitset的IO运算符 17.3 正则表达式 17.3.1 使用正则表达式库 指定regex对象的选项 17.3.2 匹配与Regex迭代器类型17.3.3 使用子表达式17.3.4 使用regex_replace 17.4 随机数 17.4.1 随机数引擎和分布 分布类型和引擎设置随机数发生器的种子 17.4.2 其他随机数分布 生成随机实数使用分布的默认结果类型生成非均匀分布的随机数bernoulli_distribution类是一个普通类,不是模板类 17.5 IO库再探 17.5.1 格式化输入与输出 很多操纵符改变格式状态控制布尔值的格式指定整型值的进制在输出中指定进制控制浮点数的格式输出补白控制输入格式 17.5.2 未格式化的输入/输出操作 单字节操作将字符放回输入流从输入操作返回int值多字节操作确定读取了多少个字符 17.5.3 流随机访问 seek和tell函数只有一个标记重定位标记访问标记读写同一个文件

    第十七章 标准库特殊设施

    17.1 tuple类型

    定义在tuple头文件中tuple是类似pair的模板一个tuple可以有任意数量的成员,每个确定的tuple类型的成员数目是固定的,但一个tuple类型的成员数目可以与另一个tuple类型不同.

    17.1.1 定义和初始化tuple

    当我们定义一个tuple时候,需要指出每个成员的类型

    tuple <size_t, size_t, size_t> threeD; //默认值初始化为0

    tuple 的构造函数时explicit的,因此我们必须使用直接初始化语法

    //生成tuple对象 auto i = make_tuple("string", 3, 2.3);

    访问tuple的成员

    不能像pair一样用first,second等,因为tuple类型的成员数目是没有限制的,使用 get 的标准库函数模板

    传递给get一个tuple对象,返回指定成员的引用

    //尖括号中的值必须是常量表达式,返回成员的引用, 0是第一个成员,1是第二个,依次类推 auto book = get<0>(i); //返回成员数量 auto s = tuple_size<i>::value; //使用成员的类型 这里面tuple_element<1, i>::type代表int类型 tuple_element<1, i>::type cnt = get<1>(i);

    关系和相等运算符

    只有两个tuple具有相等数量的成员时,才可以进行比较,两个成员使用==或<等运算符必须是合法的

    17.1.2 使用tuple返回多个值

    tuple常见的用途就是一个函数返回多个值



    17.2 bitset类型

    用于位运算,在头文件bitset中

    17.2.1 定义和初始化bitset

    bitset类是一个类模板,指定大小,大小需要时常量表达式

    bitset<32> bitvec(1U);

    bitset中的二进制位是未命名的,我们通过位置来访问他们,二进制位的位置是从0开始编号的,编号从0开始的二进制被称为低位,编号到最大值的二进制位称为高位

    用unsigned值初始化bitset

    当我们使用一个整型值来初始化bitset时,此值将被转换为unsigned long long类型并被当作位模式来处理,bitset中的二进制位是此模式的一个副本

    如果bitset大小大于一个unsigned long long , 则剩余高位置为0如果bitset大小小于一个unsigned long long , 则超出部分被丢弃

    从一个string初始化bitset

    可以从一个string或一个字符数组指针来初始化bitset

    字符串中下标最小的字符对应高位注意string下标标号从左往右递增,而bitset是从右往左递增

    17.2.2 bitset操作

    bit.size()是一个常量表达式,可以用在常量表达式的地方.

    我的理解:因为bitset指定大小的时候也需要传入一个常量表达式,因此在编译时候就知道了size,因此其也是个常量表达式下标运算符对const属性进行了重载 const版本的下标运算符在指定位 置位 时返回true,否则返回false非const版本返回bitset定义的一个特殊类型,允许操纵指定位的值

    提取bitset的值

    to_ulong和to_ullong操作返回一个值,保存了与bitset对象相同的位模式,只有bitset的大小小于ul和ull两种类型的大小的时候才能使用这个操作,否则会抛出异常

    bitset的IO运算符

    输入运算符从一个输入流读取字符,保存到临时的string对象中,直到读取字符数达到bitset大小或者是遇到不是1或0的字符,或是遇到文件尾或输入错误时候才停止, 之后用string对象来初始化bitset.

    17.3 正则表达式

    正则表达式是一种描述字符序列的方法,是一种极其强大的计算工具.

    正则表达式库(RE库),定义在头文件regex中.

    17.3.1 使用正则表达式库

    看完整章,主要用在了字符串的匹配工作/格式化工作

    指定regex对象的选项

    regex r(re,f)//re是一个正则表达式,可以用string,迭代器等多种方式,f是一个标志

    使用RE库的类型必须与输入序列的类型匹配

    17.3.2 匹配与Regex迭代器类型

    sregex_iterator regex的迭代器是一种迭代器适配器,被绑定到一个输入序列和一个regex对象.

    17.3.3 使用子表达式

    正则表达式语法通常用括号表示子表达式

    可单独访问每个子表达式,(序号),0表示整个表达式,1 表示第一个子表达式,一次类推

    17.3.4 使用regex_replace

    实现产找到给定的序列并替换为我们希望的另一个序列

    可以设置控制配合和格式的标志

    17.4 随机数

    定义在头文件random中的随机数库通过一组协作的类来工作:

    随机数引擎类: 生成随机unsigned整数序列随机数分布类: 使用引擎返回服从特定概率分布的随机数

    C++程序不应该使用rand(C库函数),而是使用default_random_engine类和恰当的分布类对象

    17.4.1 随机数引擎和分布

    标准库定义了多个随机数引擎类,区别是性能和随机性质量不同. 每个编译器会指定其中一个作为default_random_engine类型

    随机数引擎的输出是不能够直接使用的,因为其范围通常与我们的需求不符

    分布类型和引擎

    分布类型定义了一个调用运算符,他接受一个随机数引擎作为参数,分布对象使用它的引擎参数生成随机数,并将其映射到指定分布.

    我们所说的随机数发生器,其实指分布对象和引擎对象的组合

    一个给定的随机数发生器一直会生成相同的随机数序列.一个函数如果定义了局部的随机数发生器,应该将其(包括引擎和分布对象)定义为static的.否则,每次调用函数都会生成相同的序列.

    设置随机数发生器的种子

    随机数发生器会生成相同的随机数序列这一特性在调试中很有用. 一旦我们的程序调试完毕,我们通常希望每次运行程序都会生成不同的随即结果. 可以通过提供一个 种子 来达到这个目的.

    选取好的种子十分困呐,比较常用的方法是调用系统函数time,定义在ctime头文件中, time返回以秒计的时间,因此这种方式只适合生成种子的间隔位秒级或者更长的应用.

    可以在初始化时候设置种子,也可以调用引擎的seed成员

    17.4.2 其他随机数分布

    生成随机实数

    程序常需要一个随机浮点数的源,特别是经常需要0到1之间的随机数

    新标库中,很容易获得随机浮点数,定义一个uniform_real_distribution类型对象

    uniform_real_distribution<double> u(0,1);

    使用分布的默认结果类型

    每个分布模板都有一个默认模板实参,使用默认随机数类型是在模板名之后使用尖括号

    uniform_real_distribution<> u(0,1); //使用默认double类型

    生成非均匀分布的随机数

    新标准库定义了20种分布类型.

    正态分布normal_distribution<>n(u,sigma);均值和标准差

    bernoulli_distribution类是一个普通类,不是模板类

    此分布返回一个bool值,返回bool概率是一个常数,默认0.5由于引擎返回相同的随机数序列,通常应该在循环外声明和定义引擎对象和分布对象

    17.5 IO库再探

    17.5.1 格式化输入与输出

    标准库定义了一组操纵符来修改流的格式状态,一个操纵符是一个函数或是一个对象,会影响流的状态,可以用作输入输出运算符的运算对象。

    很多操纵符改变格式状态

    操纵符用于两大类输出控制:控制数值的输出形式以及控制补白的数量和位置。大多数改变格式状态的操纵符都是设置/复原成对的。

    当操纵符改变流格式的状态时,通常对之后的IO都生效,因此在不需要特殊格式的时候尽快恢复到默认状态。

    控制布尔值的格式

    使用boolalpha 使得false,true输出打印而不是0 和 1 取消使用noboolalpha

    指定整型值的进制

    hex, oct, dec 分别表示十六进制,八进制,十进制

    在输出中指定进制

    使用showbase显式进制 , noshowbase不显示

    前导0x十六进制前导0八进制无前导十进制

    uppercase输出大写,nouppercase恢复

    控制浮点数的格式

    多高精度打印浮点值,就是有多少个数字(默认六位数字精度打印)打印十六进制、定点十进制还是科学计数法形式 (标准库会选择可读性好的)对于没有小数部分的浮点值是否打印小数点 (默认不打印)

    1.指定打印精度

    默认情况控制打印数字的总数,按照舍入规则。

    IO对象的成员precision和setprecision操纵符

    setprecision操纵符和其他接收参数的操纵符定义在头文件iomanip中

    cout.precision() 和 cout.precision(int) 是重载的,一个返回当前精度,一个设置指定的精度返回当前精度

    2.指定浮点数记数法

    除非需要控制浮点数表示形式,否则最好有标准库选择记数法

    scientific使用科学计数法;fixed定点十进制;hexfloat是用十六进制格式;defaultfloat恢复默认状态 打印小数点 showpoint操纵符强制打印小数点

    noshowpoint恢复默认格式

    输出补白

    按列打印时候要控制数据来良好展示

    setw指定下一个数字或字符串值的最小空间,不改变输出流的内部状态,只决定下一个输出的大小.left左对齐right 右对齐 默认是右对齐internal 左对齐符号,右对齐值,中间空间空格填满setfill 使用一个默认字符代替空格补白

    控制输入格式

    默认情况,输入运算符会忽略空白符(空格\制表\换行\换纸\回车)

    使用noskipws会令输入运算符读取空白符而不是跳过,skipws恢复默认行为

    17.5.2 未格式化的输入/输出操作

    标准库支持未格式化IO,允许我们将一个流当作一个无解释的字节序列来处理

    单字节操作

    is.get() is.get(ch) os.put() 等可以每次一个字节地处理流

    将字符放回输入流

    有时候需要读取一个字符才能知道还未准备好处理它,希望将字符放回流中.有三种方法:

    peek 返回输入流中下一个字符的副本, 不会将它从流中删除unget 使得输入流向后移动,从而最后读取的值又回到流中putback(ch) 退回从路中读取的最后一个值,需要参数,参数值是读取的最后一个值

    从输入操作返回int值

    peek和无参get() 都以int类型返回一个字符,因为这样可以返回文件尾标记EOF

    多字节操作

    一次处理大块数据

    get和getline参数相同时行为类似,区别是处理分隔符的方式,get将分隔符留在iostream中作为下一个字符,getline读取并丢弃分隔符

    确定读取了多少个字符

    调用gcount来确定最后一个未格式化输入操作读取了多少个字符

    17.5.3 流随机访问

    stream和ostream不支持流随机访问, 以下内容只适用于fstream,sstream

    各种流类型通常都支持对流中数据的随机访问,可以重定位流,使之跳过一些数据,首先读取最后一行,然后读取第一行.

    标准库提供了seek定位和tell当前位置的函数对

    seek和tell函数

    g版本和p版本,g是读取数据,p是写入数据

    只有一个标记

    一个流中只有单一的标记,p和g都使用这一个标记,因此在读写操作切换时候必须进行seek操作重定位标记

    重定位标记

    seek两个版本,一个移动到绝对位置,另一个移动到偏移位置

    访问标记

    tellp和tellg返回一个pos_type值,表示流当前位置

    读写同一个文件

    注意每次更改标记以及返回标记

    Processed: 0.011, SQL: 9