您的位置:首页 > 编程语言 > C语言/C++

《C++primer(第五版)》学习之路-第十七章:标准库特殊设施

2015-10-04 21:09 525 查看
【 声明:版权所有,转载请标明出处,请勿用于商业用途。 联系信箱:libin493073668@sina.com】

17.1 tuple类型

1.tuple是类似pair的模板。每个pair的成员类型都不同,但每个pair都恰好有两个成员。不同tuple类型的成员类型也不相同,但一个tuple可以有任意数量的成员。每个确定的tuple类型的成员数目是固定的,但一个tuple类型的成员数目可以与另一个tuple类型不同。

要访问一个tuple成员,就要使用一个名为get的标准库函数模板。

2.

tuple支持的操作

tuple<T1,T2,...,Tn> t;

t是一个tuple,成员数位n,第i个成员的类型为Ti。所有成员都进行值初始化

tuple<T1,T2,...,Tn>
t(v1,v2,...,vn);

t是一个tuple,成员类型为T1,T2,...,Tn,每个成员用对应的初始值vi进行初始化。此构造函数是explicit的

make_tuple(v1,v2,...,vn);

返回一个用给定初始值初始化的tuple。tuple的类型从初始值的类型推断

t1
== t2

t1
!= t2

当两个tulpe具有相同数量的成员对应相等时,两个tuple相等。这两个操作使用成员的==运算符来完成。一旦发现某对成员不等,接下来的成员就不用比较了

t1
relop t2

tuple的关系运算使用字典序。两个tuple必须具有相同数量成员。使用<运算符比较t1的成员和t2的对应成员。

get<i>(t)

返回t的第i个成员的引用;如果t是一个左值,结果是一个左值引用;否则,结果是一个右值引用。tuple的所有成员都是public的

tuple_size<tupleType>::value

一个类模板,可以通过一个tuple类型来初始化,它有一个名为value的public
constexpr static数据成员,类型为size_t,表示给定tuple类型中成员的数量

tuple_element<i,tupleType>::type

一个类模板,可以通过一个整型常量和一个tuple类型来初始化,它有一个名为type的public成员,表示给定tuple类型中指定成员的类型。

17.2 bitset类型

1.

初始化bitset的方法

bitset<n> b;

b有n位,每一位均为0,此构造函数是一个constexpr

bitset<n> b(u);

b是unsigned long long值u的低n位的拷贝。如果n大于unsigned
long long的大小,则b中超出unsigned long long的高位被置为0.此构造函数是一个constexpr

bitset<n>
b(s,pos,m,zero,one);

b是string
s从位置pos开始m个字符的拷贝。s只能包含字符zero或one;如果s包含其他任何字符,构造函数会抛出invalid_argument异常。字符在b中分别保存为zero和one。pos默认为0,m默认为string::npos,zero默认为'0',one默认为'1'。

bitset<n>
b(cp,pos,m,zero,one);

与上一个构造函数相同,但从cp指向的字符数组中拷贝字符。如果未提供m,则cp必须指向C风格字符串。如果提供了m,则从cp开始必须至少有M个zero或one字符。

2.

bitset操作

b.any()

b中是否存在置位的二进制位

b.all()

b中所有元素都置位了吗

b.none()

b中不存在置位的二进制位吗

b.count()

b中置位的位数

b.size()

一个constexpr函数,返回b的位数

b.text(pos)

若pos位置的位是置位的,则返回true,否则返回false

b.set(pos,v)

b.set()

将位置pos处的位设置为bool值为v。v默认为true。如果未传递实参,则将b中所有位置位

b.reset(pos)

b.reset()

将位置pos处的位复位或将b中所有位复位

b.filp(pos)

b.filp()

改变位置pos处的位的状态或改变b中每一位的状态

b[pos]

访问b中位置pos处的位;如果b是const的,则当该位置位时b[pos]返回一个bool值true,否则返回false

b.to_ulong()

b.to_ullong()

返回一个unsigned
long或一个unsigned long long值,其位模式与相同。如果b中位模式不能放入指定的结果类型,则抛出一个overflow_error异常

b.to_string(zero,one)

返回一个string,表示b中的位模式。zero和one默认值分别为0和1,用来表示b中的0和1

os<<b

将b中二进制位打印为字符1或0,打印到流os

is>>b

从is读取字符存入b。当下一个字符不是1或0时,或是已经读入b.size()个位时,读取过程停止

17.3
正则表达式


1.正则表达式库组件

regex

表示由一个正则表达式的类

regex_match

将一个字符序列与一个正则表达式匹配

regex_search

寻找第一个与正则表达式匹配的子序列

regex_replace

使用给定格式替换一个正则表达式

sregex_iterator

迭代器适配器,调用regex_search来遍历一个string中所有匹配的子串

smatch

容器类,保存在string中搜索的结果

ssub_match

string中匹配的子表达式的结果

17.4 随机数

1.

随机数库的组成

引擎类型:生成随机unsigned整数序列

分布类型:使用引擎返回服从特定概率分布的随机数

2.随机数引擎操作

Engine e

默认构造函数,使用该引擎类型默认的种子

Engine e(s)

使用整型值s作为种子

e.seed(s)

使用种子s重置引擎的状态

e.min()

e.max()

此引擎可生成的最小值和最大值

Engine::result_type

此引擎生成的unsigned整型类型

e.discard(u)

将引擎推进u步,u的类型为unsigned long long

3.分布类型的操作

Dist d;

默认构造函数;使d准备好被使用

其他构造函数依赖于Dist的类型。分布类型的构造函数是explicit的

d(e)

用相同的e连续调用d的话,会根据d的分布式类型生成一个随机数序列;e是一个随机数引擎对象

d.min()

d.max()

返回d(e)能生成的最小值和最大值

d.reset()

重建d的状态,使得随后对d的使用不依赖于d已经生成的值

17.5 IO库再探

1.操作符用于两大类输出控制:控制数值的输出形式以及控制补白的数量和位置。大多数改变格式状态的操纵符都是设置/复原成对的;一个操纵符用来将格式状态设置为一个新值,而另一个用来将其复原,恢复为正常的默认格式。

PS:部分练习答案

练习17.1 & 17.2

#include <iostream>
#include <tuple>
#include <string>
#include <vector>

int main()
{
std::tuple<int,int,int> i3 {10,20,30};
std::tuple<std::string,std::vector<std::string>, std::pair<std::string, int>> t;

}


练习17.4

std::vector<matches>
findBook(const std::vector<std::vector<Sales_data>>& files, const std::string& book)
{
std::vector<matches> ret;

for (auto it = files.cbegin(); it != files.cend(); ++it)
{
auto found = std::equal_range(it->cbegin(), it->cend(), book, compareIsbn);
if(found.first != found.second)
ret.push_back(std::make_tuple(it - files.cbegin(), found.first, found.second));
}
return ret;
}


练习17.5

std::vector<matches_pair> findBook_pair(const std::vector<std::vector<Sales_data> > &files, const std::string &book)
{
std::vector<matches_pair> ret;
for(auto it = files.cbegin(); it != files.cend(); ++it)
{
auto found = std::equal_range(it->cbegin(), it->cend(), book, compareIsbn);
if(found.first != found.second)
ret.push_back(std::make_pair(it - files.cbegin(), std::make_pair(found.first, found.second)));
}
return ret;
}


练习17.6

std::vector<matches_struct> findBook_struct(const std::vector<std::vector<Sales_data> > &files, const std::string &book)
{
std::vector<matches_struct> ret;
for(auto it = files.cbegin(); it != files.cend(); ++it)
{
auto found = std::equal_range(it->cbegin(), it->cend(), book, compareIsbn);
if(found.first != found.second)
ret.push_back(matches_struct(it - files.cbegin(), found.first, found.second));
}
return ret;
}


练习17.10

#include <iostream>
#include <bitset>
#include <vector>

int main()
{
std::vector<int> v = {1,2,3,5,8,13,21};
std::bitset<32> bset;

for (auto i : v)
bset.set(i);

std::bitset<32> bset2;
for (unsigned i = 0; i != 32; ++i)
bset2[i] = bset[i];

std::cout <<bset <<std::endl;
std::cout <<bset2<<std::endl;
}


练习17.11 & 17.12 & 17.13

#ifndef QUIZ
#define QUIZ
#include <iostream>
#include <bitset>
#include <utility>
#include <string>
#include <iostream>

//class Quiz
template<std::size_t N>
class Quiz
{
public:
//constructors
Quiz() = default;
Quiz(std::string& s) :bitquiz(s) {}

//generate grade
template<std::size_t M>
friend std::size_t grade(Quiz<M> const&, Quiz<M> const&);

//print
template<std::size_t M>
friend std::ostream& operator<<(std::ostream&, Quiz<M> const&);

//update bitset
void update(std::pair<std::size_t, bool>);
private:
std::bitset<N> bitquiz;
};
#endif

template<std::size_t N>
void Quiz<N>::update(std::pair<std::size_t, bool> pair)
{
bitquiz.set(pair.first, pair.second);
}

template<std::size_t M>
std::ostream& operator<<(std::ostream& os, Quiz<M> const& quiz)
{
os << quiz.bitquiz;
return os;
}

template<std::size_t M>
std::size_t grade(Quiz<M> const& corAns, Quiz<M> const& stuAns)
{
auto result = stuAns.bitquiz ^ corAns.bitquiz;
result.flip();
return result.count();
}

int main()
{
//Ex17_11
std::string s = "1010101";
Quiz<10> quiz(s);
std::cout << quiz << std::endl;

//EX17_12
quiz.update(std::make_pair(1, true));
std::cout << quiz << std::endl;

//Ex17_13
std::string answer = "10011";
std::string stu_answer = "11001";
Quiz<5> ans(answer), stu_ans(stu_answer);
std::cout << grade(ans, stu_ans) << std::endl;

return 0;
}


练习17.14 & 17.15 & 17.16

#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include<string>
using std::string;

#include <regex>
using std::regex;
using std::regex_error;

int main()
{
//! for ex17.14
//! error_brack
try
{
regex r("[[:alnum:]+\\.(cpp|cxx|cc)$", regex::icase);
}
catch(regex_error e)
{
cout << e.what() << " code: " << e.code() << endl;
}

//! for ex17.15
regex r("[[:alpha:]]*[^c]ei[[:alpha:]]*", regex::icase);
string s;
cout << "Please input a word! Input 'q' to quit!" << endl;
while(cin >> s && s != "q")
{
if(std::regex_match(s, r))
cout << "Input word " << s << " is okay!" << endl;
else
cout << "Input word " << s << " is not okay!" <<endl;

cout << "Please input a word! Input 'q' to quit!" << endl;
}

cout << endl;

//! for ex17.16
r.assign("[^c]ei", regex::icase);
cout << "Please input a word! Input 'q' to quit!" << endl;
while(cin >> s && s != "q")
{
if(std::regex_match(s, r))
cout << "Input word " << s << " is okay!" << endl;
else
cout << "Input word " << s << " is not okay!" <<endl;

cout << "Please input a word! Input 'q' to quit!" << endl;
}

return 0;
}


练习17.17
& 17.18

#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include<string>
using std::string;

#include <regex>
using std::regex;
using std::sregex_iterator;

int main()
{
string s;
cout << "Please input a sequence of words:" << endl;
getline(cin, s);
cout << endl;
cout << "Word(s) that violiate the \"ei\" grammar rule:" << endl;
string pattern("[^c]ei");
pattern = "[[:alpha:]]*" + pattern + "[[:alpha:]]*";
regex r(pattern, regex::icase);
for (sregex_iterator it(s.begin(), s.end(), r), end_it;
it != end_it; ++it)
cout << it->str() << endl;

return 0;
}


练习17.19 & 19.20

#include <iostream>
#include<string>
#include <regex>

using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::regex;
using std::sregex_iterator;
using std::smatch;

bool valid(const smatch& m);

int main()
{
string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ]?)(\\d{4})";
regex r(phone);
smatch m;
string s;
bool valid_record;
while (getline(cin, s))
{
valid_record = false;

for (sregex_iterator it(s.begin(), s.end(), r), end_it; it != end_it; ++it)
{
valid_record = true;
if (valid(*it))
cout << "valid phone number: " << it->str() << endl;
else
cout << "invalid phone number: " << it->str() << endl;
}

if (!valid_record)
cout << "invalid record!" << endl;
}
return 0;
}

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();
}


练习17.28 & 17.29 & 17.30

#include <iostream>
#include <random>
//ex17.28
unsigned random_gen()
{
static std::default_random_engine e;
static std::uniform_int_distribution<unsigned> ud;
return ud(e);
}
//ex17.29
unsigned random_gen(unsigned seed)
{
static std::default_random_engine e(seed);
static std::uniform_int_distribution<unsigned> ud;
return ud(e);
}
//ex17.30
unsigned random_gen(unsigned seed, unsigned min, unsigned max)
{
static std::default_random_engine e(seed);
static std::uniform_int_distribution<unsigned> ud(min,max);
return ud(e);
}

int main()
{
std::string temp;
while(std::cin >> temp)
std::cout << std::hex << random_gen(19,1,10) << std::endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++primer