Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >第 17 章 标准库特殊设施

第 17 章 标准库特殊设施

作者头像
用户1653704
发布于 2018-06-07 06:21:17
发布于 2018-06-07 06:21:17
1.1K00
代码可运行
举报
运行总次数:0
代码可运行

第 17 章 标准库特殊设施

标签: C++Primer 学习记录 tuple 正则表达式 随机数 IO库



17.1 tuple类型

  1. 当我们希望将一些数据组合成单一对象,但又不想麻烦地定义一个新数据结构来表示这些数据时,可以使用 tuple类型。与 pair类似,但 tuple可以有任意数量的成员。它的一个常见用途就是从一个函数返回多个值
  2. tuple的默认构造函数会对每个成员进行值初始化,也可以提供初始值。不过提供初始值的构造函数是 explicit的,因此必须使用直接初始化语法。 tuple<size_t, size_t, size_t> threeD; // 三个成员都设置为 0 tuple<size_t, size_t, size_t> threeD = {1, 2, 3}; // 错误 tuple<size_t, size_t, size_t> threeD{1, 2, 3}; // 正确 // 表示书店交易记录的 tuple,包含:ISBN、数量和每本书的价格 auot item = make_tuple("0-999-78", 3, 20.00);
  3. 要访问一个 tuple的成员,使用 get<i>(t)函数模板。其中,i的值必须是一个整型常量表达式,从 0开始计数,返回指定成员的引用。 auto book = get<0>(item); // 返回 item的第一个成员 get<0>(item) *= 0.8; // 修改书的单价
  4. 借助辅助类模板 tuple_sizetuple_element,可以查询 tuple成员的数量和类型。不过使用这两个类,必须知道 tuple对象的类型,这可以通过 decltype很简单地得到。 typedef decltype(item) trans; // 返回 trans类型对象中成员的数量 size_t sz = tuple_size<trans>::value; // 返回 3 // cnt的类型与 item中第二个成员相同,是一个 int tuple_element<1, trans>::type cnt = get<1>(item);
  5. 只有两个 tuple具有相同数量的成员,且每对成员使用 ==<是合法时,才能比较两个 tuple。另外,由于 tuple定义了 <和 ==运算符,可以将 tuple序列传递给算法,并且可以在无序容器中将 tuple作为关键字类型。

17.2 bitset类型

  1. bitset类,可以方便地将整型运算对象当作二进制位集合处理,并且能够处理超过最长整型类型大小的位集合。可以用以下几种方式进行值初始化。
    • 使用整型值初始化 bitset时,会将此值转换为 unsigned long long类型并被当作位模式处理。

    // bitvec1比初始值小,初始值中的高位被丢弃 bitset<13> bitvec1(oxbeef); // 二进制位序列为 1111011101111 // bitvec2比初始值大,它的高位被置为 0 bitset<20> bitvec2(oxbeef); // 二进制位序列为 00001011111011101111 // 在 64位机器中,long long 0ULL是 64个 0比特,因此 ~0ULL是 64个 1 bitset<20> bitvec3(~0ULL); // 0~63位为 1,64~127位为 0

    • 使用字符串初始化 bitset时,下标最小的字符对应 bitset中的高位。

    bitset<32> bitvec4("1100"); // 2、3两位为 1,剩余位为 0

  2. bitset可以使用 to_ulong和 to_ullong返回位模式对应的整数值。另外,bitset还支持 <<>>运算符,对于输入运算符 <<,直到读取的字符数达到对应 bitset的大小时,或遇到不是 1或 0 的字符时,或是遇到文件尾或输入错误时,读取过程才停止。

17.3 正则表达式

  1. regex类,用一组描述语言来表示一个特定的模式。之后可以使用 regex_searchregex_match来验证给定的字符序列是否与此模式匹配。如果输入序列中一个子串与表达式匹配,则 regex_search函数返回 true。注意,该函数只要找到一个匹配子串就会停止查找。 // 非 c字母后接 ei string pattern("[^c]ei"); // 包含 pattern的整个单词 pattern = "[[:alpha:]]*" + pattern + "[[:alpha:]]*"; regex r(pattern, regex::icase); // 忽略大小写 smatch results; // 定义一个对象保存搜索结果 // 定义一个 string保存待查询的文本 string test_str = "receipt freind theif receive"; // 用 r在 test_str中查找与 pattern匹配的子串 if (regex_search(test_str, results, r)) cout << results.str() << endl;
  2. 在正则表达式语言中,字符点(.)通常匹配任意字符,可以在字符之前放置一个反斜线来去掉其特殊含义。另外,由于反斜线 “\”又是 C++中的特殊字符,所以在正则表达式的字符串中必须使用两个反斜线“\\”来去掉某些字符的特殊含义。
  3. 正则表达式是在运行时而非编译时编译的,而正则表达式的编译是一个非常慢的操作。所以在实际编程中,应该尽量避免创建很多不必要的 regex对象。如果要在循环中使用正则表达式,应该在循环外创建它,而不是在每步迭代时都编译它
  4. 正则表达式可以搜索多种类型的输入序列,输入可以是普通 char数据或 wchar_t数据,字符可以保存在标准库 string或 char数组中。RE为这些不同的输入序列类型都定义了对应的类型。重要的是使用的 RE库类型必须与输入序列类型匹配。
  1. sregex_iterator可以获得所有匹配的子串。将一个 sregex_iterator绑定到一个 string和一个 regex对象时,迭代器自动定位到给定 string中第一个匹配位置。解引用这个迭代器,则会得到一个 smatch对象。如果正则表达式中的模式包含一个或多个子表达式时,得到的 smatch对象中还会包含多个 ssmatch对象,表示与模式中每个子表达式的匹配信息
  2. 对于多个子表达式,使用括号来进行分组隔开。得到的匹配对象中,第一个子匹配位置为 0,表示整个模式对应的匹配,随后是每个子表达式对应的匹配
  3. regex_replace可以在输入序列中查找具有指定模式的字符串,并将其替换为指定格式的字符串。注意,只对输入序列中匹配的字符串进行替换,未匹配部分不做修改。另外,还可以通过改变匹配标志来控制匹配过程。比如 format_no_copy不输出输入序列中未匹配的部分,format_first_only只替换第一次出现的子表达式。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 将电话号码进行转换,只返回它替换的文本
string phone =
	"(\\()?(\\d{3})(\\))?([-. ]*)?(\\d{3})([-. ]*)?(\\d{4})";
regex r(phone);
string fmt{"$2.$5.$7"};
string number = "morgan (908) 555-1800";
// 实际输出 908.555.1800
cout << regex_replace(number, r, fmt, format_no_copy) << endl;
;

17.4 随机数

  1. 新标准出现之前,C和 C++都依赖于一个简单的 C库函数 rand来生成随机数。此函数生成均匀分布的伪随机整数,每个随机数的范围在 0和一个系统相关的最大值(至少为 32767)之间。但是当程序需要不同范围的随机数、随机浮点数或非均匀分布的数时,就需要程序员自己进行类型转换了,而这往往会引入非随机性
  2. C++中解决上述问题的方法是,使用随机数发生器,包括一个随机数引擎(生成 unsigned随机数序列)和分布对象(使用引擎返回服从特定概率分布的随机数)。注意,随机数发生器指的是 u(e),而不是 u(e())。第一种写法传递的是随机数引擎,而第二种写法传递的是生成的随机数。
  3. 一个给定的随机数发生器一直会生成相同的随机数序列。一个函数如果定义了局部的随机数发生器,应该将其(包括引擎和分布对象)定义为 static的。否则,每次函数调用都会生成相同的序列。 // 返回一个 vector,包含 100个均匀分布的随机数 vector<unsigned> good_randVec() { // 由于我们希望引擎和分布对象保持状态,因此应该将他们 // 定义为 static的,从而每次调用都生成新的数 static default_random_engine e; static uniform_int_distribution<unsigned> u(0, 9); vector<unsigned> ret; for (size_t i = 0; i <100; ++i) ret.push_back(u(e)); return ret; }
  4. 可以使用 time()函数来设置一个较为随机的种子,不过,由于其返回以秒记的时间,所以这种方式只适用于生成种子的间隔为秒级或更长的应用。
  5. 假如有一个程序需要随机浮点数,最常用但不正确的方法是用 rand()的结果除以 RAND_MAX。因为随机整数的精度通常低于随机浮点数,这会导致有一些浮点值永远都不会生成了。在新标准中可以使用 uniform_real_distribution

17.5 IO库再探

  1. 操纵符用于两大类输出控制:控制数据的输出形式以及控补白的数量和位置。大多数改变格式状态的操纵符,都是设置/复原成对的;一个操纵符用来将格式状态设置为一个新值,而另一个用来将其复原,恢复为正常的默认格式
  2. boolalpha控制布尔值的格式,默认情况下,true输出为 1,false输出为 0。使用 boolalpha后,按照字符形式输出。 bool bool_val = get_status(); // 输出字符形式的 true或 false后,再将内部状态恢复为默认格式 cout << boolalpha << bool_val << noboolalpha;
  3. 默认情况下,整型值的输入输出使用十进制。可以使用操纵符 hex、oct和 dec将其改为十六进制、八进制或是改回十进制。
  4. 默认情况下,打印数值时,没有可见的线索指出使用的是几进制。使用 showbase操纵符,可以在输出结果中显示进制。
  5. 可以控制浮点数输出的三个格式。
    • 以多高精度(多少个数字)打印浮点值。默认情况下,精度是指不包括小数点在内的数字的总数,并且浮点值按当前精度舍入而非直接截断,浮点值按六位数字精度打印
    • 数值是打印为十六进制、定点十进制还是科学计数法形式。非常大和非常小的值打印为科学计数法形式,其他值为定点十进制形式。使用 hexfloat、fixed、scientific后,精度值控制的是小数点后面的数字位数
    • 默认情况下,浮点值的小数部分为 0时,不显示小数点。showpoint操纵符强制打印小数点。
  6. 默认情况下,输入运算符会忽略空白符(空格符、制表符、换行符、换纸符和回车符),而使用 noskipws可以令输入运算符读取空白符,而不是跳过它们。
  7. 对于未格式化的单字节操作,要非常注意,将 get或 peek的返回值赋予一个 int而不是 char。乍看上去有些难以理解,这些函数返回 int值的原因是:可以返回文件尾标记。这些函数的返回值转换过程:字符->unsigned char->int。这样,字符集中的字符的返回值总是正值,而文件尾是用负值表示。这样就不会出现某个字符的返回值与文件标记重复的情形
  8. 对于多字节操作中的 get或 getline函数,两者的作用基本类似,但是 get将分隔符留作 istream中的下一个字符,而 getline则读取并丢弃分隔符。无论哪个函数都不会将分隔符保存在目的字符数组中。
  9. 由于 istream和 ostream类型通常不支持随机访问,流随机访问通常只适用于 fstream和 sstream类型。
  10. IO类型维护一个标记来确定下一个读写操作要在哪里进行,g版本表示正在“获得”(读取)数据,而 p版本表示正在“放置”(写入)数据。但是在一个流中,其实只维护单一的标记,因此只要我们在读写操作间切换,就必须进行 seek操作来重定位标记。相关的所有用法在下面代码中都会有所体现,下面代码会在文件的最后一行输出之前每一行的偏移量。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-01-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
第 17 章 标准库特殊设施
第 17 章 标准库特殊设施 标签: C++Primer 学习记录 tuple 正则表达式 随机数 IO库 ---- ---- 17.1 tuple类型 当我们希望将一些数据组合成单一对象,但又不想麻烦地定义一个新数据结构来表示这些数据时,可以使用 tuple类型。与 pair类似,但 tuple可以有任意数量的成员。它的一个常见用途就是从一个函数返回多个值。 tuple的默认构造函数会对每个成员进行值初始化,也可以提供初始值。不过提供初始值的构造函数是 explicit的,因此必须使用直接初始化语
用户1653704
2018/07/05
8010
【笔记】《C++Primer》—— 第17章:标准库特殊设施
这一章介绍了标准库中另外的一些之前没提到但也很实用的东西,读起来并不困难。其中17.1的tuple很适合快速组织数据,17.3的正则表达式可以快速处理字符串,17.4和17.5的随机数部分和IO流部分都是非常常用的特性,可以有效提高我们的开发效率。
ZifengHuang
2020/07/29
1.1K0
【笔记】《C++Primer》—— 第17章:标准库特殊设施
《C++Primer》第十七章 标准库特殊设施
tuple是类似pair的模板,每个pair的成员类型都不相同,但是每个pair恰好有两个成员。我们希望将一些数据组合成单一对象,但又不想麻烦地定义一个新数据结构来表示这些数据,这时候就可以用到tuple。
TOMOCAT
2020/12/03
7910
【笔记】《C++Primer》—— 第四部分:高级主题(完)
这篇是第四部分的总结,大致上就是回看了最后的3篇笔记并且重新翻翻书梳理了一下,内容基本都是从前面的章节复制来的。
ZifengHuang
2020/07/29
9480
【笔记】《C++Primer》—— 第四部分:高级主题(完)
标准库类型
一.标准string类型     string类型支持长度可变的字符串,C++标准库将负责管理与存储字符相关的内存,以及提供各种有用的操作。 1.1 string对象的定义和初始化     当没有明确
猿人谷
2018/01/17
9570
标准库类型
Python入门摘要
在 Python 中,所有标识符可以包括英文、数字以及下划线(_),但不能以数字开头。
辉哥
2020/09/10
1.7K0
Python入门摘要
Java基础——正则表达式与基础类应用
组捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:
阿Q说代码
2021/05/13
4340
Android 常用正则表达式
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/77800756
程序员徐公
2018/09/17
2.2K0
Java学习笔记--常用类及其常用方法、JDK5新特性、正则表达式介绍
object类String类其他类常用方法StringBuffer类JDK5新特性正则表达式Random类其他类常用方法Calendar类
用户7886150
2020/12/12
5590
java基础学习_常用类04_正则表达式、Math类、Random类、System类、BigInteger类、BigDecimal类、Date和DateFormat类、Calendar类_day14总
============================================================================= ======================
黑泽君
2019/02/25
6530
java基础学习_常用类04_正则表达式、Math类、Random类、System类、BigInteger类、BigDecimal类、Date和DateFormat类、Calendar类_day14总
Java基础笔记14
14.01_常见对象(正则表达式的概述和简单使用) A:正则表达式 是指一个用来描述或者匹配一系列符合某个语法规则的字符串的单个字符串。其实就是一种规则。有自己特殊的应用。 B:案例演示 需求:校验qq号码. 1:要求必须是5-15位数字 2:0不能开头 3:必须都是数字 a:非正则表达式实现 b:正则表达式实现 14.02_常见对象(字符类演示) A:字符类 [abc] a、b 或 c(简单类) [^abc] 任何字符,除了 a、b 或 c(否定) [a-zA-Z] a到 z 或 A到 Z,两
dreamkong
2018/06/21
3880
Js中RegExp对象
RegExp对象表示正则表达式,是由普通字符和特殊字符也叫元字符或限定符组成的文字模板,用于对字符串执行模式匹配。
WindRunnerMax
2020/09/07
10.8K0
阶段01Java基础day14常用对象03
声明:本文为原创,作者为 对弈,转载时请保留本声明及附带文章链接:http://www.duiyi.xyz/c%e5%ae%9e%e7%8e%b0%e9%9b%b7%e9%9c%86%e6%88%98%e6%9c%ba-21/
对弈
2019/09/04
4340
C++11常用新特性快速一览
在某种意义上来说,传统 C++ 会把 NULL、0 视为同一种东西,这取决于编译器如何定义 NULL,有些编译器会将 NULL 定义为 ((void*)0),有些则会直接将其定义为 0。
f_zyj
2019/05/27
2.6K0
Java中的正则表达式详解
为让大家对正则表达式底层实现有一个直观的映象,给大家举个实例 给你一段字符串(文本), 请找出所有四个数字连在一起的子串, 比如: 应该找到1998 1999 3443 9889 ===> 分析底层实现
timerring
2023/05/24
1K0
Java中的正则表达式详解
Python3 标准库概览
本文基于以下教程: http://www.runoob.com/python3/python3-stdlib.html
py3study
2020/01/03
7340
编码篇 - 正则表达式及其相关
有时我们需要在一大段长文本中过滤出我们需要的字段,或者检验该文本是否符合要求(该文本是否是邮箱,链接,电话号码或身份证),这时候就需要用到正则表达式了,当然我们也可以使用 NSPredicate,这不重要,重要的是表达式对于刷选和逻辑判断来说是十分方便的。
進无尽
2018/09/12
1.1K0
编码篇 - 正则表达式及其相关
一个正则表达式测试(只可输入中文、字母和数字)
  在项目中碰到了正则表达式的运用,正则还是非常强大的,不管什么编程语言,基本上都可以用到。之前在用java时特别是对用户名或密码使用正则非常爽,写脚本上用正则也非常爽,可是到了OC这却把我虐了一把,可能是对OC掌握的不够。这里就罗列了从网上找的很有用的资料,感谢大神们的贡献。 首先举一个例子: 匹配9-15个由字母/数字组成的字符串的正则表达式: NSString * regex = @"^[A-Za-z0-9]{9,15}$"; NSPredicate *pred = [NSPredi
猿人谷
2018/01/17
5.7K0
C++ 与正则表达式
正则表达式可以说是软件开发中最常用的功能之一。本文将以C++语言为例,介绍其中的正则表达式相关知识。
C语言与CPP编程
2021/10/09
2.9K0
python学习笔记(九)、模块
使用import 语句从外部导入模块信息,python提供了很大内置模块。当你导入模块时,你会发现其所在目录中,除源代码文件外,还新建了一个名为__pycache__的子目录(在较旧的Python版本中,是扩展名为.pyc 的文件)。这个目录包含处理后的文件,Python能够更高效地处理它们。以后再导入这个模块时,如果.py文件未发生变化,Python将导入处理后的文件,否则将重新生成处理后的文件。删除目录__pycache__不会有任何害处,因为必要时会自动创建它。
py3study
2020/01/17
9630
相关推荐
第 17 章 标准库特殊设施
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验