Exercise 10.1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
int main()
{
  int i;
  vector<int> vi;
  while(cin >> i)
    vi.push_back(i);
  cout << "Specify a number: " << endl;
  cin.clear();
  cin >> i;
  cout << "There are " << count(vi.begin(), vi.end(), i)
       << " count of " << i << " in input numbers" << endl;
}

Exercise 10.2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
int main()
{
  string i;
  list<string> ls;
  while(cin >> i)
    ls.push_back(i);
  cout << "Specify a string: " << endl;
  cin.clear();
  cin >> i;
  cout << "There are " << count(ls.begin(), ls.end(), i)
       << " count of " << i << " in input strings" << endl;
}

Exercise 10.3

1
2
3
4
5
6
7
int main()
{
  vector<int> vi = {0, 1, 2, 3, 4, 5};
  int sum = accumulate(vi.begin(), vi.end(), 0);
  cout << sum << endl;
}

Exercise 10.4

1
2
3
4
5
6
7
8
9
int main()
{
  vector<double> vi = {0.0, 1.1, 2.2, 3.3, 4.4, 5.5};
  double sum = accumulate(vi.begin(), vi.end(), 0); // sum is 15.0
  // element in vi is transformmed to type int, precision loss
  // that is not good
  cout << sum << endl;
}

Exercise 10.5

1
2
3
// '==' operator for two C type strings compares the pointers point to them;
// which is not expected.

Exercise 10.6

1
2
3
4
5
6
7
8
int main()
{
  vector<int> vi = {1, 2, 3, 4, 5, 6};
  fill_n(vi.begin(), vi.size(), 0);
  for(const auto &i : vi)
    cout << i << endl;
}

Exercise 10.7

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// a: illegal
// b: illegal
int main()
{
  // a
  vector<int> vec;
  list<int> lst;
  int i;
  while(cin >> i)
    lst.push_back(i);
  vec.assign(lst.size(), 0);
  copy(lst.cbegin(), lst.cend(), vec.begin());
  for(const auto &i : vec) cout << i << endl;
  // b
  vector<int> vec2;
  vec2.reserve(10);	     // vec2 still has no elements, it is empty
  vec2.assign(10, 1);		// without it, fill_n would output undefined result, see the example illustrated in P341
  fill_n(vec2.begin(), 10, 0);
  for(const auto &i : vec2) cout << i << endl;
}

Exercise 10.8

1
2
3
4
// Standard library algorithm just assign values through insert iterator:
// *insert_iterator = some_value
// job of inserting an element and then changing the size of container is done by insert iterator, there is none of algorithm's business

Exercise 10.9

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
void elimDups(vector<string> &words)
{
  for(const auto &s : words) cout << s << endl;
  sort(words.begin(), words.end());
  for(const auto &s : words) cout << s << endl;
  auto end_unique = unique(words.begin(), words.end());
  for(const auto &s : words) cout << s << endl;
  words.erase(end_unique, words.end());
  for(const auto &s : words) cout << s << endl;
}
int main()
{
  vector<string> vs =
    {"the", "time", "is", "near", "near", "the", "sunrise"};
  elimDups(vs);
}

Exercise 10.10

1
2
// Algorithm operates on iterators, not containers, it could change the value pointed by iterator(if it is not const iterator), but it is not capable of deleting or inserting, which are functions based on container itself(container.erase(...), container.inser(...)...).

Exercise 10.11

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
bool isShorter(const string &s1, const string &s2)
{
  return s1.size() < s2.size();
}
void elimDups(vector<string> &words)
{
  sort(words.begin(), words.end());
  auto end_unique = unique(words.begin(), words.end());
  words.erase(end_unique, words.end());
}
int main()
{
  vector<string> vs =
    {"the", "time", "is", "near", "near", "the", "great", "sunrise"};
  elimDups(vs);
  stable_sort(vs.begin(), vs.end(), isShorter);
  for(const auto &s : vs) cout << s << endl;
}

Exercise 10.12

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
bool compareIsbn(Sales_data &d1, Sales_data &d2)
{
  return d1.isbn() < d2.isbn();
}
int main()
{
  vector<Sales_data> vs;
  while(cin)
    {
      Sales_data item;
      read(cin,item);
      vs.push_back(item);
    }
  sort(vs.begin(), vs.end(), compareIsbn);
}

Exercise 10.13

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
bool greater_than_five(const string &s)
{
  return s.size() >= 5;
}
int main()
{
  vector<string> vs =
    {"hello", "world", "is", "everything", "all", "right"};
  auto iter = partition(vs.begin(), vs.end(), greater_than_five);
  for(auto beg = vs.begin(); beg != iter; ++beg)
    cout << *beg << endl;
}

Exercise 10.14

1
2
// [](int i, int j) {return i + i;}

Exercise 10.15

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int sample(int i)
{
  int x = 5;
  return ([x](int n){return x + n;})(i);
}
int main()
{
  cout << sample(2) << endl;
}

Exercise 10.16

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void elimDups(vector<string> &words)
{
  sort(words.begin(), words.end());
  auto end_unique = unique(words.begin(), words.end());
  words.erase(end_unique, words.end());
}
void biggies(vector<string> &words, vector<string>::size_type sz)
{
  elimDups(words);
  stable_sort(words.begin(), words.end(),
	    [](const string &word1, const string &word2)
	    {return word1.size() < word2.size();});
  auto iter = find_if(words.begin(), words.end(),
		    [sz](const string &word)
		    {return word.size() >= sz;});
  auto count = words.end() - iter;
  cout << count << " words" << endl;
  for_each(iter, words.end(), [](const string &s){cout << s << endl;});
}
int main()
{
  vector<string> vs =
    {"the", "time", "is", "near", "near", "the", "sunrise"};
  biggies(vs, 4);
}

Exercise 10.17

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
int main()
{
  vector<Sales_data> vs;
  while(cin)
    {
      Sales_data item;
      read(cin,item);
      vs.push_back(item);
    }
  sort(vs.begin(), vs.end(),
       [](Sales_data &item1, Sales_data &item2)
       {return item1.isbn() < item2.isbn();});
}

Exercise 10.18

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void elimDups(vector<string> &words)
{
  sort(words.begin(), words.end());
  auto end_unique = unique(words.begin(), words.end());
  words.erase(end_unique, words.end());
}
void biggies(vector<string> &words, vector<string>::size_type sz)
{
  elimDups(words);
  stable_sort(words.begin(), words.end(),
	    [](const string &word1, const string &word2)
	    {return word1.size() < word2.size();});
  auto iter = partition(words.begin(), words.end(),
		    [sz](const string &word)
		    {return word.size() >= sz;});
  auto count = iter - words.begin();
  cout << count << " words" << endl;
  for_each(words.begin(), iter, [](const string &s){cout << s << endl;});
}
int main()
{
  vector<string> vs =
    {"the", "time", "is", "near", "near", "the", "sunrise"};
  biggies(vs, 4);
}

Exercise 10.19

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void elimDups(vector<string> &words)
{
  sort(words.begin(), words.end());
  auto end_unique = unique(words.begin(), words.end());
  words.erase(end_unique, words.end());
}
void biggies(vector<string> &words, vector<string>::size_type sz)
{
  elimDups(words);
  stable_sort(words.begin(), words.end(),
	    [](const string &word1, const string &word2)
	    {return word1.size() < word2.size();});
  auto iter = stable_partition(words.begin(), words.end(),
		    [sz](const string &word)
		    {return word.size() >= sz;});
  auto count = iter - words.begin();
  cout << count << " words" << endl;
  for_each(words.begin(), iter, [](const string &s){cout << s << endl;});
}
int main()
{
  vector<string> vs =
    {"the", "time", "is", "near", "near", "the", "sunrise"};
  biggies(vs, 4);
}

Exercise 10.20

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void elimDups(vector<string> &words)
{
  sort(words.begin(), words.end());
  auto end_unique = unique(words.begin(), words.end());
  words.erase(end_unique, words.end());
}
void count_biggies(vector<string> &words, vector<string>::size_type sz)
{
  elimDups(words);
  stable_sort(words.begin(), words.end(),
	    [](const string &word1, const string &word2)
	    {return word1.size() < word2.size();});
  auto count = count_if(words.begin(), words.end(),
		      [sz](const string &word)
		      {return word.size() >= sz;});
  cout << count << " words" << endl;
}
int main()
{
  vector<string> vs =
    {"the", "time", "is", "near", "near", "the", "sunrise"};
  count_biggies(vs, 6);
}

Exercise 10.21

1
2
3
4
5
6
7
8
9
int main()
{
  int j = 4;
  auto f = [j] () mutable -> bool {int result = j; while(j) --j; return result;};
  cout << f() << endl;
  cout << f() << endl;
  cout << j << endl;
}

Exercise 10.22

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void elimDups(vector<string> &words)
{
  sort(words.begin(), words.end());
  auto end_unique = unique(words.begin(), words.end());
  words.erase(end_unique, words.end());
}
bool is_shorter(const string &s1, const string &s2)
{
  return s1.size() < s2.size();
}
bool compare_sz(const string &s, string::size_type sz)
{
  return s.size() >= sz;
}
void biggies(vector<string> &words, vector<string>::size_type sz)
{
  elimDups(words);
  stable_sort(words.begin(), words.end(), is_shorter);
  auto iter = find_if(words.begin(), words.end(),
		    bind(compare_sz, _1, sz));
  auto count = words.end() - iter;
  cout << count << " words" << endl;
  for_each(iter, words.end(), [](const string &s){cout << s << endl;});
}
int main()
{
  vector<string> vs =
    {"the", "time", "is", "near", "near", "the", "sunrise"};
  biggies(vs, 4);
}

Exercise 10.23

1
2
// bind requires an argument as callable and the rest arguments responded to given callable's arguments.

Exercise 10.24

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
bool check_size(const string &s, string::size_type sz)
{
  return s.size() >= sz;
}
int main()
{
  cout << "Please enter a string: " << endl;
  string s;
  cin >> s;
  vector<int> vi = {1, 2, 3, 4, 5, 6};
  auto iter = stable_partition(vi.begin(), vi.end(),
		    bind(check_size, s, _1));
  if(iter == vi.end()) cout << "No desired element found in vector" << endl;
  else cout << *iter << endl;
}

Exercise 10.25

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
bool check_size(const string &s, string::size_type sz)
{
  return s.size() >= sz;
}
bool is_shorter(const string &word1, const string &word2)
{
  return word1.size() < word2.size();
}
void elimDups(vector<string> &words)
{
  sort(words.begin(), words.end());
  auto end_unique = unique(words.begin(), words.end());
  words.erase(end_unique, words.end());
}
void biggies(vector<string> &words, vector<string>::size_type sz)
{
  elimDups(words);
  stable_sort(words.begin(), words.end(), is_shorter);
  auto iter = partition(words.begin(), words.end(),
		      bind(check_size, _1, sz));
  auto count = iter - words.begin();
  cout << count << " words" << endl;
  for_each(words.begin(), iter, [](const string &s){cout << s << endl;});
}
int main()
{
  vector<string> vs =
    {"the", "time", "is", "near", "near", "the", "sunrise"};
  biggies(vs, 4);
}

Exercise 10.26

1
2
3
4
// back_inserter always pushs new element to the back of given container
// front_inserter always pushs new element to the frot of given container
// inserter always pushs new element to the front of the element pointered by a iterator, which is the given container's iterator and passed in as the second argument.

Exercise 10.27

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
int main()
{
  cout << "Please enter integers: " << endl;
  vector<int> vi;
  int i;
  while(cin >> i)
    vi.push_back(i);
  if(!vi.size()) return -1;
  list<int> li;
  unique_copy(vi.cbegin(), vi.cend(), inserter(li, li.begin()));
  cout << "Unique integers among your inputs: " << endl;
  for(const auto &i : li)
    cout << i << endl;
}

Exercise 10.28

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
int main()
{
  vector<int> vi1, vi2, vi4 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  forward_list<int> fl;
  // same as vi4
  copy(vi4.cbegin(), vi4.cend(), inserter(vi1, vi1.begin()));
  // same as vi4
  copy(vi4.cbegin(), vi4.cend(), back_inserter(vi2));
  // reverse order of vi4
  copy(vi4.cbegin(), vi4.cend(), front_inserter(fl));
  cout << "for the one using inserter: " << endl;
  for(const auto &i : vi1)
    cout << i << endl;
  cout << "for the one using back_inserter: " << endl;
  for(const auto &i : vi2)
    cout << i << endl;
  cout << "for the one using front_inserter: " << endl;
  for(const auto &i : fl)
    cout << i << endl;
}

Exercise 10.29

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int main(int argc, char *argv[])
{
  if(argc != 2) return -1;
  ifstream ifs(argv[1]);
  istream_iterator<string> ifs_iter(ifs), eof;
  vector<string> vs(ifs_iter, eof);
  for(const auto &s : vs)
    cout << s << endl;
}

Exercise 10.30

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int main()
{
  istream_iterator<int> in_iter(cin), eof;
  ostream_iterator<int> out_iter(cout, "\n");
  vector<int> vi;
  copy(in_iter, eof, back_inserter(vi));
  sort(vi.begin(), vi.end());
  copy(vi.cbegin(), vi.cend(), out_iter);
}

Exercise 10.31

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int main()
{
  istream_iterator<int> in_iter(cin), eof;
  ostream_iterator<int> out_iter(cout, "\n");
  vector<int> vi;
  copy(in_iter, eof, back_inserter(vi));
  sort(vi.begin(), vi.end());
  unique_copy(vi.begin(), vi.end(), out_iter);
}

Exercise 10.32

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// using find, program is really complex
// easier and simpler if using find_if
bool compareIsbn(Sales_item &s1, Sales_item &s2)
{
  return s1.isbn() < s2.isbn();
}
int main()
{
  vector<Sales_item> vsa;
  istream_iterator<Sales_item> in_iter(cin), eof;
  ostream_iterator<Sales_item> out_iter(cout);
  copy(in_iter, eof, back_inserter(vsa));
  sort(vsa.begin(), vsa.end(), compareIsbn);
  auto iter = vsa.cbegin();
  while(iter != vsa.cend())
    {
      Sales_item total;
      auto found = vsa.cend();
      auto temp = found;
      auto beg = iter;
      do
      {
	++iter;
	temp = found;
      }
      while(iter != vsa.cend() && (found = find(iter, vsa.cend(), *beg)) != vsa.cend())
      if(temp == vsa.cend()) cout << *beg << endl;
      else cout << accumulate(beg, temp + 1, total) << endl;
    }
}

Exercise 10.33

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
void even_odd_f2f(const string &inf, const string &outf1, const string &outf2)
{
  ifstream ifs(inf);
  ofstream ofs1(outf1);
  ofstream ofs2(outf2);
  istream_iterator<int> in_iter(ifs), eof;
  ostream_iterator<int> out_iter1(ofs1, " "), out_iter2(ofs2, "\n");
  while(in_iter != eof)
    {
      (*in_iter % 2) ? out_iter1 = *in_iter : out_iter2 = *in_iter;
      ++in_iter;
    }
}
int main(int argc, char *argv[])
{
  if(argc != 4) return -1;
  even_odd_f2f(argv[1], argv[2], argv[3]);
}

Exercise 10.34

1
2
3
4
5
6
7
int main()
{
  vector<int> vi = {1, 2, 3, 4, 5, 6, 7};
  for(auto riter = vi.crbegin(); riter != vi.crend(); ++riter)
    cout << *riter << endl;
}

Exercise 10.35

1
2
3
4
5
6
7
int main()
{
  vector<int> vi = {1, 2, 3, 4, 5, 6, 7};
  for(auto iter = vi.cend() - 1; iter != vi.cbegin() - 1; --iter)
    cout << *iter << endl;
}

Exercise 10.36

1
2
3
4
5
6
7
8
int main()
{
  list<int> li = {1, 2, 3, 4, 0, 0, 7, 0, 8};
  auto riter = find(li.crbegin(), li.crend(), 0);
  list<int> result(li.cbegin(), riter.base());
  for(const auto &i : result) cout << i << endl;
}

Exercise 10.37

1
2
3
4
5
6
7
int main()
{
  vector<int> vi = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  list<int> li(vi.crbegin() + 3, vi.crbegin() + 8);
  for(const auto &i : li) cout << i << endl;
}

Exercise 10.38

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// input iterator
// support operators: ==, !=, ++(prefix and suffix), *(result as the right value of one assignment), ->(same as *iter.member), single pass scan.
// output iterator
// support operators: complement of input iterator's support operators, ++(prefix and suffix), *(result as the left value of one assignment), single pass scan.
// forward iterator
// support operators: all of input and out operator's operators, read & write one element for arbitrary times, multi pass scan.
// bidirectional iterator
// support operator: all of input, out, forward iterator's operators, --(prefix, suffix), read & write  elements in a noraml and reverse order, multi pass scan.
// random-access iterator
// support operators: all of input, out, forward, bidirectional iterator's operators, access of arbitrary element whihin constant time, relationship operators(<, <=, >, >=), calculating with integers(+, +=, -, -=), substraction operator for two iterators(-, get the distance between two iterators), subscript operator(iter[n], same as *(iter[n])), multi pass scan.

Exercise 10.39

1
2
3
// iterator of list type is bidirectional iterator
// iterator of vector type is random-access iterator

Exercise 10.40

1
2
3
4
// algorighm copy reauires input iterators as the first two arguments, and output iterator as the third argument.
// reverse requires bidirectional iterators as the first two arguments.
// unique requires forward iterators as the first two arguments.

Exercise 10.41

1
2
3
4
5
6
7
8
9
// replace(beg, end, old_val, new_val)
// replaces old_val among elements spedified by [beg, end) with new_val
// replace_if(beg, end, pred. new_val)
// replaces element which makes pred return non-zero result with new_val, element belongs to the range spedified by [beg, end).
// replace_copy(beg, end, dest, old_val, new_val)
// mostly same as replace(beg, end, old_val, new_val), but would not modify the container spedified by the first two arguments, just copies the result to the container spedified by dest.
// replace_copy_if(beg, end, dest, pred, new_val)
// mostly same as replace_copy(beg, end, dest, old_val, new_val), but only replaces the element which makes pred return non-zero result, that element is spedified by rang[beg, end).

Exercise 10.42

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
void elimDups(list<string> &words)
{
  words.sort();
  words.unique();
}
int main()
{
  list<string> ls =
    {"the", "time", "is", "near", "near", "the", "sunrise"};
  elimDups(ls);
  for(const auto &s : ls) cout << s << endl;
}