标准库特殊设施
tuple、bitset、正则表达式以及随机数,附加的一些IO库功能:格式控制、未格式化IO和随机访问
1.tuple类型:
- 类似于pair的模板,定义在tuple头文件中
tuple支持的操作
tuple<T1,T2,.....Tn> t; t是一个tuple,成员时为n,第i个成员的类型为Ti,所有成员都进行值初始化
tuple<T1,T2,...,Tn> t(v1,v2....vn) 每个成员用对应的初始值vi进行初始化。此构造函数是explicit的
make_tuple(v1,v2,....vn) 返回一个用给定初始值初始化的tuple。tuple的类型由初始值推断而来
t1 relop t2 使用字典序进行比较(必须具有相同数量的成员)
get<i> (t) 返回t的第i个数据成员的引用
tuple_size<tupleType>::value 返回给定tuple类型中成员的数量
tuple_element<i,tupleType>::type 表示给定tuple类型中指定成员的类型
定义和初始化tuple:
1.使用直接初始化:
tuple<size_t, size_t, size_t> threeD{1,2,3};
2.使用make_tuple函数生成tuple:
auto item = make_tuple("0-999-78345-x", 3, 20.00);
3.访问tuple成员:
auto book = get<0>(item); //返回item的第一个成员
4.使用两个辅助模板:
typedef decltype(item) trans; //trans是item的类型 //返回trans类型对象中成员的数量 size_t sz = tuple_size<trans>::value; //cnt的类型与item中的第二个成员相同 tuple_element<1, trans>::type cnt = get<1>(item);
- tuple的一个常见用途是从一个函数返回多个值
2.bitset类型:
- 定义在头文件bitset中,作用:能够处理超过最长整型类型大小的位集合
- bitset类是一个类模板,它类似array类,具有固定的大小,且大小必须是一个常量表达式
初始化bitset的方法
bitset<n> b; b有n位,每一位均为0.构造函数是一个constexper
bitset<n> b(u); b是unsigned long long值u的低n位的拷贝
//如果n大于unsigned long long的大小,则b中超过unsigned long long的高位被置为0 //bitvec1比初始值小;初始值中的高位被丢弃 bitset<13> bitvec1(0xbeef); //二进制序列为1111011101111 //bitvec2比初始值大;它的高位被置为0 bitset<20> bitvec2(0xbeef); //二进制序列00001011111011101111
bitset<n> b(s, pos, m, zero, one); //b是string s从位置pos开始m个字符的拷贝,s只能包含字符zero或one,如果包含其他字符,构造函数抛出invalid_argument异常
//当我们使用字符串表示数时,字符串中下标最小的字符对应高位 bitset<32> bitvec4("1100"); //2、3两位为1,剩余两位为0 string str("1111111000000011001101"); bitset<32> bitvec5(str, 5,4); //从str[5]开始的四个二进制位 bitset<32> bitvec6(str, str.size()-4); //使用最后四个字符
bieset<n> b(cp, pos, m, zero, one); //cp指向字符数组
bitset操作
置位即将位置为1
b.any() b中是否存在置位的二进制位
b.all() b中所有位都置位了吗
b.none() b中不存在置位的二进制位吗
b.count() b中置位的位数
b.size() 一个constexpr函数,返回b中的位数
b.test(pos) 若pos位是置位的,返回true,否则返回false
b.set(pos,v) 将位置pos处的位设置为bool值v,v默认为true,未有实参则将所有位置位
b.set()
b.reset(pos) 将位置pos处的位复位或将b中所有位复位
b.reset()
b.flip(pos) 改变位置pos处的位的状态或改变b中每一位的状态
b.flip()
b[pos] 访问b中位置pos处的位
b.to_ulong() 返回一个unsigned long或一个unsigned long long值,其位模式与b相同
b.to_ullong()
b.to_string(zero, one) 返回一个string,表示b中的位模式
3.正则表达式:
- 是一种描述字符序列的方法,C++正则表达式库(RE库),定义在头文件regex中
正则表达式库组件
regex 表示有一个正则表达式的类
regex_match 将一个字符序列与正则表达式匹配
regex_search 寻找第一个与正则表达式匹配的子序列
regex_replace 使用给定格式替换一个正则表达式
sregex_iterator 迭代器适配器,调用regex_search来遍历一个string中所有匹配的子串
smatch 容器类,保存在string中搜索的结果
ssub_match string中匹配的子表达式的结果
- 使用正则表达式库:
//例
string pattern("[^c]ei"); //查找不在字符c之后的字符串ei
pattern = "[[:alpha:]]*" + pattern + "[[:alpha:]]*";
regex r(pattern); //构造一个用于查找模式的regex
smatch results; //定义一个对象保存结果
//定义一个string保存与模式匹配和不匹配的文本
string test_str = "receipt friend theif receive";
//用r在test_str中查找与pattern匹配的子串
if (regex_search(test_str, results, r)) //有匹配子串
cout << results.str() << endl; //打印匹配单词
regex和(wregex)选项
regex r(re) re表示一个正则表达式 定义regex时指定的标志
regex r(re, f) icase 在匹配过程中忽略大小写
r1 = re 将r1中的正则表达式替换为re nosubs 不保存匹配的子表达式
r1.assign(re, f) 与使用赋值运算符效果相同 optimize 执行速度优于构造速度
r.mark_count() r中子表达式的数目
r.flags() 返回r的标志集
- 一个正则表达式的语法是否正确是在运行时解析的;如果我们编写的正则表达式存在错误,则在运行时标准库会抛出一个类型为regex_error的异常
- sregex_iterator操作:
sregex_iterator it(b, e, r); //一个sregex_iterator,遍历迭代器b和e表示的string,调用sregex_search(b, e, r)将it定位到输入中第一个匹配的位置
smatch操作
m.ready() 如果已经通过regex_search或regex_match设置了m,则返回true
m.size() 匹配失败则返回0;成功返回匹配的正则表达式中子表达式的数目
m.empty() 若m.size()为0,则返回true
m.prefix() 表示当前匹配之前的序列
m.suffix() 表示当前匹配之后的序列
m.format()
m.length(n) 第n个匹配的子表达式的大小
m.position(n) 第n个子表达式距序列开始的距离
m.str(n) 第n个子表达式匹配的string
m[n] 对应第n个子表达式的ssub_match对象
m.begin(),m.end()
m.cbegin(),m.cend()
子匹配操作
matched 指出是否匹配
first 指向序列首元素和尾后位置的迭代器
second
length() 匹配的大小,如果matched为false,则返回0
str() 返回一个包含输入中匹配部分的string
s == ssub 将ssub_match对象转化为string对象s
- 使用regex_replace
m.format(dest, fmt. mft) //使用格式字符串fmt生成格式化输出
m.format(fmt, mft)
regex_replace(dest, seq, r, fmt, mft) //遍历seq,用regex_search查找与regex对象r匹配的子串,使用格式字符串fmt生成格式化输出
regex_replace(seq, r, fmt, mft)
//mft为匹配标志,使用时必须在名字前加上两个命名空间的限定符
using std::regex_constants::format_no_copy;
4.随机数:
- 定义在头文件random中的随机数库通过一组协作的类来解决生成随机数的问题:随机数引擎类和随机数分布类
随机数库的组成
引擎 类型,生成随机unsigned整数序列
分布 类型,使用引擎返回服从特定概率分布的随机数
- c++程序应使用default_random_engine类和适当的分布类对象
default_random_engine e; //生成随机无符号数
for (size_t i = 0; i < 10; ++i)
{
//e()调用对象来生成下一个随机数
cout << e() << " ";
}
随机数引擎操作
engine e; 使用引擎类型默认的种子
engine e(s); 使用整型值s作为种子
e.seed(s) 使用s重置引擎状态
e.min() 此引擎可生成的最小值和最大值
e.max()
engine::result_type 此引擎生成的unsigned整数类型
e.discard(u) 将引擎推动u步
- 一个给定的(分布对象和引擎对象的结合)随机数发生器 一直会生成相同的随机数。一个函数如果定义了局部的随机数发生器应该将其定义为static的
- uniform_real_distribution生成随机的浮点数;uniform_int_distribution生成随即的整数
- 还有其他的一些分布类型,可以生成各种随机数,在这里就不一一列举了。。。
5.额外IO库特性:
- 特殊的IO库特性:格式控制、未格式化IO和随机访问
格式控制:
- 标准库定义了一组操纵符来修改流的格式状态
- 当操纵符改变流的格式状态时,通常改变后的状态对所有后续IO都生效
- 通常在不需要特殊格式时尽快将流恢复到默认状态
- 操纵符setprecision和其他接受参数的操纵符都定义在头文件iomanip中
未格式化IO:
- 标准库提供了一组低层操作,支持未格式化IO,这些操作允许我们将一个流当作一个无解释的字节序列来处理
- 单字节操作:每次一个字节地处理流,它们会读取而不是忽略空白符
- 多字节操作:一次处理大块数据
- 一般情况下,主张使用标准库提供的高层抽象
流随机访问:
- 标准库提供了一堆函数,来定位(seek)到流中给定的位置,以及告诉(tell)我们当前位置
- 两对seek和tell函数,一对用于输入流,另一对用于输出流。差别在于名字地后缀是g还是p,g版本表示我们正在获得数据,p版本表示我们正在放置数据
- 由于只有单一的标记,因此只要我们在读写操作间切换,就必须进行seek操作来重定位标记