C++ Primer(第五版)|練習題答案與解析(第十章:泛型算法)
本博客主要記錄C++ Primer(第五版)中的練習題答案與解析。
參考:C++ Primer
C++ Primer
練習題10.1
頭文件algorithm中定義了一個名爲count的函數,它類似find,接受一對迭代器和一個值作爲參數。count返回給定值在序列中出現的次數。編寫程序,讀取int序列存入vector中,打印有多少個元素的值等於給定值。
練習題10.2
重做上一題,但讀取string序列存入list中。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <list>
int main()
{
// 練習題10.1
std::vector<int> v = { 1, 6, 3, 6, 5, 6, 7, 8, 9 };
std::cout << "ex 10.01: " << std::count(v.cbegin(), v.cend(), 6) << std::endl;
// 練習題10.2
std::list<std::string> l = { "aa", "bb", "aa", "cc" };
std::cout << "ex 10.02: " << std::count(l.cbegin(), l.cend(), "aa") << std::endl;
return 0;
}
測試:
ex 10.01: 3
ex 10.02: 2
練習題10.3
用accumulate求一個vector中的元素之和。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
int main()
{
int ia[] = {1, 2, 2, 4, 3, 4, 2};
vector<int> ivec(ia, ia+7);
int sum = accumulate(ivec.begin(), ivec.end(), 0);
cout << sum << endl;
return 0;
}
輸出:18
練習題10.4
假定v是一個vector, 那麼調用accumulate(v.cbegin(), v.cend(), 0)有何錯誤(如果存在)?
因爲第三個參數是0,則編譯器會認爲其是一個int類型。最後的求和會損失精度。
練習題10.5
在本節對名冊(roster)調用equal的例子中,如果兩個名冊中保存的都是c風格字符串而不是string,會發生什麼?
引用牛客網的回答:
equal使用運算符比較兩個序列中的元素。string類重載了,可比較兩個字符串是否長度相等且其中元素對位相等。而C風格字符串本質是char類型,用==比較兩個char對象,只是檢查兩個指針值是否相等,即地址是否相等,而不會比較其中字符是否相同。所以,只有當兩個序列中的指針都指向相同的地址時;
equal纔會返回true。否則,即使字符串內容完全相同,也會返回false。
如下面的程序,q中的每個字符串是p中字符串的拷貝,雖然內容相同,但是不同對象指向不同地址,因此equal判定它們不等。而r中每個指針都是p中指針的拷貝,指向相同的地址,因此equal判定它們相等。
練習題10.6
編寫程序,使用fill_n將一個序列中的int都設置爲0。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> vec{ 0, 1, 2, 3, 4, 5, 6};
fill_n(vec.begin(), vec.size(), 0);
for (auto i : vec)
cout << i << " ";
cout << endl;
}
測試:0 0 0 0 0 0 0
練習題10.7
下面程序是否有錯誤?如果有,請改正。
(a)
vector<int> vec; list<int> lst; int i;
while (cin >> i)
lst.push_back(i);
copy(lst.cbegin(), lst.cend(), vec.begin()
有錯誤,其中vec的大小爲0,如果直接將lst複製到vec,將會發生災難性的錯誤(P341)。
需要在copy前加上:vec.resize(lst.size());
(b)
vector<int> vec;
vec.reserve(10); // 有誤
fill_n(vec.begin(), 10, 0);
其中reserve是改變容器容量的,並不能改變容器大小。應改爲resize。
練習題10.8
本節提到過,標準庫算法不會改變他們所操作的容器的大小。爲什麼使用back_inserter不會使這一斷言失效?
傳遞的參數是back_inserter返回的迭代器,每次賦值都會調用push_back。通過插入迭代器來插入元素,使用的是迭代器,而不是算法插入(P341)。
練習題10.9
實現你自己的elimDups。測試你的程序,分別在讀取輸入後、調用unique後以及調用erase後打印vector的內容(P343有例程)
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
void elimDups(vector<string>& words)
{
sort(words.begin(), words.end());
// 按字典序重排words
for (auto i : words) {
cout << i << " ";
}
cout << endl;
auto end_unique = unique(words.begin(), words.end());
// 重排,使每個單詞只出現一次,指向不重複區域之後的迭代器。
for (auto i : words) {
cout << i << " ";
}
cout << endl;
words.erase(end_unique, words.end());
for (auto i : words) {
cout << i << " ";
}
cout << endl;
}
int main()
{
vector<string> vs{ "a", "b", "a", "b", "e", "f", "a" };
elimDups(vs);
return 0;
}
測試:
a a a b b e f
a b e f b a a
a b e f
練習題10.10
你認爲算法不改變容器大小的原因是什麼?
標準庫算法是對迭代器而不是容器進行操作。因此,算法不能(直接)添加或刪除元素(P343)。
練習題10.11
編寫程序,使用stable_sort和isShorter將傳遞給你的elimDups版本的vector排序。打印vector的內容,驗證你的程序的正確性。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
void printWordVec(vector<string>& words){
for(const auto& word:words )
cout<<word<<" ";
}
void elimDups(vector<string>& words)
{
sort(words.begin(), words.end());
// 按字典序重排words
auto end_unique = unique(words.begin(), words.end());
// 重排,使每個單詞只出現一次,指向不重複區域之後的迭代器。
words.erase(end_unique, words.end());
printWordVec(words);
}
bool isShorter(const string &s1, const string &s2){
return s1.size() < s2.size();
}
int main()
{
vector<string> vs{ "the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle" };
printWordVec(vs);
cout<<"\nuse elimDups: "<<endl;
elimDups(vs);
// 使用 isShorter
sort(vs.begin(), vs.end(), isShorter);
cout<<"\nuse isShorter: "<<endl;
printWordVec(vs);
// 使用 stable_sort
stable_sort(vs.begin(), vs.end(), isShorter);
cout<<"\nuse stable_sort: "<<endl;
printWordVec(vs);
return 0;
}
測試:
the quick red fox jumps over the slow red turtle
use elimDups:
fox jumps over quick red slow the turtle
use isShorter:
fox red the over slow jumps quick turtle
use stable_sort:
fox red the over slow jumps quick turtle
練習題10.12
編寫程序,使用stable_sort和isShorter將傳遞給你的elimDups版本的vector排序。打印vector的內容,驗證你的程序的正確性。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include "Sales_data.h" // Sales_data class.
using namespace std;
inline bool compareIsbn(const Sales_data &sd1, const Sales_data &sd2)
{
return sd1.isbn().size() < sd2.isbn().size();
}
int main()
{
Sales_data d1("aa"), d2("aaaa"), d3("aaa"), d4("z"), d5("aaaaz");
vector<Sales_data> v{ d1, d2, d3, d4, d5 };
// 迭代器所指向的元素必須與謂詞的參數匹配
sort(v.begin(), v.end(), compareIsbn);
for(const auto &element : v)
cout << element.isbn() << " ";
return 0;
}
練習題10.13
標準庫定義了名爲partition的算法,它接受一個謂詞,對容器內容進行劃分,使得謂詞爲true的值對排在容器的前半部分,而使謂詞爲false的值會排在後半部分。算法返回一個迭代器,指向最後一個使謂詞爲true的元素之後的位置。編寫函數,接受一個string,返回一個bool值,指出string是否有5個或更多字符。使用此函數劃分words。打印出長度大於等於5的元素。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
bool predicate(const string &s)
{
return s.size() >= 5;
}
int main()
{
auto v = vector<string>{ "a", "abc", "aaabbb", "aaabbbc", "aaabbbccc", "aaabbbe" };
auto pivot = partition(v.begin(), v.end(), predicate);
for (auto it = v.cbegin(); it != pivot; ++it)
cout << *it << " ";
return 0;
}
測試:aaabbbe aaabbbccc aaabbb aaabbbc
練習題10.14
編寫一個lambda,接受兩個int,返回它們的和。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
auto sum = [](const int a, const int b) { return a+b; };
cout<<sum(10,5);
return 0;
}
測試:15
練習題10.15
編寫一個lambda,捕獲它所在函數的int,並接受一個int參數。lambda應該返回捕獲的int和int參數的和。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int a = 10;
auto sum = [a](const int b) { return a+b; };
cout<<sum(5);
return 0;
}
測試:15
練習題10.16
使用lambda編寫你自己版本的biggies。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
// 來自練習題 10.9
void elimDups(vector<string>& words)
{
sort(words.begin(), words.end());
// 按字典序重排words
auto end_unique = unique(words.begin(), words.end());
// 重排,使每個單詞只出現一次,指向不重複區域之後的迭代器。
words.erase(end_unique, words.end());
}
void biggies(vector<string> &vs, size_t sz)
{
elimDups(vs);//將words按字典順序排序,刪除重複單詞。
// 按大小排序,但保持相同大小的字母順序。
stable_sort(vs.begin(), vs.end(), [](string const& lhs, string const& rhs){
return lhs.size() < rhs.size();
});
// 獲取一個迭代器,指向第一個滿足 size() >= sz的元素
auto wc = find_if(vs.begin(), vs.end(), [sz](string const& s){
return s.size() >= sz;
});
// 打印
for_each(wc, vs.end(), [](const string &s){
cout << s << " ";
});
}
int main()
{
vector<string> v
{
"the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle"
};
cout << "ex10.16: ";
biggies(v, 4);
cout << endl;
return 0;
}
測試:ex10.16: over slow jumps quick turtle
練習題10.17
重新10.12的程序,在對sort的調用中使用lambda來代替函數compareIsbn。
將其中sort一行改爲:sort(sale_vec.begin(), sale_vec.end(), [](const Sales_data& sale1, const Sales_data& sale2) { return sale1.isbn().size() > sale2.isbn().size(); });
練習題10.18
重寫biggies,用partition代替find_if。我們在10.13中介紹了partition算法。
練習題10.19
用stable_partition重寫前一題的程序,與stable_sort類似,在劃分後的序列中維持原有元素的順序。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
// 來自練習題 10.9
void elimDups(vector<string>& words)
{
sort(words.begin(), words.end());
// 按字典序重排words
auto end_unique = unique(words.begin(), words.end());
// 重排,使每個單詞只出現一次,指向不重複區域之後的迭代器。
words.erase(end_unique, words.end());
}
// ex10.18
void biggies_partition(vector<string> &vs, size_t sz)
{
elimDups(vs);
auto pivot = partition(vs.begin(), vs.end(), [sz](const string &s){
return s.size() >= sz;}
);
for(auto it = vs.cbegin(); it != pivot; ++it)
cout << *it << " ";
}
// ex10.19
void biggies_stable_partition(vector<string> &vs, size_t sz)
{
elimDups(vs);
auto pivot = stable_partition(vs.begin(), vs.end(), [sz](const string& s){
return s.size() >= sz;
});
for(auto it = vs.cbegin(); it != pivot; ++it)
cout << *it << " ";
}
int main()
{
// 練習題10.18
vector<string> v{
"the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle"
};
cout << "ex10.18: ";
vector<string> v1(v);
biggies_partition(v1, 4);
cout << endl;
// 練習題10.19
cout << "ex10.19: ";
vector<string> v2(v);
biggies_stable_partition(v2, 4);
cout << endl;
return 0;
}
測試:
ex10.18: turtle jumps over quick slow
ex10.19: jumps over quick slow turtle
練習題10.20
標準庫定義了一個名爲count_if的算法。類似find_if,此函數接受一對迭代器,表示一個輸入範圍,還接受一個謂詞,會對輸入範圍中每個元素執行。count_if返回一個計數值,表示謂詞有多少次爲真。使用count_if重寫我們程序中統計有多少單詞長度超過6的部分。
練習題10.21
編寫一個lambda,捕獲一個局部int變量,並遞減變量值,直至它變爲0.一旦變量變爲0,再調用lambda應該不再遞減變量.lambda應該返回一個bool值,指出捕獲的變量是否爲0.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
// 練習題 10.20
size_t bigerThan6(vector<string> const& v)
{
return count_if(v.cbegin(), v.cend(), [](string const& s){
return s.size() > 6;
});
}
int main()
{
// 10.20
vector<string> v{
"the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle", "moreThanSix"
};
cout << "ex10.20: " << bigerThan6(v) << endl;
// 練習題10.21
int i = 6;
auto check_and_decrement = [&i]() { return i > 0 ? !--i : !i; };//使用&引用
cout << "ex10.21: ";
while(!check_and_decrement())
cout << i << " ";
return 0;
}
測試:
ex10.20: 1
ex10.21: 5 4 3 2 1
練習題10.22
重寫統計長度小於等於6的單詞數量的程序,使用函數代替lambda.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
bool isStrShorterThan6(string& str)
{
return str.size() < 6;
}
int main()
{
vector<string> v{
"the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle", "moreThanSix"
};
int cnt = count_if(v.begin(), v.end(), isStrShorterThan6);
cout << cnt << endl;
return 0;
}
測試:9
練習題10.23
bind接受幾個參數?
定義:auto newCallable = bind(callable, arg_list);
其中,arg_list是一個用逗號分隔的參數列表,對應給callable的參數。當我們調用newCallable時,實際會調用callable。
arg_list中的參數可能會包含形如_n的名字,其中n是一個整數。這些參數是“佔位符”,表示newCallable的參數,它們佔據了傳遞給newCallable的參數位置。
練習題10.24
給定一個string, 使用bind和check_size在一個int的vector中查找第一個大於string長度的值.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
bool check_size(string const& str, size_t sz)
{
return str.size() < sz;
}
int main()
{
vector<int> vec{ 0, 1, 2, 3, 4, 5, 6, 7 };
string str1("12345689");
string str2("123");
auto result = find_if(vec.begin(), vec.end(), bind(check_size, str1, std::placeholders::_1));
if (result != vec.end())
cout << *result << endl;
else
cout << "Not found" << endl;
result = find_if(vec.begin(), vec.end(), bind(check_size, str2, std::placeholders::_1));
if (result != vec.end())
cout << *result << endl;
else
cout << "Not found" << endl;
return 0;
}
測試:
Not found
4
練習題10.25
在10.3.2節的練習中,編寫了一個使用partition的biggies版本.使用check_size和bind重寫此函數.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
using namespace std::placeholders;//使用了佔位符_1
void printWordVec(vector<string>& words){
for(const auto& word:words )
cout<<word<<" ";
cout<<endl;
}
void elimDups(vector<string>& words)
{
sort(words.begin(), words.end());
// 按字典序重排words
auto end_unique = unique(words.begin(), words.end());
// 重排,使每個單詞只出現一次,指向不重複區域之後的迭代器。
words.erase(end_unique, words.end());
printWordVec(words);
}
bool check_size(const string &s, string::size_type sz)
{
return s.size() >= sz;
}
void biggies(vector<string> &words, vector<string>::size_type sz)
{
elimDups(words);
auto iter = stable_partition(words.begin(), words.end(), bind(check_size, _1, sz));
for_each(words.begin(), iter, [](const string &s){ cout << s << " "; });
}
int main()
{
std::vector<std::string> v{
"the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle"
};
biggies(v, 4);
}
測試:
fox jumps over quick red slow the turtle
jumps over quick slow turtle
練習題10.26
解釋三種插入迭代器的不同之處。
三種迭代器的區別在於元素插入的位置(P358):
back_inserter
:創建一個使用push_back
的迭代器。front_insert
:創建一個使用push_front
的迭代器。inserter
:創建一個使用insert
的迭代器。此函數接受第二個參數,元素將被插入到給定迭代器所表示的元素之前。
練習題10.27
處理unique之外,標準庫還定義了名爲unique_copy的函數,它接受第三個迭代器,表示拷貝不重複元素的目的位置。編寫一個程序,使用unique_copy將一個vector中不重複的元素拷貝到一個初始化爲空的list中。
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <list>
#include <iterator>
using namespace std;
int main()
{
vector<string> svec = {"the", "the", "the", "fox", "jumps", "over", "the", "slow", "congratulate", "turtle"};
list<string> slist(12);//如果不使用插入迭代器需要初始化空間
unique_copy(svec.begin(), svec.end(), slist.begin());//重複元素必須相鄰
for (auto i : slist) {
cout << i << " ";
}
cout << endl;
vector<int> vec{ 1, 2, 1, 3, 5, 5, 7, 7, 9 };
list<int> lst;
unique_copy(vec.begin(), vec.end(), back_inserter(lst));
for (auto i : lst)
cout << i << " ";
cout << endl;
}
測試:
the fox jumps over the slow congratulate turtle
1 2 1 3 5 7 9
練習題10.28
處理unique之外,標準庫還定義了名爲unique_copy的函數,它接受第三個迭代器,表示拷貝不重複元素的目的位置。編寫一個程序,使用unique_copy將一個vector中不重複的元素拷貝到一個初始化爲空的list中。
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <list>
#include <iterator>
using namespace std;
void printNum(list<int>& words){
for(const auto& word:words )
cout<<word<<" ";
cout<<endl;
}
int main()
{
std::vector<int> vec{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
// 使用 inserter
list<int> lst1;
copy(vec.cbegin(), vec.cend(), inserter(lst1, lst1.begin()));
printNum(lst1);
// 使用 back_inserter
list<int> lit2;
copy(vec.cbegin(), vec.cend(), back_inserter(lit2));
printNum(lit2);
// 使用 front_inserter
list<int> lst3;
copy(vec.cbegin(), vec.cend(), front_inserter(lst3));
printNum(lst3);
}
測試:
1 2 3 4 5 6 7 8 9 10 11
1 2 3 4 5 6 7 8 9 10 11
11 10 9 8 7 6 5 4 3 2 1
練習題10.29
編寫程序,使用流迭代器讀取一個文本文件,存入一個vector中的string裏。
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <iterator>
using namespace std;
int main()
{
ifstream ifs("test.txt");
istream_iterator<string> in(ifs), eof;
vector<string> vec;
copy(in, eof, back_inserter(vec));
// 輸出
copy(vec.cbegin(), vec.cend(), ostream_iterator<string>(cout, "\n"));
}
測試:
This
is
a
C++
test
練習題10.30
使用流迭代器、sort和copy從標準輸入讀取一個整數序列,將其排序,並將結果寫到標準輸出。
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
istream_iterator<int> in_iter(cin);//輸入
istream_iterator<int> eof;//空
vector<int> ivec;
ostream_iterator<int> out_iter(cout, " ");//輸出
while (in_iter != eof) {//當不等於空時
ivec.push_back(*in_iter++);
}
sort(ivec.begin(), ivec.end());
copy(ivec.begin(), ivec.end(), out_iter);
cout << endl;
}
測試:
5 2 6 9 1 3
^Z
1 2 3 5 6 9
練習題10.31
修改前一題的程序,使其只打印不重複的元素。你的程序應使用unique_copy。
只需要將上題copy替換:unique_copy(ivec.begin(), ivec.end(), out_iter);
練習題10.32
重寫1.6節的書店程序,使用一個vector保存交易記錄,使用不同算法完成處理。使用sort和10.3.1節中的compareIsbn函數來排序交易記錄,然後使用find和accumulate求和。
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <numeric>
#include "Sales_item.h"
using namespace std;
int main()
{
istream_iterator<Sales_item> in_iter(cin), in_eof;
vector<Sales_item> vec;
while (in_iter != in_eof)
vec.push_back(*in_iter++);
sort(vec.begin(), vec.end(), compareIsbn);
for (auto beg = vec.cbegin(), end = beg; beg != vec.cend(); beg = end) {
end = find_if(beg, vec.cend(), [beg](const Sales_item &item){ return item.isbn() != beg->isbn(); });
cout << accumulate(beg, end, Sales_item(beg->isbn())) << endl;
}
}
練習題10.33
編寫程序,接受三個參數:一個輸入文件和兩個輸出文件的文件名。輸入文件保存的應該是整數。使用istream_iterator讀取輸入文件。使用ostream_iterator將奇數寫入第一個輸出文件,每個值之後都跟一個空格。將偶數寫入第二個輸出文件,每個值都獨佔一行。
#include <fstream>
#include <iterator>
#include <algorithm>
using namespace std;
int main()
{
ifstream ifs("input.txt");
ofstream ofs_odd("odd.txt"), ofs_even("even.txt");
istream_iterator<int> in(ifs), in_eof;
ostream_iterator<int> out_odd(ofs_odd, " "), out_even(ofs_even, " ");
for_each(in, in_eof, [&out_odd, &out_even](const int i){
*(i & 0x1 ? out_odd : out_even)++ = i;//奇偶判斷
});
return 0;
}
練習題10.34
使用reverse_iterator逆序打印一個vector。
練習題10.35
使用普通迭代器逆序打印一個vector。
練習題10.36
使用find在一個int的list中查找最後一個值爲0的元素。
練習題10.37
給定一個包含10個元素的vector,將位置3到7之間的元素按逆序拷貝到一個list中。
#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <iterator>
using namespace std;
int main()
{
vector<int> vec = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
// 練習題10.34
cout<<"ex10.34: ";
for (auto rit = vec.crbegin(); rit != vec.crend(); ++rit)
cout << *rit << " ";
cout << endl;
// 練習題10.35
cout<<"ex10.35: ";
for (auto it = prev(vec.cend()); true; --it) {
cout << *it << " ";
if (it == vec.cbegin()) break;
}
cout << endl;
// 練習題10.36
cout<<"ex10.36: ";
list<int> lst = { 1, 2, 3, 4, 0, 5, 6 };
auto found_0 = find(lst.crbegin(), lst.crend(), 0);
cout << distance(found_0, lst.crend()) << endl;
// 練習題10.37
list<int> ret_lst(8 - 3);
copy(vec.cbegin() + 3, vec.cbegin() + 8, ret_lst.rbegin());
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
// ^ ^
// rend rbegin
// @note: copy將範圍[first, last]複製到結果中。
// 因此,這裏的參數表示:
// [7 6 5 4 3 2)
// ^ 這只是指定,但不包括。
cout<<"ex10.37: ";
for (auto i : ret_lst) cout << i << " ";
cout << endl;
}
測試:
ex10.34: 9 8 7 6 5 4 3 2 1 0
ex10.35: 9 8 7 6 5 4 3 2 1 0
ex10.36: 5
ex10.37: 7 6 5 4 3
練習題10.38
列出5個迭代器類別,以及每類迭代器所支持的操作。
P366
- 輸入迭代器:只讀,不寫;單遍掃描,只能遞增。支持==、!=、++、*、->
- 輸出迭代器:只寫,不讀;單遍掃描,只能遞增。支持++、*
- 前向迭代器:可讀寫,多邊掃描,只能遞增。支持輸入輸出迭代器的所有操作。
- 雙向迭代器:可讀寫,多遍掃描,可遞增遞減。除支持前向迭代器的操作外,還支持–。
- 隨機訪問迭代器:可讀寫,多遍掃描,支持全部迭代器運算。除支持雙向操作外,還支持<、<=、>、>=、+、+=、-、-=、迭代器的減法運算符(-)、下標運算符(iter[n], *(iter[n]) )。
練習題10.39
list上的迭代器屬於哪類?vector呢?
- list的迭代器屬於雙向迭代器。
- vector屬於隨機訪問迭代器。
練習題10.40
你認爲copy要求哪類迭代器?reverse和unique呢?
-
copy前兩個參數要求輸入迭代器,最後一個參數要求輸出迭代器。
-
reverse要求雙向迭代器。
-
unique要求前向迭代器。
練習題10.41
僅根據算法和參數的名字,描述下面每個標準庫算法執行什麼操作:
(a)replace(beg, end, old_val, new_val);
替換操作,從beg到end,把old_val替換成new_val
(b)replace_if(beg, end, pred, new_val);
替換操作,從beg到end,如果滿足pred條件,就把old_val替換成new_val
(c)replace_copy(beg, end, dest, old_val, new_val);
替換拷貝操作,從beg到end,把old_val替換成new_val,並拷貝至dest
(d)replace_copy_if(beg, end, dest, pred, new_val);
替換拷貝操作,從beg到end,如果滿足pred條件,就把old_val替換成new_val,並拷貝至dest
練習題10.42
使用list代替vector重新實現10.2.3節中的去除重複單詞的程序。
#include <iostream>
#include <string>
#include <list>
using namespace std;
void elimDups(list<string> &words)
{
words.sort();
words.unique();
for(const auto word : words)
cout<<word<<" ";
}
int main()
{
list<string> l = { "aa", "bb", "cc", "aa", "aasss", "aa", "cc" };
elimDups(l);
}
測試:aa aasss bb cc