C++ Primer 中文第 5 版练习答案 第 10 章 泛型算法

C++ Primer 中文版(第 5 版)练习解答合集

自己写的解答,如有错误之处,烦请在评论区指正!


1 & 2

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <list>
using namespace std;

int main() {
	vector<int> vec{1, 2, 3, 2, 1};
	int cnt = count(vec.begin(), vec.end(), 3); 
	cout << cnt << endl;
	
	list<string> lst{"Hi", "dull", "poker", "vivy", "Hi"};
	cnt = count(lst.begin(), lst.end(), "Hi");
	cout << cnt << endl;
	return 0;
}

3

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
	vector<int> vec{1, 2, 3, 2, 1};
	int sum = 0;
	sum = accumulate(vec.begin(), vec.end(), sum);
	cout << sum << endl;
	return 0;
}

4

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
	vector<double> vec{1.9, 2.9, 3.9, 2.9, 1.9};
	cout << accumulate(vec.begin(), vec.end(), 0) << endl;
	return 0;
}

如以上的代码所示,cout 输出 9,因为编译器认为 0 是 int 类型。如果把 0 改成 0.0 才是想要的结果:13.5。

5

编译错误。因为 C 风格字符串之间没有定义相等运算符。

6

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
	vector<double> vec{1.9, 2.9, 3.9, 2.9, 1.9};
	fill_n(vec.begin(), vec.size(), 0.0);
	for (auto num : vec)
		cout << num << " ";
	return 0;
}

7

(a)copy 中,vec 没有预留足够的空间。要么用 back_inserter,要么事先用 resize 开辟足够的空间。

(b)reserve 只是改变 capacity,如果要修改实际大小用 resize

代码改成下面这样:

#include <iostream>
#include <algorithm>
#include <vector>
#include <list>
using namespace std;

int main() {
	// 1007(a)
	vector<int> vec;
	list<int> lst;
	int i;
	while (cin >> i)
		lst.push_back(i);
	copy(lst.cbegin(), lst.cend(), back_inserter(vec));
	for (auto num : vec)
		cout << num << " ";
	cout << endl;
	// 1007(b)
	vector<int> vec1;
	vec1.resize(10);
	fill_n(vec1.begin(), 10, 0);
	for (auto num : vec1)
		cout << num << " ";
	cout << endl;
	return 0;
}

8

严格来说,泛型算法只操作迭代器,不操作容器,甚至不关心容器是否存在。所以算法能做什么取决于迭代器能做什么,插入迭代器能改变容器大小,那么调用插入迭代器的算法自然也可以。

9

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

void elimDups(vector<string>& words) {
	sort(words.begin(), words.end());
	auto uniqueEnd = unique(words.begin(), words.end());
	words.erase(uniqueEnd, words.end());
}

template <class T>
void displayVec(const vector<T>& vec) {
	for (auto item : vec)
		cout << item << " ";
	cout << endl;
}

int main() {
	vector<string> words{"leet", "code", "nine", "one", "code", "one", "one"};
	elimDups(words);
	displayVec(words);
	return 0;
}

10

和第 8 题一样,泛型算法的操作依赖于迭代器,只要迭代器不支持改变容器大小,算法就不能改变容器大小。(并且一些改变容器大小的行为会让迭代器失效)

11

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

bool isShorter(const string& a, const string& b) {
	return a.size() < b.size();
}

void elimDups(vector<string>& words) {
	sort(words.begin(), words.end(), isShorter);
	auto uniqueEnd = unique(words.begin(), words.end());
	words.erase(uniqueEnd, words.end());
}

template <class T>
void displayVec(const vector<T>& vec) {
	for (auto item : vec)
		cout << item << " ";
	cout << endl;
}

int main() {
	vector<string> words{"leet", "c", "nine", "one", "co", "one", "one"};
	elimDups(words);
	displayVec(words);
	return 0;
}

12

#include <iostream>
#include <algorithm>
#include <vector>
//#include <string>
#include "Sales_data.h"
using namespace std;

bool compareIsbn(const Sales_data& a, const Sales_data& b) {
	return a.isbn() < b.isbn();
}

template <class T>
void displayVec(const vector<T>& vec) {
	for (auto item : vec)
		print(cout, item) << " ";
	cout << endl;
}

int main() {
	vector<Sales_data> vec;
	vec.emplace_back("1009", 10, 7);
	vec.emplace_back("0039", 9, 10);
	vec.emplace_back("9987", 10, 6);
	vec.emplace_back("3456", 0, 10);
	sort(vec.begin(), vec.end(), compareIsbn);
	displayVec(vec);
	return 0;
}

13

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

bool sizeLE5(const string& a) {
	return a.size() >= 5;
}

void displayVec(vector<string>::const_iterator begin, vector<string>::const_iterator end) {
	for (; begin != end; ++begin) {
		cout << *begin << " ";
	}
	cout << endl;
}

int main() {
	vector<string> words{"leetasddaf", "c", "nine", "onffe", "csdfadfao", "one", "onedfdfdf"};
	auto displayEnd = partition(words.begin(), words.end(), sizeLE5);
	displayVec(words.begin(), displayEnd);
	return 0;
}

14

#include <iostream>
using namespace std;

int main() {
	auto sum = [](const int& a, const int& b)->int
				{return a + b;};
	cout << sum(8, 9) << endl;
	return 0;
}

15

#include <iostream>
using namespace std;

int main() {
	int a = 8;
	auto sum = [a](const int& b)->int
				{return a + b;};
	cout << sum(9) << endl;
	return 0;
}

16

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

void biggies(vector<string>& words,
			 vector<string>::size_type sz) {
	sort(words.begin(), words.end(),
		[](const string& a, const string& b)->bool{
			if (a.size() != b.size())
				return a.size() < b.size();
			else
				return a < b;
		});
//	// for debugging
//	for_each(words.begin(), words.end(),
//		[](const string& str){
//			cout << str << " ";
//		});
//	cout << endl;
	// erase the duplicate words
	auto uniqueEnd = unique(words.begin(), words.end());
	words.erase(uniqueEnd, words.end());
	// display words equal or longer than sz
	auto disBegin = find_if(words.begin(), words.end(),
		[sz](const string& str)->bool{
			return str.size() >= sz;
		});
	for_each(disBegin, words.end(),
		[](const string& str){
			cout << str << " "; 
		});
	cout << endl;
}

int main() {
	vector<string> words{"csdfadfao", "c", "nine", "one", "csdfadfao", "one", "onedfdfdf", "aine"};
	biggies(words, 4);
	return 0;
}

17

#include <iostream>
#include <algorithm>
#include <vector>
#include "Sales_data.h"
using namespace std;

template <class T>
void displayVec(const vector<T>& vec) {
	for (auto item : vec)
		print(cout, item) << " ";
	cout << endl;
}

int main() {
	vector<Sales_data> vec;
	vec.emplace_back("1009", 10, 7);
	vec.emplace_back("0039", 9, 10);
	vec.emplace_back("9987", 10, 6);
	vec.emplace_back("3456", 0, 10);
	sort(vec.begin(), vec.end(),
		[](const Sales_data& a, const Sales_data& b) -> bool {
			return a.isbn() < b.isbn();
		});
	displayVec(vec);
	return 0;
}

18

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

void biggies(vector<string>& words,
			 vector<string>::size_type sz) {
	sort(words.begin(), words.end(),
		[](const string& a, const string& b)->bool{
			if (a.size() != b.size())
				return a.size() < b.size();
			else
				return a < b;
		});
	// erase the duplicate words
	auto uniqueEnd = unique(words.begin(), words.end());
	words.erase(uniqueEnd, words.end());
	// display words equal or longer than sz
	auto disBegin = partition(words.begin(), words.end(),
		[sz](const string& str) -> bool {
			return str.size() < sz;
		});
	for_each(disBegin, words.end(),
		[](const string& str){
			cout << str << " "; 
		});
	cout << endl;
}

int main() {
	vector<string> words{"csdfadfao", "c", "nine", "one", "csdfadfao", "one", "onedfdfdf", "aine"};
	biggies(words, 4);
	return 0;
}

19

把 partition 换成 stable_partition

20

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

int main() {
	vector<string> words{"leetasddaf", "c", "nine", "onffe", "csdfadfao", "one", "onedfdfdf"};
	string::size_type sz = 6;
	auto cnt = count_if(words.begin(), words.end(),
		[sz](const string& str) -> bool {
			return str.size() >= sz;
		});
	cout << cnt << endl;
	return 0;
}

21

#include <iostream>
#include <algorithm>
using namespace std;

int main() {
	int test = 5;
	auto dec = [test]() mutable -> bool {
		if (test > 0)
			--test;
		return test == 0;
	};
	for (int i = 0; i < 10; ++i) {
		cout << dec() << endl;
	}
	return 0;
}

22

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <string>
using namespace std;
using namespace std::placeholders;

bool stringSizeLE(const string& str, string::size_type sz) {
	return str.size() <= sz;
}

int main() {
	vector<string> words{"leetasddaf", "c", "nine", "onffe", "csdfadfao", "one", "onedfdfdf"};
	string::size_type sz = 6;
	auto cnt = count_if(words.begin(), words.end(),
			bind(stringSizeLE, _1, sz));
	cout << cnt << endl;
	return 0;
}

23

第一个参数是要适配的可调用对象,后面是一个参数列表

参数列表的参数数量等于可调用对象的参数数量

可以使用 _1_2std::placeholders 中的占位符来替换形参

24

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <string>
using namespace std;
using namespace std::placeholders;

bool check_size(const string& s, string::size_type sz) {
	return s.size() >= sz;
}

int main() {
	vector<string> words{"ccc", "c", "nine", "onffe", "csdfadfao", "one", "onedfdfdf"};
	string target("Hello");
	auto it = find_if(words.begin(), words.end(),
			bind(check_size, _1, target.size()));
	if (it != words.end())
		cout << *it << endl;
	return 0;
}

25

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <string>
using namespace std;
using namespace std::placeholders;

bool check_size(const string& s, string::size_type sz) {
	return s.size() < sz;
}

void biggies(vector<string>& words,
			 vector<string>::size_type sz) {
	sort(words.begin(), words.end(),
		[](const string& a, const string& b)->bool{
			if (a.size() != b.size())
				return a.size() < b.size();
			else
				return a < b;
		});
	// erase the duplicate words
	auto uniqueEnd = unique(words.begin(), words.end());
	words.erase(uniqueEnd, words.end());
	// display words equal or longer than sz
	auto disBegin = partition(words.begin(), words.end(),
		bind(check_size, _1, sz));
	for_each(disBegin, words.end(),
		[](const string& str){
			cout << str << " "; 
		});
	cout << endl;
}

int main() {
	vector<string> words{"csdfadfao", "c", "nine", "one", "csdfadfao", "one", "onedfdfdf", "aine"};
	biggies(words, 4);
	return 0;
}

26

插入器有三种类型:

  • back_inserter:创建使用 push_back 的迭代器
  • front_inserter:创建使用 push_front 的迭代器
  • inserter:创建一个使用 insert 的迭代器。接受第二个参数,一个迭代器,所有元素将被插入到这个迭代器表示的元素前面

27

#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <list>
using namespace std;

int main() {
	vector<int> source{1, 1, 2, 2, 2, 3, 4, 5, 5};
	list<int> target;
	unique_copy(source.begin(), source.end(), back_inserter(target));
	for_each(target.begin(), target.end(),
		[](int num){ cout << num << " "; });
	cout << endl;
	return 0;
}

28

#include <iostream>
#include <algorithm>
#include <iterator>
#include <deque>
using namespace std;

void display(const deque<int>& vec) {
	for (auto num : vec)
		cout << num << " ";
	cout << endl;
}

int main() {
	deque<int> source{1, 1, 2, 2, 2, 3, 4, 5, 5}, target;
	copy(source.begin(), source.end(), inserter(target, target.end()));
	display(target);
	
	target = deque<int>();
	copy(source.begin(), source.end(), back_inserter(target));
	display(target);
	
	target = deque<int>();
	copy(source.begin(), source.end(), front_inserter(target));
	display(target);
	return 0;
}

输出:

1 1 2 2 2 3 4 5 5
1 1 2 2 2 3 4 5 5
5 5 4 3 2 2 2 1 1

29

#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;

int main() {
	ifstream input("words.d");
	vector<string> vec;
	istream_iterator<string> in_iter(input);
	istream_iterator<string> eof;
	while (in_iter != eof) {
		vec.push_back(*in_iter++);
	}
	for (auto str : vec)
		cout << str << " ";
	cout << endl;
	return 0;
}

30

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
	istream_iterator<int> is_iter(cin), eof;
	ostream_iterator<int> os_iter(cout, " ");
	vector<int> vec;
	while (is_iter != eof) {
		vec.push_back(*is_iter++);
	}
	sort(vec.begin(), vec.end());
	copy(vec.begin(), vec.end(), os_iter);
	return 0;
}

31

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
	istream_iterator<int> is_iter(cin), eof;
	ostream_iterator<int> os_iter(cout, " ");
	vector<int> vec;
	while (is_iter != eof) {
		vec.push_back(*is_iter++);
	}
	sort(vec.begin(), vec.end());
	unique_copy(vec.begin(), vec.end(), os_iter);
	return 0;
}

32

#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include "Sales_data.h"
using namespace std;

int main() {
	ifstream input("data.d");
	Sales_data buffer;
	vector<Sales_data> salesdatas;
	while (read(input, buffer)) {
		salesdatas.emplace_back(buffer);
	}
	if (salesdatas.empty()) {
		cerr << "No data" << endl;
		return -1;
	}
	sort(salesdatas.begin(), salesdatas.end(),
		[](const Sales_data& a, const Sales_data& b) {
			return a.isbn() < b.isbn(); });
	for (auto it = salesdatas.cbegin(); it != salesdatas.cend();) {
		auto sameEnd = find_if(it, salesdatas.cend(),
			[it](const Sales_data& a) {	return a.isbn() != it->isbn(); });
		print(cout, accumulate(it, sameEnd, Sales_data(it->isbn())));
		it = sameEnd;
	}
	return 0;
}

33

#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>
using namespace std;

int main(int argc, char** argv) {
	if (argc < 4) {
		cerr << "need 3 arguments:" << endl
			 << "1. input filename (conclude integers)" << endl
			 << "2. output filename1 (odd numbers)" << endl
			 << "3. output filename2 (even numbers)" << endl;
		return -1;
	}
	ifstream input(argv[1]);
	ofstream outOdd(argv[2]), outEven(argv[3]);
	istream_iterator<int> is_iter(input), eof;
	ostream_iterator<int> os_od_it(outOdd, " ");
	ostream_iterator<int> os_ev_it(outEven, "\n");
	vector<int> vec;
	while (is_iter != eof) {
		vec.push_back(*is_iter++);
	}
	for (const int num : vec) {
		if (num % 2)
			os_od_it = num;
		else
			os_ev_it = num;
	}
	return 0;
}

34

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
	vector<int> vec{1, 2, 3};
	for (auto rit = vec.crbegin(); rit != vec.crend(); ++rit)
		cout << *rit << " ";
	cout << endl;
	return 0;
}

35

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
	vector<int> vec{1, 2, 3};
	for (auto it = vec.cend(); it != vec.cbegin();) {
		--it;
		cout << *it << " ";
	}
	cout << endl;
	return 0;
}

36

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
	vector<int> vec{1, 2, 3, 0, 1, 0, 2};
	auto rit = find(vec.rbegin(), vec.rend(), 0);
	if (rit != vec.rend())
		cout << *rit << " " << distance(vec.rbegin(), rit) << endl;
	return 0;
}

37

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
#include <list>
using namespace std;

int main() {
	vector<int> vec;
	list<int> lst;
	for (int i = 0; i < 10; ++i)
		vec.emplace_back(i);
	copy(vec.rbegin() + 3, vec.rbegin() + 8, back_inserter(lst));
	for (auto num : lst)
		cout << num << " ";
	cout << endl;
	return 0;
}

38

迭代器类别支持的操作
输入迭代器== != ++ * ->
输出迭代器++ *
前向迭代器上方所有
双向迭代器上方所有 --
随机访问迭代器上方所有、比较运算符、和整数的加减、两个迭代器的减法、下标运算符

39

list 的是双向迭代器

vector 的是随机访问迭代器

40

copy 的前两个表示范围的参数需要至少是前向迭代器,表示输出的参数至少是输出迭代器

reverse 需要双向迭代器

unique 需要前向迭代器

41

将前两个迭代器指示的范围中的 old_val 都替换为 new_val

将前两个迭代器指示的范围中符合谓词的元素都替换为 new_val

replace 的 copy 版本,替换后不直接将新的范围覆盖在原来的范围上,而是将新的范围输出到 dest 开始的范围去。

同上,replace_if 的 copy 版本

42

#include <iostream>
#include <algorithm>
#include <string>
#include <list>
using namespace std;

void elimDups(list<string>& words) {
	words.sort();
	words.unique();
}

void displayLst(const list<string>& lst) {
	for (auto str : lst)
		cout << str << " ";
	cout << endl;
}

int main() {
	list<string> lst{"ada", "u", "o", "u", "ada"};
	elimDups(lst);
	displayLst(lst);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值