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
,_2
等 std::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;
}