c++ primer 第五版 笔记 第十七章

第十七章标准库设施

17.1 tuple类型

不同tuple的成员类型不同,且可以有任意数量的成员。每个tuple类型的成员数目是固定的,但一个tuple类型的成员数目可以与另一个tuple类型不同

在这里插入图片描述

17.1.1 定义和初始化tuple

tuple<size_t,size_t,size_t> threeD;
tuple<string,vector<double>,int,list<int>>
    someVal("constants",{3.14,2.718},42,{0,1,2,3,4,5});
auto item = make_tuple("0-999-78345-X",3,20.00);

访问tuple成员

auto book = get<0>(item);
auto cnt = get<1>(item);
auto price = get<2>(item)/cnt;
get<2>(item) *= 0.8;

typedef decltype(item) trans;

size_t sz = tuple_size<trans>::value;//返回3
tuple_element<1,trans>::type cnt = get<1>(item);

17.2 bitset类型

17.2.1 定义和初始化bitset

在这里插入图片描述

bitset<32> bitvec(1U);//32位,低位位1,其他位为0
bitset<32> bitvec4("1100");//2 3位为1,其他为0

17.2.2 bitset操作

在这里插入图片描述

17.3 正则表达式

在这里插入图片描述

regex类表示一个正则表达式。除了初始化和赋值之外,regex还支持其他一些操作。

函数regex_match和regex_search确定一个给定字符序列与一个给定regex是否匹配。如果整个输入序列与表达式匹配,则regex_match函数返回true;如果输入序列中一个子串与表达式匹配,则regex_search函数返回true。

17.3.1 使用正则表达式库

string pattern("[^c]ei");
pattern = "[[:alpaha:]]*"+pattern+"[[:alpha:]]*";
regex r(pattern);//构造一个用于查找模式的regex
smatch results;//定义一个对象保存搜索结果

string test_str = "receipt freind theif receive";

if(regex_search(test_str,results,r))
    cout << results.str() << endl;

指定regex对象的选项

当我们定义一个regex或是对一个regex调用assign为其赋予新值时,可以指定一些标志来影响regex如何操作。

在这里插入图片描述

正则表达式的错误

注意:一个正则表达式的语法是否正确是在运行时解析的。

常见错误类型如下:

在这里插入图片描述

正则表达式类和输入序列类型

输入可以是char数据或是wchar_t数据,字符可以保存在string中,或是char数组中。RE为这些不同的输入序列类型都定义了对应的类型,如下图:

在这里插入图片描述

17.3.2 匹配与Regex迭代器类型

string pattern("[^c]ei");
pattern = "[[:alpha:]]*"+pattern+"[[:alpha:]]*";

regex r(pattern,regex::icase);

for(sregex_iterator it(file.begin(),file.end(),r),end_it;it != end_it ;++it)
    cout << it->str() << endl;

sregex_iterator绑定一个string和一个regex对象时,迭代器自动定位到给定string中第一个匹配位置。当解引用迭代器时,会得到一个对应最近一次搜索结果的smatch对象。当递增迭代器时,它调用regex_search在输入string中查找下一个匹配

17.3.3 使用子表达式

regex r("([[:alnum:]]+)\\.(cpp|cxx|cc)$",regex::icase);

if(regex_search(filename,results,r))
    cout << results.str(1) << endl;//打印第一个子表达式

匹配对象除了提供匹配整体的相关信息以外,还提供访问模式中每个子表达式的能力。子匹配是按位置来访问的。第一个子匹配位置为0,表示整个模式对应的匹配,随后是每个子表达式对应的匹配。因此,本例中第一个子表达式,即表示文件名的子表达式,其位置为1,而文件扩展名对应的子表达式位置为2.

17.3.4 使用regex_replace

还可以在输入序列中查找并替换一个正则表达式,此时可以使用regex_replace.下图描述了regex_replace

在这里插入图片描述

string fmt = "$2.$5.$7";

regex r(phone);
string number="(908) 555-1800";

cout << regex_replace(number,r,fmt) << endl;

输出为:

908.555.1800

用来控制匹配和格式的标志

标准库还定义了用来在替换过程中控制匹配和格式的标志。如下图。这些标志可以传递给函数regex_search或regex_match或是类smatch的format成员

在这里插入图片描述

17.4 随机数

c++中跟随机数相关的两个概念有:随机数引擎和随机数分布。

随机数引擎用于生成unsigned随机数序列。

随机数分布用于对引擎生成的随机数进行特定的概率分布

17.4.1 随机数引擎和分布

default_random_engine e;
for(size_t i = 0;i< 10;++i)
    cout << e() << " ";

下图列出了随机数引擎常见的操作

在这里插入图片描述
分布类型和引擎

为了得到一个指定范围内的数,我们使用一个分布类型的对象:

uniform_int_distribution<unsigned> u(0,9);
default_random_engine e;
for(size_t i  = 0;i<10;++i)
    cout << u(e) << " ";

uniform_int_distribution<unsigned>此类型生成俊宇分布的unsigned值。

注意:当我们说随机数发生器时,是指分布对象和引擎对象的组合

引擎生成一个数值序列

注意:一个给定的随机数发生器一直会生成相同的随机数序列。一个函数如果定义了局部的随机数发生器,应该将其定义为static的。否则,每次调用函数都会发生相同的序列

//几乎肯定是生成随机整数vector的错误方法
//每次调用这个函数都会生成相同的100个数
vector<unsigned> bad_randVec(){
    default_random_engine e;
    uniform_int_distribution<unsigned> u(0,9);
    vector<unsiged> ret;
    for(size_t i = 0;i<100;++i)
        ret.push_back(u(e));
    return ret;
}

正确的写法如下

vector<unsigned> good_randVec(){
    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;
}

设置随机数发生器种子

一旦程序调试完毕,我们通常希望每次运行程序都会生成不同的随机结果,可以通过提供一个种子来达到这一目的。

default_random_engine e1;
default_random_engine e2(2147483646);

default_random_engine e3;
e3.seed(32767);

default_random_engine e4(32767);

for(size_t i=0;i!=100;++i)
    if(e1() == e2())
        cout << "unseeded match at iteration:" << i << endl;
    if( e3()!= e4() )
        cout << "seeded differs at iteration:" << endl;

17.4.2 其他随机数分布

随机数引擎生成unsigned数,范围内的每个数被生成的概率都是相同的。而应用程序常常需要不同类型或不同分布的随机数。标准库通过定义不同随机数分布对象来满足这两方面的要求,分布对象和引擎对象协同工作,生成想要的结果。下图列出了分布类型所支持的操作。

在这里插入图片描述

17.5 IO库再探

17.5.1 格式化输入和输出

每个iostream对象维护了一个格式状态来控制IO如何格式化的细节。

标准库定义了一组操纵符来修改流的格式状态,如下图

在这里插入图片描述
在这里插入图片描述

很多操纵符改变格式状态

当操纵符改变流的格式状态时,通常改变后的状态对所有后续IO都生效

17.5.2 未格式化的输入/输出操作

标准库还提供了一组底层操作,支持未格式化IO。这些操作允许我们将一个流当做一个无解释的字节序列来处理

单字节操作

如下图

在这里插入图片描述
将字符放回输入流

标准库提供了三种方法回退字符:

  1. peek返回输入流中下一个字符的副本,但不会将他从流中删除,peek返回的值仍然留在流中

  2. unget使得输入流向后移动,从而最后读取的值又回到流中。即使我们不知道最后从流中读取什么值,仍然可以使用unget

  3. putback是更特殊的unget;它返回从六中读取的最后一个值,但他接受一个参数,此参数必须与最后读取的值相同

从输入操作返回的int

返回int的原因是:可以返回文件尾标记。我们使用char范围中的每个值来表示一个真实的字符,因此,取值范围没有额外的值可以用来表示文件尾

多字节操作

下图列出了多字节操作

在这里插入图片描述

17.5.3 流随机访问

标准库提供了一对函数,来定位(seek)到流中给定的位置,以及高速(tell)我们当前位置。

如下图

在这里插入图片描述
本章完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《C Primer》是一本针对C语言初学者的经典教材,第五的第六章主要介绍了函数的基本概念和用法。 在第六章中,教材首先介绍了函数的定义和调用。函数是具有独立功能的代码块,可以通过函数名来调用。函数由函数头、参数、函数体和返回值组成。函数头包括函数类型、函数名和参数类型,参数用于接收传递给函数的值,返回值用于将结果返回给调用者。 接着,教材详细介绍了函数的参数传递方式,包括按值传递、按引用传递和按指针传递。按值传递是指将参数的值复制给形参,按引用传递是指将参数的引用传递给形参,而按指针传递是将参数的地址传递给形参。不同的传递方式在函数内部对参数进行操作时,会对应不同的结果。 此外,教材还讲解了函数的返回值和函数的调用顺序。函数的返回值类型由函数头中的类型确定,可以是任意类型。当函数需要返回多个值时,可以使用结构体或指针进行返回。函数的调用顺序决定了函数执行的顺序,即哪个函数先执行,哪个函数后执行。 在函数的实现过程中,教材介绍了函数的定义和声明、局部变量和全局变量、递归等内容。通过这些知识点的学习,读者可以了解到函数的具体细节和一些实践技巧。 总的来说,第五的第六章通过清晰的语言和丰富的例子,循序渐进地讲解了函数的基本概念和用法。学完这一章,读者将能够理解函数的定义、调用、参数传递、返回值和实现等方面的知识,为之后的学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值