C/C++基础----标准库几个工具库tuple,bitset,正则表达式,随机数,IO库

时间:2022-10-09 15:52:47

tuple

tuple可以有任意多个成员
默认初始化,值初始化
构造函数是explicit,必须直接初始化
make_tuple(v1,v2,…,vn)
get<i> (t) 返回第i个数据成员的引用,t是左值则返回左值引用,右值则返回右值引用
tuple_size<tupleType>::value 表示成员的数量
tuple_element<i,tupleType>::type 表示给定tuple类型中指定成员的类型
为了使用关系运算符,每对成员使用运算符比较都是合法的。
如果tuple定义了<和==,则可以将tuple序列传递给算法,并且可以在无序容器中讲tuple作为关键字。

bitset

使得位运算的使用更加容易,并且能够处理超过最长整型类型大小的位集合。
具有固定的大小,定义时必须给出。编号从0开始是低位。
默认构造,constexpr,每一位均为0
直接构造,将unsigned long long值u的低n位拷贝,如果不足n位高位被置0
bitset<n> b(s, pos, m, zero, one) string s的pos位置开始拷贝m个字符,s只能包含zero和one。pos默认0,m默认string::npos,zero默认’0’
也可以从指向的字符数组中拷贝字符,如果未提供m则必须是c风格字符串。如果提供了m从pos开始至少有m个zero或one 字符串中下标最小的字符对应高位。
函数 操作
b.any() b中是否存在置位
b.all() 是否所有位都置位
b.none() 是否不存在置位的位
b.count() 位置的位数
b.size() constexpr 返回b中的位数
b.test(pos) 检查pos位置是否置位
b.set(pos,v) 将pos位置设置为v,v默认true
b.set() 所有位置位
b.reset(pos) 复位pos处
b.reset() 所有位复位
b.flip(pos) 改变pos处位的状态
b.flip() 改变所有位的状态
b[pos] 访问pos处的位;如果b是const,返回的是bool
b.to_ulong() 只能往大了转,否则抛出overflow_error
b.to_ullong()
b.to_string(zero,one) 返回一个string
os<<b
is>>b 当下一个不是1或0时,或已经读了size位时停止

正则表达式

  • regex 正则表达式类
regex_match 判定整个输入序列与表达式是否匹配
regex_search 判定是否有子串与表达式匹配,找到一个就停止
regrex_replace 使用给定格式替换一个表达式
sregex_iterator 迭代器适配器,调用search来遍历一个string中所有的子串
smatch 容器类,保存搜索的结果
ssub_match string中匹配的子表达式的结果
regrex_search参数 (seq, m, r, mft) 在seq序列中查找regrex对象r中的正则表达式,匹配的结果保存在m,mft是一个可选的regex_constants::match_flag_type值,会影响匹配过程
regex_match参数 (seq, r, mft)
regex r(re, f) re是一个正则表达式,f是标志,默认为ECMAScript
标志定义在regex和regex_constants::syntax_option_type中
icase 在匹配过程中忽略大小写
nosubs 不保存匹配的子表达式
optimize 执行速度优先于构造速度
ECMAScript 使用ECMA-262指定的语法
basic 使用POSIX基本的正则表达式语法
extended POSIX扩展
awk POSIX版本的awk语言的语法
grep POSIX版本的grep语法
egrep POSIX版本的egrep语法
  • 特殊字符
[^c]任意不是c的字符
ECMAScript中[[:alpha:]]表示匹配任意字母
+表示一个或多个
*表示零个或多个
string pattern(“[^c]ei”);
pattern = “[[:alpha:]]*” + pattern + “[[:alpha:]]*”; regex r(“[[:alpha:]]+\\.(cpp|cxx|cc)$”, regex::icase);
字符点.通常匹配任意字符
可以在前面放一个反斜线来去掉其特殊意义
又因为反斜线也是C++中的特殊字符,所以需要再使用一个反斜线得到普通反斜线字符
  • 使用
一个正则表达式的语法是否正确是在运行时解析的。
如果存在错误,会抛出regex_error
catch (regex_error e)
{cout<<e.what()<<”\ncode: ”<<e.code()<<endl;}
构造或者赋值一个regex对象是非常耗时的,最小化开销应该避免创建不必要的regex。
特别是在循环中使用的话,应该在外部创建。
  • RE库类

    string regex、smatch、ssub_match和sregex_iterator

    const char* regex、cmatch、csub_match和cregex_iterator

    wstring wregex、wsmatch、wssub_match和wsregex_iterator

    const wchar_t* wregex、wcmatch、wcsub_match和wcregex_iterator

迭代器在构造时会执行一次search,后面每递增一次从当前位置开始调用search

sregex_iterator it(b, e, r);

sregex_iterator end; //空的表示尾后迭代器

除了得到匹配的结果,我们还能够得到匹配结果的更多细节信息。

                            it->str()

it->prefix().str() xxxeixxx it->suffix().str()

  • smatch操作

(同样适用于cmatch、wsmatch、wcmatch和对应的csub_match、wsub_match和wcsub_match)

操作 描述
m.ready() 已经通过搜索设置了m则返回true
m.size() 如匹配失败,则返回0;否则返回匹配子表达式的个数
m.empty() size为0 则true
m.prefix() 一个ssub_match对象,表示当前匹配之前的序列
m.suffix() 之后的序列
m.format(…) 生成格式化输出
以下n默认0且必须小于m.size().索引0表示整个匹配
m.length(n) 匹配结果中第n个子表达式
mposition(n) 第n个子表达式距序列开始的距离
m.str(n) 第n个子表达式的string
m[n] 对应第n个子表达式的ssub_match对象
m.begin() m.end() 表示m中sun_match元素范围的迭代器
m.cbegin() m.cend()
  • 使用子表达式
通常用括号表示子表达式
regex r(“[[:alpha:]]+\\.(cpp|cxx|cc)$”, regex::icase);
如上面的例子在search之后
results.str(1)表示第一个子表达式,即文件名部分
  • ECMAScript正则表达式的一些特性
\{d}表示单个数字,\{d}{n}表示n个数字(如\{d}{3})
方括号中的字符集合表示匹配这些字符中任意一个(如[-. ]匹配短横、点或一个空格)。点在括号中没有特殊含义
后接一个’?’的组件是可选的( \{d}{3}[-. ]?\{d}{4} )
反斜线表示一个字符本身而不是其特殊意义。由于括号是特殊字符,所以需要加\(和\)
C++中反斜线是特殊字符,所以每次出现的地方都要两个\\
“(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ]?)(\\d{4})”
(\\()? 表示区号部分可选的左括号
(\\d{3}) 表示区号
(\\))? 表示区号部分可选的右括号
([-. ])? 表示可选的分隔符
(\\d{3}) 表示3位号码
([-. ]?) 表示可选的分隔符
(\\d{4}) 表示号码的最后4位
  • 子匹配操作
操作 描述
matched 指出ssub_match是否匹配了
first 指向匹配序列首元素的迭代器
second 指向匹配序列尾后位置的迭代器
length() 子匹配序列的大小
str() 返回一个包含输入中匹配部分的string,未匹配则空串
s=ssub ssub_match对象ssub转换为string对象
  • 当希望查找并替换时,可以使用regex_replace
m.format(dest, fmt,mft)
m.format(fmt, mft)
使用格式化字符串fmt生成格式化输出。第一个版本写入迭代器dest指向的目的位置。fmt可以是string,也可以是表示字符数组范围的一对指针。
第二个版本返回一个string,fmt可以是string,也可以是一个指向空字符结尾的指针。
mft默认format_default
regex_replace(dest, seq, r, fmt, mft)
regex_replace(seq, r, fmt, mft)
遍历seq查找匹配的子串。seq既可以是string也可以是c风格字符串。fmt既可以是string也可以是c风格字符串。
mft默认match_default
  • 使用$后跟子表达式的索引号来表示一个特定的子表达式
string fmt=”$2.$5.$7”;//将号码格式改为ddd.ddd.dddd
regex r(phone);
string number = “(905) 555-1800”;
cout<<regex_replace(number, r, fmt)<<endl;
  • 匹配和格式化标志 regex_constants::match_flag_type
标志 描述
match_default 同format_dafault
match_not_bol 不将首字符作为行首处理
match_not_eol 不将尾字符作为行尾处理
match_not_bow 不将首字符作为单词首处理
match_not_eow 不将尾字符作为单词尾处理
match_any 如果存在多余一个匹配,则可返回任意一个匹配
match_not_null 不匹配任何空序列
match_continuous 匹配必须从输入的首字符开始
match_prev_avial 输入序列包含第一个匹配之前的内容
format_default 使用ECMAScript规则替换字符串
format_sed 用POSIX sed规则替换
format_no_copy 不输出输入序列中未匹配的部分
format_first_only 只替换子表达式的第一次出现

随机数

以前都依赖rand函数来生成,此函数生成均匀分布的伪随机整数。每个数的范围都在0到一个系统相关最大值之间。
问题:需要不同范围的随机数,需要随机浮点数,需要非均匀分布的数。程序员为解决这些问题而试图转换的过程常常会引入非随机性。 标准库提供了随机数引擎类和随机数分布类来解决这些问题。
引擎类生成unsigned随机数序列,分布类使用引擎类生成指定类型的、在给定范围内、服从特定概率分布的随机数。 C++程序不应该使用rand,而应该使用default_random_engine类和恰当的分布类对象
可以通过调用引擎对象来生成原始随机数
default_random_engine e; cout<<e()<<endl;
引擎可以用整型值s作为种子 Engine e(s); e.seed(s);//重置引擎状态
e.discard(u) 将引擎推进u步 原始随机数通常不能直接使用,需要转换。所以用到分布类
uniform_int_distribution<unsigned> u(0, 9);//0到9之间(包含)均匀分布随机数
default_random_engine e;
cout<<u(e)<<endl; 分布类也是函数对象类,可以调用,接收一个引擎对象作为参数。注意是引擎对象本身,而不是其生成的值。 当我们说随机数发生器时,是指的引擎对象和分布对象的组合。 引擎生成整数在一个系统定义的范围内(我的系统0到4294967295)
rand生成范围0到RAND_MAX之间(我的系统0到32767) 每次返回相同的数值序列,在调试时非常有用,但是设计时必须考虑。
如是局部的可以定义为static,则每次调用都会推进。
种子是一个数值,引擎可以从序列中一个新位置重新开始生成随机数。
最常用的是调用系统时间time(在头文件<ctime>中),time接受单个指针参数,指向用于写入时间的数据结构。如果指针为空,则简单的返回时间。
因为time返回的是以秒计的时间,只适用于生成种子间隔秒级甚至更长的应用。
d.reset()//重置d的状态,不依赖与已经生成的值 uniform_real_distribution<double> u(0, 1); //生成均匀分布的随机实数,同样包含 非均匀分布随机数
标准库定义20中分布类型,见附录
正态 normal_distribution<> n(4, 1.5);
伯努利 bernoulli_ distribution b;//非模板,返回bool,true的概率为常数,默认0.5

IO库再探

格式控制、未格式化IO、随机访问

操纵符改变流的状态,通常改变后对后面所有IO都生效。不需要特殊格式时尽快恢复。

输出控制:控制数值输出形式,控制补白的数量和位置

浮点数默认:6位数字精度打印;没有小数部分则不打印小数点根据浮点数的值打印成定点十进制或科学计数法

调用IO对象的precision成员或setprecision操纵符来改变精度

precision接收一个int,将精度设置成此值,并返回旧精度值。或者不接受参数,返回当前精度值。setprecision接收一个参数设置精度。

scientific、fixed或hexfloat后,精度值时控制的小数点后位数,而默认是总的位数。

setw指定下一个数字或字符串值的最小空间

setfill可以指定一个字符替代默认的空格

setprecision设置精度

setbase设置整数输出进制

  • 输入控制

默认:忽略空白符(空格、制表符、换行符、换纸符、回车符)

操纵符noskipws,读取空白符,skipws恢复

  • 未格式化IO , 允许我们将一个流当做无解释的字节序列来处理

    单字节低层IO操作

操作 描述
is.get(ch) 从is读取下一个字节存入字符ch中,返回is
os.put(ch) 将字符ch输出到os,返回os
is.get() 将is的下一个字节作为一个int返回
is.putback(ch) 将字符ch放回is,返回is
is.unget() 将is向后移动一个字节,返回is
is.peek() 将下一个字节作为int返回,但是不从流中删除它
  • 标准库保证我们可以退回最多一个值
返回int值可以返回文件尾标记,char范围内的字符都已经占了。标准库使用负值表示文件尾。<cstdio>中定义了名为EOF的const来检测返回的是否是文件尾。
int ch;
while((ch = cin.get() !=EOF)
cout.put(ch);
  • 多字节底层IO操作
操作 描述
is.get(sink, size, delim) 从is中读取最多size个字节,保存在sink给出的字符数组中。直至遇到字符delim或者读满了size个或遇到文件尾。delim不读取,留在输入流中
is.getline(sink, size, delim) 与上面的get类似,但是会读取并丢弃delim
is.read(sink,size) 读取最多size个字节,存入字符数组sink。返回is
is.gcount() 返回上一个未格式化读取操作从is读取的字节数
os.write(source, size) 将字符数组source中size个字节写入os,返回os
is.ignore(size, delim) 读取并忽略最多size个字符,包括delim。size默认为1,delim默认为文件尾。

一般情况下,推荐更安全更高层的操作

  • 流随机访问

随机IO本质上依赖于系统

IO类型维护一个标记来确定下一个读写操作要在哪里进行。

istream和ostream通常不支持随机访问

操作 描述
tellg() 返回一个输入流中标记的当前位置
tellp() 输出流
seekg(pos)
seekp(pos) 输出流
seekg(off, from) 将一个输入流中,将标记定位到from前后off个字符的位置
seekp(off, from) from可以是beg,cur,end

流中只维护单一的标记,对于支持读写操作的流,在读写之间切换时,必须进行seek操作来重定位标记。

pos和off的类型分别是是pos_type和off_type,是机器相关的,定义在和