本文答案,部分参考于C++ Primer 习题集
前面章节的习题答案
配套的学习资料
https://www.jianguoyun.com/p/DTK5uJgQldv8CBjKv80D
10.1
代码如下:
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
//我们这里定义为10个数字
const int length = 10;
int main(void) {
vector<int> Array;
for (int i = 0; i < length; ++i) {
int t = 0;
cin >> t;
Array.push_back(t);
}
cout << "请请入你要查找的值:" << endl;
int find = 0;
cin >> find;
cout << "出现次数为:" << count(Array.begin(), Array.end(), find) << endl;
return 0;
}
结果如下:
1 2 3 4 5 6 7 8 9 10
请请入你要查找的值:
2
出现次数为:1
10.2
#include<algorithm>
#include<iostream>
#include<list>
#include<string>
using namespace std;
//我们这里定义为10个数字
const int length = 10;
int main(void) {
list<string> Array;
string a;
for (int i = 0; i < length; ++i) {
cin >> a;
Array.push_back(a);
}
cout << "请请入你要查找的值:" << endl;
string find;
cin >> find;
cout << "出现次数为:" << count(Array.begin(), Array.end(), find) << endl;
return 0;
}
结果如下:
money rich powerful fruitful yield good hard result excelent finally
请请入你要查找的值:
money
出现次数为:1
10.3
#include<iostream>
#include<vector>
#include<numeric> //accumulate需要的头文件
using namespace std;
//我们这里定义为10个数字
const int length = 10;
int main(void) {
int sum = 0;
vector<int> a = {1,2,3,4,5,6,7,8,9,10};
//for (auto i : a) cout << i << endl;
sum=accumulate(a.cbegin(), a.cend(), 0);
printf("%d", sum);
return 0;
}
结果是:
55
10.4
#include<iostream>
#include<vector>
#include<numeric> //accumulate需要的头文件
using namespace std;
//我们这里定义为10个数字
const int length = 10;
int main(void) {
double sum = 0;
vector<double> a = {1.5,2.6,3.5,4.9,5,6,7,8,9,10};
//for (auto i : a) cout << i << endl;
sum=accumulate(a.cbegin(), a.cend(), 0);
printf("%llf", sum);
return 0;
}
小数部分的精度会丢失掉.
例子的结果是
55.000000
正确的结果是
57.500000
10.5(对我来讲有个坑)-指针指向的地址
吐槽,下面贴一下,答案书上的标准答案,然后在解释一下,为什么.
#include<iostream>
#include<string>
#pragma warning(disable:4996)
using namespace std;
int main(void) {
const char* p[] = { "Hello","World","!" };
const char* q[] = { strdup(p[0]),strdup(p[1]),strdup(p[2]) };
const char* r[] = { p[0],p[1],p[2] };
cout << equal(cbegin(p), cend(p), q) << endl; //p和q的地址是不一样的
cout << equal(cbegin(p), cend(p), r) << endl; //p和r的地址是一样的
printf("%d\n%d\n", &(*p[0]), &(*r[0]));
//来判断p的地址和r的地址是一样的吗
printf("%d\n%d\n", &(*p[1]), &(*r[1]));
printf("%d\n%d\n", &(*p[2]), &(*r[2]));
cout << "-----------------------------" << endl;
printf("%d\n%d\n", &(*p[0]), &(*q[0]));
return 0;
}
10.6
#include<iostream>
#include<vector>
using namespace std;
int main(void) {
vector<int> Array;
for (int i = 0; i < 10; ++i) {
Array.push_back(i);
}
fill_n(Array.begin(), Array.size(), 0);
for (auto i : Array) cout << i << endl;
return 0;
}
10.7
(a)是错误的,vec这个vector里面现在是没有空间来容纳lst的.
(b)是错误的.因为,虽然vec在一开始的时候,就通过reserve开辟了10个内存容量.但是这个不是内存空间,具体就是capacity和size的区别.
而且 generic(泛型) algorithm 一般是要有足够的size 大小
(a)正确的如下:
#include<iostream>
#include<vector>
#include<list>
using namespace std;
int main(void) {
vector<int> vec;
list<int> lst;
int i;
while (cin >> i) lst.push_back(i);
copy(lst.cbegin(), lst.cend(),back_inserter(vec));
return 0;
}
因为,copy本身是不改变容器的大小和容量的.
所以,只能通过调用back_insert来改变容器的大小和容量.
这个还有一个要特别注意的点就是.
要特别注意capacity 和size的区别.
贴个地址吧
(b)的正确写法
#include<iostream>
#include<vector>
#include<list>
using namespace std;
int main(void) {
vector<int> vec;
list<int> lst;
int i;
vec.reserve(10);
fill_n(back_inserter(vec), 10, 0);
for (auto i : vec) cout << i << endl;
return 0;
}
10.8
严格来讲,标准库根本不知道有"容器"这个东西,它们只接受迭代器参数,运行于这些迭代器之上.通过这些迭代器来访问元素.
因此,当你传递给普通算法迭代器时,这些迭代器只能顺序访问或随机访问容器中的元素,造成的效果就是算法只能读取元素.改变元素值,移动元素,但无法添加或删除元素.
但当我们传递给算法插入器,例如back_inserter时,由于这类迭代器能调用下层容器的操作来向容器插入元素.造成的算法执行的效果就是向容器中添加了元素.
重点:标准库算法从来不直接操作容器,它们只操作迭代器,从而间接访问容器,能不能插入和删除元素,不在于算法,而在于传递给它们的迭代器是否具有这样的能力
10.9
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
void elimDups(vector<string>& words) {
//先输出一边
for (auto i : words) cout << i << " ";
sort(words.begin(), words.end());
cout << endl;
cout << "\n\n-------------------------------------------------------\n\n" << endl;
for (auto i : words) cout << i << " ";
cout << endl;
auto end_uqe=unique(words.begin(), words.end());
for (auto i = words.begin(); i < end_uqe; ++i) {
cout << *i << " ";
}
words.erase(end_uqe,words.end());
cout << "\n\n-------------------------------------------------------\n\n" << endl;
for (auto i : words) cout << i << " ";
}
int main(void) {
vector<string> words;
words = {
"the",
"quick",
"red",
"fox",
"jumps",
"over",
"the",
"slow",
"red",
"turtle"
};
elimDups(words);
return 0;
}
就是加点输出啦.
10.10
第十章讲的都是泛型算法,泛型泛型.
英文原名叫 generic 就是普通的,普遍的意思.
意思就是这些算法是和我们要操作的类型是无关的.
和类型有关的是迭代器,迭代器里面写了操作类型的代码.
容器只是一个桥梁.
就像vector可以用来操控int 也可以用来操作string一样.
都不是vector来操作的.而且迭代器来操作他们.进行访问.容器只是一个桥梁.
来链接迭代器和数据结构的.
这样就实现了算法和操作的数据结构的分离.提升了编程的效率.
算法是不应该知道容器的存在的
10.11
isShorter我改成cmp了(刷过力扣的都懂)
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
bool cmp(const string& a1, const string& a2) {
return a1.size() < a2.size();
}
void elimDups(vector<string>& words) {
//先输出一边
for (auto i : words) cout << i << " ";
sort(words.begin(), words.end(),cmp);
cout << endl;
cout << "\n\n-------------------------------------------------------\n\n" << endl;
for (auto i : words) cout << i << " ";
cout << endl;
auto end_uqe=unique(words.begin(), words.end());
for (auto i = words.begin(); i < end_uqe; ++i) {
cout << *i << " ";
}
words.erase(end_uqe,words.end());
cout << "\n\n-------------------------------------------------------\n\n" << endl;
for (auto i : words) cout << i << " ";
}
int main(void) {
vector<string> words;
words = {
"the",
"quick",
"red",
"fox",
"jumps",
"over",
"the",
"slow",
"red",
"turtle"
};
elimDups(words);
return 0;
}
10.12
这个C++Primer上写的太复杂了.就离谱.
我自己写了一下.还踩了个坑,就是这题要写你的compareISbn在后面的Sales_data版本中,被写入了头文件中.
这题最后不要直接用.所以我改了个名
代码如下:
#include<iostream>
#include<vector>
#include "Sales_data.h"
#include <algorithm>
using namespace std;
inline bool compareIs(const Sales_data& lhs, const Sales_data& rhs) {
return lhs.isbn() < rhs.isbn();
}
int main(void) {
vector<Sales_data> sds;
Sales_data sd;
sds.push_back(Sales_data("How to Become Rich"));
sds.push_back(Sales_data("C++ Primer"));
sort(sds.begin(), sds.end(),compareIs);
for (auto i : sds) cout << i.isbn() << endl;
return 0;
}
Sales_date等需要的头文件,我发到了云盘哪.有需自取.
10.13
老实讲,这个题目我都没有看懂.还是看看题解吧
#include<iostream>
#include<vector>
#include "Sales_data.h"
#include <algorithm>
using namespace std;
inline void output_words(vector<string>::iterator beg, vector<string>::iterator end) {
for (auto iter = beg; iter != end; iter++) cout << *iter << " ";
cout << endl;
}
bool five_or_more(const string& s1) {
return s1.size() >= 5;
}
int main() {
vector<string>words;
string t;
for (int i = 0; i < 5; ++i) {
cin >> t;
words.push_back(t);
}
output_words(words.begin(), words.end());
auto iter = partition(words.begin(), words.end(), five_or_more);
output_words(words.begin(), iter);
}
改写的代码.
但是还是奇怪partition 里面的内部构造是啥
输出结果和我想的也不是非常的一样.
10.14
#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
int main() {
auto sum =[](const int a, const int b) {return a + b; };
cout << sum(1, 1) << endl;
}
10.15
#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
void add(int a) {
auto sum = [a](const int b) {return a + b; };
cout << sum(2) << endl;
return;
}
int main() {
add(2);
}
10.16
代码过长,就不贴原图了.这里贴一下.照片.
10.17
#include<iostream>
#include<vector>
#include "Sales_data.h"
#include <algorithm>
using namespace std;
int main(void) {
vector<Sales_data> sds;
Sales_data sd;
sds.push_back(Sales_data("How to Become Rich"));
sds.push_back(Sales_data("C++ Primer"));
sort(sds.begin(), sds.end(), [](const Sales_data& lhs, const Sales_data& rhs) {return lhs.isbn() < rhs.isbn(); });
for (auto i : sds) cout << i.isbn() << endl;
return 0;
}
10.18
copy C++ Primer 习题集
10.19
copy
10.20
PS:吐槽,这个谓词的翻译,我是不懂.还是去翻了一下官方文档才看懂了.
贴一下count_if的官方地址
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
bool isPredicate(string a) {
return a.length() > 6 ? true : false;
}
int main(void) {
vector<string> array;
string t;
for (int i = 0; i <5; ++i) {
cin >> t;
array.push_back(t);
}
int count_num=count_if(array.cbegin(), array.cend(), isPredicate);
cout << count_num;
return 0;
}
输入的东西
LotMoney
ManyMoney
RichMan
Loss
Power
结果如下:
3
10.21
代码如下:
这个C++Primer写的蛮简洁的而且好用.
#include<iostream>
#include<algorithm>
using namespace std;
void mutable_lambda(void) {
int i = 5;
auto f = [i]()mutable->bool {
if (i > 0) {
i--;
return false;
}
else
return true;
};
for (int j = 0; j < 6; ++j)
cout << f() << " "; //前五次都是假的,只有最后一次是真的.
cout << endl;
}
int main(void) {
mutable_lambda();
}
10.22
代码如下:
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int sum(vector<string> a) {
int sum = 0;
for (auto i = a.begin(); i != a.end(); ++i) {
if ((*i).length() <= 6)++sum;
}
return sum;
}
int main(void) {
vector<string>a;
string t;
for (int i = 0; i < 5; ++i) {
cin >> t;
a.push_back(t);
}
int result = sum(a);
cout << result;
}
运行结果如下:
RichMan
RichMoney
Money
Power
Women
3
10.23
bind是可变参数的,它接受的第一个参数是一个可调用对象.即实际工作函数A,返回供算法使用的新的可调用对象B,若A接受x个参数,则bind的参数个数应该是x+1,即除了A外,其他参数应一一对应A所接受的参数,这些参数中有一部分来自于B( _ n ),另外一些来自于所处函数的局部变量.
10.24
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<functional>
//#include "make_plural.h"
using namespace std;
using namespace std::placeholders;
bool check_size(const string& s, string::size_type sz) {
return s.size() <=sz;
}
void biggies(vector<int>& vc, const string& s) {
//查找第一个大于等于s长度的数值
//find_if vc.begin()和vc.end()代表的啥,不解释了.
//重点是bind代表的啥.
//_1是参数的列表可调用对象,也就是find_if本身的参数.s就是s本身,
//s和vc传递给check_size来的
auto p = find_if(vc.begin(), vc.end(), bind(check_size, s, _1));
//打印结果
cout << "第" << p - vc.begin() + 1 << "个数" << *p << "大于等于" << s << "的长度" << endl;
}
int main() {
vector<int> vc = { 1,2,3,4,5,6,7,8,9 };
biggies(vc, "Hello");
biggies(vc, "everyone");
biggies(vc, "!");
return 0;
}
第5个数5大于等于Hello的长度
第8个数8大于等于everyone的长度
第1个数1大于等于!的长度
10.25
10.26
插入迭代器又称插入器,本质上是一个迭代器适配器,如前所述.标准库算法为了保证通用性,并不直接操作容器,而是通过迭代器来访问容器元素,因此,算法不具备直接插入元素的能力,而插入器正是帮助算法实现向容器插入元素的机制.
除了back_inserter 标准库还提供了另外两种插入器, front_inserter.和insert 三者的差异在于如何向容器插入元素,back_inserter调用push_back,front_inserter则调用insert 显然,这也决定了他们插入元素位置的不同.back_inserter总是插入到容器尾元素之后,front_inserter总是插入到容器首元素之前,而inserter则是插入到给定位置 作为inserter的第二个参数传递给它 之前.
因此,需要注意这些.特点带来的元素插入效果的差异,例如,使用front_inserter向容器插入一些元素,元素最终在容器中的顺序与插入顺序相反,但back_inserter和inserter则不会有这个问题.
10.27
#include<iostream>
#include<vector>
#include<list>
#include<string>
#include<algorithm>
using namespace std;
int main() {
vector<int> a;
list<int> b(9);
for (int i = 0; i < 9; ++i) {
a.push_back(i);
}
unique_copy(a.begin(),a.end(), b.begin());
for (auto i : b) cout << i << " ";
return 0;
}
10.28
#include<iostream>
#include<vector>
#include<list>
#include<algorithm>
using namespace std;
int main() {
vector<int> a;
list<int> list1,list2,list3;
for (int i = 1; i <=9; ++i) {
a.push_back(i);
}
//使用front_inserter插入到list中
copy(a.begin(), a.end(), front_inserter(list1));
for (auto i : list1) cout << i << " ";
cout << endl;
//使用back_insert
copy(a.begin(), a.end(), back_inserter(list2));
for (auto i : list2) cout << i << " ";
cout << endl;
//使用insert
copy(a.begin(), a.end(),inserter(list3,list3.begin()));
for (auto i : list3) cout << i << " ";
cout << endl;
return 0;
}
10.29
那个ifstream in 卡了我会.
我改写了一下,改写的地方如下:
ifstream in("E:\\File\\HPY\\Zelda.txt");
全部代码如下:
#include<iostream>
#include<fstream>
#include<vector>
#include<string>
#include<iterator>
#include<algorithm>
using namespace std;
int main(void) {
ifstream in("E:\\File\\HPY\\Zelda.txt");
if (!in) {
cout << "打卡输入文件失败!" << endl;
exit(1);
}
//创建流迭代器从文件读入字符串
istream_iterator<string> in_iter(in);
//尾后迭代器
istream_iterator<string> eof;
vector<string> words;
while (in_iter != eof) words.push_back(*in_iter++);
for (auto word:words) cout << word << " ";
cout << endl;
return 0;
}
10.30
#include<iostream>
#include<fstream>
#include<vector>
#include<string>
#include<iterator>
#include<algorithm>
using namespace std;
int main(void) {
//in 是我们读入的数据,eof就是尾后迭代器
istream_iterator<int> in(cin), eof;
vector<int> vec;
while (in != eof) vec.push_back(*in++);
sort(vec.begin(), vec.end());
ostream_iterator<int> out_iter(cout, " ");
copy(vec.begin(), vec.end(), out_iter);
return 0;
}
输入输出如下:
-1 2 3 -4 5 -2 3 4 6 10
^Z
-4 -2 -1 2 3 3 4 5 6 10
10.31
我就改了一行代码:
unique_copy(vec.begin(), vec.end(), out_iter);
代码如下:
#include<iostream>
#include<fstream>
#include<vector>
#include<string>
#include<iterator>
#include<algorithm>
using namespace std;
int main(void) {
//in 是我们读入的数据,eof就是尾后迭代器
istream_iterator<int> in(cin), eof;
vector<int> vec;
while (in != eof) vec.push_back(*in++);
sort(vec.begin(), vec.end());
ostream_iterator<int> out_iter(cout, " ");
unique_copy(vec.begin(), vec.end(), out_iter);
return 0;
}
10.32
10.33
10.34
#include<iostream>
#include<vector>
using namespace std;
int main(void) {
vector<int> array;
for (int i = 0; i < 5; ++i) array.push_back(i);
for (auto i = array.crbegin(); i < array.crend(); ++i) {
cout << *i << " ";
}
cout << endl;
return 0;
}
10.35
#include<iostream>
#include<vector>
using namespace std;
int main(void) {
vector<int> array;
for (int i = 0; i < 5; ++i) array.push_back(i);
for (auto i = array.end()-1; i!= array.begin(); --i) {
cout << *i << " ";
}
cout << *array.begin() << " ";
cout << endl;
return 0;
}
10.36
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
int main(void) {
list<int> array;
for (int i = 0; i < 10; ++i) {
int t;
cin >> t;
array.push_back(t);
}
auto it=find(array.cbegin(), array.cend(), 0);
cout << *it << endl;
return 0;
}
10.37
#include<iostream>
#include<list>
#include<vector>
#include<algorithm>
using namespace std;
int main(void) {
vector<int> array;
list<int> result;
for (int i = 0; i < 10; ++i) {
int t;
cin >> t;
array.push_back(t);
}
for (auto i = array.rbegin() + 3; i <= array.rend() - 3; ++i) {
result.push_back(*i);
}
for (auto i : result) cout << i << " ";
return 0;
}
输入和输出结果
1 2 3 4 5 6 7 8 9 10
7 6 5 4 3
10.38
重复答案,就是双向迭代器那些东西.
10.39
list是双向,list是不支持类数组的访问方式的,
但是vector可以.
10.40
copy 至少是输入
reverser 至少是双向.因为需要反向
unique 至少是前向迭代器
10.41
1 将范围[beg,end)的间值等于old_val的元素替换为new_val
2 将范围[beg,end)的间值满足谓词pred的元素替换为new_val
3 将范围[beg,end)的间值的元素拷贝到目的序列dest中,将其中值等于old_val的元素替换为new_val
4 将范围[beg,end)的间的元素拷贝到目的序列dest中,将其中满足谓词pred的元素替换为new_val
10.42
#include<iostream>
#include<list>
#include<vector>
#include<algorithm>
using namespace std;
void eliDups(list<string>& words) {
words.sort();
words.unique();
}
int main(void) {
list<string> test;
for (int i = 0; i < 10; ++i) {
string t;
cin >> t;
test.push_back(t);
}
eliDups(test);
for (auto i : test) cout << i << endl;
return 0;
}
输入输出如下:
Rich Man Money Link Love Zelda Month
Link 2020 Better
2020
Better
Link
Love
Man
Money
Month
Rich
Zelda
如果这篇文章对你有张帮助的话,可以用你高贵的小手给我点一个免费的赞吗
相信我,你也能变成光.
如果你有任何建议,或者是发现了我的错误,欢迎评论留言指出.