C++_标志库特殊设施
标准库特殊设施
总览
这一部分常见的标准库“特殊设施”包括:
tuple:把多个不同类型的值打包成一个对象bitset:按位存储和操作固定大小的二进制位集合- 正则表达式:进行字符串模式匹配
- 随机数库:生成随机数与随机分布
- IO 其他功能:格式控制、未格式化 IO、随机访问
可以把它们理解为:
不是容器/算法主线,但非常常用的标准库工具
tuple 类型
什么是 tuple
tuple 是一个固定大小、可包含不同类型元素的对象。
它和 pair 很像,但比 pair 更一般:
pair只能放 2 个值tuple可以放任意多个值
例如:
1 | tuple<int, string, double> t(1, "Tom", 95.5); |
头文件
1 |
基本定义
1 | tuple<int, string, double> t1; |
也可用 make_tuple 创建:
1 | auto t3 = make_tuple(1, "Bob", 90.0); |
make_tuple 会自动推断类型。
访问元素:get
tuple 里的元素不能像数组那样用下标访问,
而是用:
1 | get<下标>(对象) |
例如:
1 | cout << get<0>(t3) << endl; |
注意:
下标必须是编译期常量
所以不能写:
1 | int i = 1; |
获取元素个数:tuple_size
1 | tuple<int, string, double> t; |
获取某个元素类型:tuple_element
1 | tuple<int, string, double> t; |
tuple 的比较
如果两个 tuple 类型相同,且其中元素类型都支持比较,则可以比较:
1 | tuple<int, int> a(1, 2), b(1, 3); |
比较规则是:
按字典序逐个元素比较
先比第 0 个,若相等再比第 1 个,依此类推。
tuple 的常见用途
函数返回多个值
1 | tuple<string, int, double> get_student() { |
把一组异构数据打包
配合泛型编程使用
C++17 补充:结构化绑定
如果课程允许写到 C++17,可以记这个很实用:
1 | auto [name, age, score] = get_student(); |
它能直接把 tuple 拆开。
如果考试主要按 C++11/14,可知道即可。
小结
tuple= 可存多个不同类型元素的固定大小对象,常用make_tuple创建,用get<>()访问。
bitset 类型
什么是 bitset
bitset 表示:
固定大小的位序列
可以把它理解成“长度固定的二进制集合”。
例如:
1 | bitset<8> b; |
表示一个 8 位的二进制集合。
头文件
1 |
定义与初始化
默认初始化
1 | bitset<8> b1; // 00000000 |
用整数初始化
1 | bitset<8> b2(13); // 00001101 |
用字符串初始化
1 | bitset<8> b3(string("1011")); // 00001011 |
也可以指定从字符串的哪一段构造。
常用操作
测试某一位:test
1 | bitset<8> b(13); // 00001101 |
设置某一位:set
1 | b.set(1); // 把第 1 位设为 1 |
复位某一位:reset
1 | b.reset(0); // 第 0 位设为 0 |
翻转:flip
1 | b.flip(0); // 翻转某一位 |
统计 1 的个数:count
1 | cout << b.count() << endl; |
判断是否有位为 1
1 | b.any(); // 是否至少有一个 1 |
获取长度:size
1 | cout << b.size() << endl; |
位运算
bitset 支持常见按位运算:
&|^~<<>>
例如:
1 | bitset<8> a(12); // 00001100 |
下标访问
1 | cout << b[0] << endl; |
但注意:
- 下标 0 通常表示最低位
- 和字符串中最左边字符的方向容易混
这是常见易错点。
转换
可以把 bitset 转成:
unsigned longunsigned long long- 字符串
例如:
1 | bitset<8> b(13); |
常见用途
- 二进制状态压缩
- 标志位管理
- 位运算题
- 模拟固定宽度二进制表示
复习小结
bitset<N>表示固定大小的二进制位集合,常用于位操作、状态表示、标志位管理。
正则表达式
C++ 正则表达式库定义在:
1 |
基本概念
正则表达式用来描述一个字符串模式,然后用它去做:
- 匹配
- 搜索
- 替换
- 提取子串
主要类型
复习时重点记这几个:
regex:表示一个正则表达式smatch:保存string匹配结果cmatch:保存 C 风格字符串匹配结果sregex_iterator:在字符串中迭代查找所有匹配项
创建正则对象
1 | regex r("[a-z]+"); |
表示匹配一个或多个小写字母。
三个常见函数
regex_match
表示:
整个字符串必须完全匹配
例如:
1 | regex r("[a-z]+"); |
因为 abc123 不是“整个字符串都由小写字母组成”。
regex_search
表示:
字符串中只要有一部分匹配即可
1 | cout << regex_search("abc123", r) << endl; // true |
因为里面有 abc 匹配。
regex_replace
表示:
把匹配到的部分替换掉
1 | string s = "abc 123 def 456"; |
输出:
1 | abc |
匹配结果对象
smatch
如果操作 string,通常用:
1 | smatch m; |
然后:
1 | if (regex_search(s, m, r)) { |
子表达式
圆括号 () 表示分组。m[^0] 是整体匹配,m[^1]、m[^2]… 是各组匹配结果。
这是非常常考的点。
常见正则符号速记
复习时不需要背太多,先记最基本的:
| 表达式 | 含义 |
|---|---|
. |
任意单个字符 |
* |
前一个字符出现 0 次或多次 |
+ |
前一个字符出现 1 次或多次 |
? |
前一个字符出现 0 次或 1 次 |
[abc] |
a/b/c 中任一个 |
[a-z] |
任一小写字母 |
[^a-z] |
非小写字母 |
\\d |
数字 |
\\w |
单词字符 |
\\s |
空白字符 |
^ |
行首 |
$ |
行尾 |
() |
分组 |
注意字符串中的转义
在 C++ 字符串里写正则时,经常要写双反斜杠:
1 | regex r("\\d+"); |
因为:
- 正则里想写
\d - C++ 字符串本身又要转义
\
所以要写成 "\\d+"
这是最常见的坑之一。
原始字符串字面值
为了避免太多转义,也可写成:
1 | regex r(R"(\d+)"); |
这往往更清晰。
小结
regex_match要求整个串匹配,regex_search只要求找到一部分匹配,regex_replace用于替换。
随机数
随机数库定义在:
1 |
这一部分非常容易混,复习时要抓住核心模型:
随机数生成 = 随机数引擎 + 分布对象
为什么不用 rand()
C++11 以后更推荐 <random>,因为它:
- 质量更好
- 更灵活
- 分布更丰富
- 接口更规范
所以现代 C++ 中应优先使用 <random>。
随机数引擎
随机数引擎负责:
生成原始随机序列
例如:
1 | default_random_engine e; |
常见引擎:
default_random_enginemt19937mt19937_64
其中 mt19937 很常用。
直接调用引擎
1 | default_random_engine e; |
每次调用 e() 产生一个伪随机数。
固定种子
如果给相同种子,产生的序列相同:
1 | default_random_engine e1(42); |
这样 e1 和 e2 生成的随机序列一致。
使用时间作为种子
常见写法:
1 | default_random_engine e(time(0)); |
这样每次程序运行的种子通常不同。
分布对象
引擎给出的是“原始随机数”,
分布对象负责把这些随机数映射为某种分布。
常见的有:
uniform_int_distributionuniform_real_distributionnormal_distributionbernoulli_distribution
均匀整数分布
1 | default_random_engine e; |
注意:
u(e)才是最终随机数u是分布,e是引擎
均匀实数分布
1 | uniform_real_distribution<double> u(0.0, 1.0); |
产生 [0.0, 1.0) 范围内的随机实数。
正态分布
1 | normal_distribution<double> n(4.0, 1.5); |
表示均值 4.0、标准差 1.5 的正态分布。
理解
随机数库分成两层:
引擎
负责“产生随机序列”
分布
负责“决定这些随机数长什么样”
所以:
引擎 + 分布 = 真正常用的随机数生成方式
常见写法模板
产生 [a, b] 的随机整数
1 | mt19937 gen(time(0)); |
产生 [0,1) 的随机实数
1 | mt19937 gen(time(0)); |
IO 库的其他功能
这一部分主要分三类:
- 格式控制
- 未格式化 IO
- 随机访问
格式控制
C++ IO 流支持控制输出/输入格式。
头文件常见有:
1 |
常见格式控制项
控制布尔值输出
1 | cout << true << " " << false << endl; // 1 0 |
控制进制
1 | cout << dec << 20 << endl; // 十进制 |
还可配合:
1 | cout << showbase << hex << 20 << endl; // 0x14 |
控制浮点数形式
1 | cout << fixed << 3.1415926 << endl; |
fixed:定点表示scientific:科学计数法
控制精度
1 | cout << setprecision(4) << 3.1415926 << endl; |
这个很常用。
控制宽度和填充
1 | cout << setw(10) << 123 << endl; |
输出宽度不足时用指定字符填充。
对齐方式
1 | cout << left << setw(10) << 123 << endl; |
常见操纵符
来自 <iostream> 的:
boolalpha / noboolalphashowbase / noshowbaseshowpoint / noshowpointshowpos / noshowposuppercase / nouppercasehex / dec / octleft / right / internalfixed / scientificendl / ends / flush
来自 <iomanip> 的:
setwsetprecisionsetfillsetbasesetiosflagsresetiosflags
小结
格式控制就是通过流操纵符改变输出/输入的显示方式。
未格式化 IO
未格式化 IO 指不按通常的“按类型解析”方式,而是直接按字符/字节操作流。
常用在:
- 逐字符读取
- 读取原始数据
- 跳过格式解析
常见函数
get()
读取一个字符:
1 | char ch; |
也可:
1 | int c = cin.get(); |
getline()
读取一整行:
1 | string line; |
注意这是非常常用的行读取方式。
put()
输出一个字符:
1 | cout.put('A'); |
read() 和 write()
按字节块读写,常用于二进制 IO:
1 | char buf[100]; |
gcount()
返回上一次未格式化输入操作读取的字符数。
ignore()
跳过若干字符:
1 | cin.ignore(100, '\n'); |
常用于清理输入缓冲区。
peek()
查看下一个字符但不提取:
1 | int c = cin.peek(); |
unget() / putback()
把字符放回输入流。
格式化输入与未格式化输入的区别
例如:
1 | int x; |
这是格式化输入:会跳过空白并按整数解析。
而:
1 | char ch; |
是未格式化输入:直接读字符,连空格和换行也可能读进来。
随机访问文件
随机访问主要针对文件流。
头文件:
1 |
两组位置指针
文件流通常有两个位置:
- get 位置:读位置
- put 位置:写位置
tellg / tellp
返回当前读/写位置:
1 | ifstream in("file.txt"); |
seekg / seekp
移动读/写位置:
1 | in.seekg(0); // 回到文件开头 |
常见形式:
1 | seekg(pos) |
其中 dir 可以是:
ios::begios::curios::end
典型用途
- 跳到文件某个位置重新读取
- 获取文件长度
- 覆盖某个位置的数据
- 实现简单二进制文件结构操作
易错点总结
tuple 用 get<>() 访问,不是 []
get<>() 的下标必须是编译期常量
bitset 的大小是编译期固定的
bitset<8> 里的 8 不是运行时变量。
bitset 下标方向容易混
通常 b[^0] 是最低位。
正则表达式里常有双重转义
1 | "\\d+" |
不要忘。
regex_match 是整串匹配,regex_search 是局部匹配
这个极易考。
随机数不是只靠引擎,还要配合分布
1 | dist(engine) |
才是常用写法。
rand() 不如 <random> 推荐
现代 C++ 优先用随机数库。
getline 和 >> 混用时要小心换行残留
必要时配合:
1 | cin.ignore(...) |
随机访问主要用于文件流,不是普通 cin/cout
结论速记
tuple
多个不同类型值的固定大小组合
bitset
固定长度位集合,支持按位操作
正则表达式
用模式匹配字符串,
match看整串,search看部分
随机数
引擎产生随机序列,分布决定随机数形式
IO 其他功能
包括格式控制、未格式化 IO、文件随机访问
总结
tuple负责异构数据打包,bitset负责位集合操作,正则表达式负责模式匹配,随机数库负责“引擎 + 分布”的随机生成,IO 扩展功能负责格式控制、原始读写和文件随机访问。




