几个标准库的使用:
1.tuple类型
1.1.定义和初始化tuple
tuplet1; //默认值初始化 tuple > t2(1,"a",{1,2}); //直接初始化 tuple t3{ 1,2 }; auto t4 = make_tuple(1, "a"); //自动推断类型
访问tuple的成员
tuplet(1,"a"); auto item = get<0>(t); //第一个元素 get<1>(t) = "b"; typedef decltype(t) v; size_t sz = tuple_size ::value; //tuple中成员数量,返回2 tuple_element<1,v>::type cnt = get<1>(t); //cnt是一个int,获取指定元素的类型
关系和相等运算符
为了使用tuple的相等或不等运算符,对每对成员使用==运算符必须都是合法的; 为了使用关系运算符,对每对成员使用<必须都是合法的。 tuplet1(1,2); tuple t2(1,2); bool b = (t1==t2); b = (t1 1.2.使用tuple返回多个值
tuplefun() { return make_tuple(1, 2); } auto d = fun(); auto first = get<0>(d); 2.bitset类型
2.1.定义和初始化bitset
用unsigned值初始化bitsetbitset<4> b(3); bitset<128> b2(~0ULL); 前面64位补0,后面64位为1(~0ULL之后全为1)从一个string初始化bitset
bitset<8> bitvec("1100"); //2、3两位为1,剩余两位为0; 位值:0000 1100 bitset中的下标从低位到高位,顺序和字符串中的下标顺序是反的。 string s("1111111100000000"); bitset<32> b(s,5,4); //从s[5]开始的四个二进制位 bitset<32> b2(s,s.size()-4); //最后四个字符
2.2.bitset操作
3.正则表达式
3.1.使用正则表达式库string s("[0-9]+"); regex r(s); smatch result; string str = "b123de4567"; if(regex_search(str, result, r)) cout << result.str(); [[::alpha::]] 匹配任意字母 [[::alpha::]]* 匹配零个或多个字母 [[::alpha::]]+ 匹配一个或多个字母指定regex对象的选项
编写程序识别文件扩展名: //一个或多个字母或数字字符后接一个.再接cpp或cxx或cc string p = "[[:alnum:]]+\.(cpp|cxx|cc)$"; regex r(p, regex::icase); smatch result; string fileName; while (cin >> fileName) if (regex_search(fileName, result, r)) cout << result.str() << endl; 由于.是通配符,所以需要加反斜杠,反斜杠也是C++中的特殊字符,因此再加一个反斜杠指定或使用正则表达式时的错误
一个正则表达式的语法是否正确是在运行时解析的。 regex_error成员: what():错误信息 code():错误类型对应的数值编码 try { regex r("[[:alnum:]]+\.(cpp|cxx|cc)$",regex::icase); } catch(regex_error e) { cout<
正则表达式类和输入序列类型
输入类型要匹配:处理什么输入序列类型,用什么类型的表达式类 string p = "[[:alnum:]]+.(cpp|cxx|cc)$"; regex r(p, regex::icase); smatch result; string fileName; while (cin >> fileName) if (regex_search(fileName, result, r)) //这里的result只能是smatch,不能是cmatch等其他类型 cout << result.str() << endl;3.2.匹配与Regex迭代器类型
使用sregex_iterator查找字符串中的数字串 string p = "[0-9]+"; regex r(p); smatch result; string str = "abc123efo345op"; sregex_iterator end; for (sregex_iterator it(str.begin(), str.end(), r); it != end; ++it) { cout << it->str() << endl; cout <<"前子串"<prefix().str() << "长度" << it->prefix().length() << endl; cout <<"后子串"< suffix().str() << "长度" << it->suffix().length() << endl; } 使用匹配数据
3.3.使用子表达式string p = "([0-4]+)([5-9]+)"; //一个小括号代表一个子表达式,两个子表达式 regex r(p); smatch result; string str = "abc123789efo345op"; sregex_iterator end; for (sregex_iterator it(str.begin(), str.end(), r); it != end; ++it) { cout << it->str() <<" First: "<str(1) << " Second: "< str(2) < 子表达式用于数据验证
string p = "(\()?(\d{3})(\))?([-. ])?(\d{3})([-. ]?)(\d{4})"; regex r(p); smatch result; string str = "abcd(123).123.1324"; sregex_iterator end; for (sregex_iterator it(str.begin(), str.end(), r); it != end; ++it) { cout << it->str() << endl; //匹配(123).123.1324 valid(*it); //验证 } (\()? :匹配( (\d{3}) :匹配3个数字 (\))? :匹配) ([-. ])? :匹配-.空格分隔符 (\d{4})" :匹配4个数字使用子匹配操作
bool valid(const smatch& m) { if(m[1].matched) //有左括号,就得有有括号 return m[3].matched && (m[4].matched == 0 || m[4].str() == " "); else //没有左括号,也没有右括号 return !m[3].matched && m[4].str() == m[6].str(); //分隔符必须匹配 }3.4.使用regex_replace
替换输入序列的一部分regex r("[0-9]+"); string str("abc123aoe"); string fmt("BBB$1AAA"); //$1表示第一个子表达式,在第一个子表达式前面置BBB,后面置AAA cout<用来控制匹配和格式的标志
使用格式标志
regex r("[0-9]+"); string str("abc123aoe"); string fmt("BBB$1AAA") cout<4.随机数
C++程序不应该使用库函数rand,应使用default_random_engine类和恰当的分部类对象。
4.1.随机数引擎和分布
default_random_engine e; cout << e() << endl;分布类型和引擎
default_random_engine e(1); //设置随机种子 uniform_int_distributionu(0, 9); //设置范围 cout << u(e) << endl; 比较随机数引擎和rand函数
//下面的函数每次返回的值都是一样的 unsigned getRandom(unsigned min, unsigned max, unsigned seed = 0) { default_random_engine e(seed); uniform_int_distributionu(min, max); return u(e); } 静态对象会保存状态,所以会不一样 unsigned getRandom(unsigned min, unsigned max, unsigned seed = 0) { static default_random_engine e(seed); static uniform_int_distribution u(min, max); return u(e); } 4.2.其他随机数分布
生成随机实数
default_random_engine e(1); uniform_real_distributionu2(0,1); //随机浮点数 cout << u(e) << endl;
使用分布的默认结果类型uniform_real_distribution<> u(0,1); //<>默认生成double值 uniform_int_distribution<> u(0, 9); //默认生成int值生成非均匀分布的随机数
正态分布 default_random_engine e; normal_distribution<> n(4, 1.5); //均值4,标准差1.5 n(e);伯努利分布
default_random_engine e; bernoulli_distribution b; //普通类 b(e); //默认是50/50的机会 bernoulli_distribution b(.55); 55/45的机会5.IO库在探
5.1.格式化输入与输出
输出补白
cout << left; //左对齐 cout << "i:" << setw(6) << "AAA" << endl; i:AAA cout << right; //右对齐 cout << "i:" << setw(6) << "AAA" << endl; i: AAA cout << internal; //用空白填充 cout << "i:" << setw(6) << "AAA" << endl; i: AAA cout << setfill('#'); //用字符填充 cout << "i:" << setw(6) << "AAA" << endl; i:###AAA控制输入格式
空白符:空格符、制表符、换行符、换纸符、回车符 默认cin会忽略空白符 noskipws:设置cin读取空白符 输入: a b c d 默认输出:abcd 设置noskipws输出: a b c d5.2.未格式化的输入/输出操作
标准库还提供了一组底层操作,支持未格式化IO。这些操作允许我们将一个流当作一个无解释的字节序列来处理。单字节操作
char ch; while(cin.get(ch)) cout.put(ch);将字符放回输入流
cin.peek(); cin.unget(); cin.putback(1);从输入操作返回的int值
int i; while (i = cin.get() != EOF) { cout.put(i); }多字节操作
确定读取了多少个字符
5.3.流随机访问
随机IO本质上是依赖于系统的,为了理解如何使用这些特性,你必须查询系统文档。 标准库提供了一对函数来定位(seek)到流中给定的位置,已经告诉(tell)我们当前位置。 虽然标准库为所有流类型都定义了seek和tell函数,但它们是否会做有意义的事情依赖于流绑定到哪个设备。 在大多数系统中,cin、cout、cerr、clog的流不支持随机访问:当向cout直接输出数据时,类似向回跳十个 位置这种操作是没有意义的。对这些流我们可以调用seek、tell函数,但在运行时会出错,将流置于一个无效 状态。 由于istream和ostream类型通常不支持随机访问,剩余内容只适用于fstream和sstream类型。seek和tell函数
为了支持随机访问,IO类型维护了一个标记来确定下一个读写操作要在哪里进行。 提供了两个函数: seek:将标记定位到一个给定位置 tell:告诉我们标记的当前位置 标准库定义了两队seek和tell函数,一对用于输入流(后缀g,获得数据),另一对用于输出流(后缀p,放置数据)只有一个标记
流中只维护单一的标记:并不存在独立的读标记和写标记重定位标记
seekg(new_pos); //绝对位置 seekg(offset,from); //相对位置访问标记
tellg(); fstream::beg sstream::beg 例如: fstream fs("path",fstream::ate|fstream::in|fstream::out); //定位到文件尾 auto endPos= fs.tellg(); //获取文件尾位置 fs.seek(0,fstream::beg); //从定位到文件开始位置 fs.seek(endPos) //定位到文件尾 fs<<"abc"; fs<<"abcn"; //输入5个字符,n添加了两个字符,最后一个字符是‘n’



