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

 声明:版权所有,转载请标明出处,请勿用于商业用途。  联系信箱:[email protected]


17.1 tuple类型


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

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


2.

tuple支持的操作

 tuple t;

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

tuple 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(t)

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

tuple_size::value

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

tuple_element::type

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


17.2 bitset类型


1.

初始化bitset的方法

bitset b;

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

bitset b(u);

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

bitset 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 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中二进制位打印为字符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 
#include 
#include 
#include 


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

}

练习17.4

std::vector
findBook(const std::vector>& files, const std::string& book)
{
	std::vector 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 findBook_pair(const std::vector > &files, const std::string &book)
{
	std::vector 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 findBook_struct(const std::vector > &files, const std::string &book)
{
	std::vector 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 
#include 
#include 

int main()
{
	std::vector 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 <

练习17.11 & 17.12 & 17.13

#ifndef QUIZ
#define QUIZ
#include 
#include 
#include 
#include 
#include 

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

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

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

		//update bitset
		void update(std::pair);
	private:
		std::bitset bitquiz;
};
#endif

template
void Quiz::update(std::pair pair)
{
	bitquiz.set(pair.first, pair.second);
}

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

template
std::size_t grade(Quiz const& corAns, Quiz 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 
using std::cout;
using std::cin;
using std::endl;

#include
using std::string;

#include 
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!" <> s && s != "q")
	{
		if(std::regex_match(s, r))
			cout << "Input word " << s << " is okay!" << endl;
		else
			cout << "Input word " << s << " is not okay!" <

练习17.17 & 17.18

#include 
using std::cout;
using std::cin;
using std::endl;

#include
using std::string;

#include 
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 
#include
#include 

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 
#include 
//ex17.28
unsigned random_gen()
{
	static std::default_random_engine e;
	static std::uniform_int_distribution ud;
	return ud(e);
}
//ex17.29
unsigned random_gen(unsigned seed)
{
	static std::default_random_engine e(seed);
	static std::uniform_int_distribution 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 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(第五版)》学习之路-第十七章:标准库特殊设施)