Exercise 17.1

1
2
3
4
5
int main()
{
  tuple<int, int, int> ti(10, 20, 30);
}

Exercise 17.2

1
2
3
4
5
int main()
{
  tuple<string, vector<string>, pair<string, int>> ti("hello", {"hello", "world"}, {"answer", 42});
}

Exercise 17.3

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// See TextQuery.h.
// if class QueryResult would not be utilized in another place;
// Using tuple instead of a class definition is a better choice;
// reduce complexity and save labor work.
void runQueries(ifstream &infile)
{
  TextQuery tq(infile);
  string s;
  while(true)
    {
      cout << "Enter word to look for, or q to quit: ";
      string s;
      if(!(cin >> s) || s == "q") break;
      print(cout, tq.query(s)) << endl;
    }
}
int main(int argc, char *argv[])
{
  ifstream ifs(argv[1]);
  runQueries(ifs);
}

TextQuery.h

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#ifndef TEXTQUERY_H
#define TEXTQUERY_H
class TextQuery
{
 public:
  using line_no = vector<string>::size_type;
  using QueryResult = tuple
    <
    shared_ptr<vector<string>>,
    shared_ptr<set<line_no>>,
    string
    >;
  TextQuery(ifstream &infile);
  TextQuery(const TextQuery &);
  TextQuery &operator=(const TextQuery &);
  QueryResult query(const string &s) const;
 private:
  shared_ptr<vector<string>> sp1;
  map<string, shared_ptr<set<line_no>>> mp;
};
TextQuery::TextQuery(ifstream &infile):
sp1(new vector<string>)
{
  line_no line_number = 0;
  string line;
  while(getline(infile, line))
    {
      // store line in vector<string>
      sp1->push_back(line);
      // scan through the line
      istringstream ist(line);
      string word;
      while(ist >> word)
      {
	if(ispunct(word[word.size() - 1]))
	  word.erase(word.size() - 1);
	auto &lines = mp[word];
	if(!lines) lines.reset(new set<line_no>);
	lines->insert(line_number);
      }
      // increase the line_number
      ++line_number;
    }
}
TextQuery::TextQuery(const TextQuery &t): sp1(make_shared<vector<string>>(*t.sp1)), mp(t.mp) {}
TextQuery &TextQuery::operator=(const TextQuery &t)
{
  sp1 = make_shared<vector<string>>(*t.sp1);
  mp = t.mp;
  return *this;
}
  ostream &print(ostream &o, const TextQuery::QueryResult &q)
  {
    auto n = get<1>(q)->size();
    o << "element occurs " << n << " times" << endl;
    auto result = *get<1>(q);
    for(const auto &l : result)
      cout << "\t(line " << l + 1 << ") "
	 << (*get<0>(q))[l] << endl;
    return o;
  }
auto TextQuery::query(const string &s) const -> QueryResult
{
  static shared_ptr<set<line_no>> nodata(new set<line_no>);
  auto iter = mp.find(s);
  auto last = mp.end();
  if(iter != last)
    return QueryResult(sp1, iter->second, s);
  else
    return QueryResult(sp1, nodata, s);
}
#endif

Exercise 17.4

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
using matches = tuple<vector<Sales_data>::size_type,
		    vector<Sales_data>::const_iterator,
		    vector<Sales_data>::const_iterator>;
bool compareIsbn(const Sales_data &d1, const Sales_data &d2)
{
  return d1.isbn() < d2.isbn();
}
vector<matches>
findBook(const vector<vector<Sales_data>> &files,
       const string &book)
{
  vector<matches> ret;
  for(auto it = files.cbegin(); it != files.cend(); ++it)
    {
      auto found = equal_range(it->cbegin(), it->cend(), book, compareIsbn);
      if(found.first != found.second)
      ret.push_back(make_tuple(it - files.cbegin(),
			       found.first, found.second));
    }
  return ret;
}

Exercise 17.5

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
using matches = pair<vector<Sales_data>::size_type,
		   pair<vector<Sales_data>::const_iterator,
			vector<Sales_data>::const_iterator>>;
bool compareIsbn(const Sales_data &d1, const Sales_data &d2)
{
  return d1.isbn() < d2.isbn();
}
vector<matches>
findBllk(const vector<vector<Sales_data>> &files,
       const string &book)
{
  vector<matches> ret;
  for(auto it = files.cbegin(); it != files.cend(); ++it)
    {
      auto found = equal_range(it->cbegin(), it->cend(), book, compareIsbn);
      if(found.first != found.second)
      ret.push_back(make_pair(it - files.cbegin(),
			      make_pair(found.first, found.second)));
    }
  return ret;
}

Exercise 17.6

 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
class Matches
{
public:
  using s = vector<Sales_data>::size_type;
  using c = vector<Sales_data>::const_iterator;
  Matches() = default;
  Matches(s i, c it1, c it2): index(i), first(it1), last(it2) {}
private:
  s index;
  c first;
  c last;
};
bool compareIsbn(const Sales_data &d1, const Sales_data &d2)
{
  return d1.isbn() < d2.isbn();
}
vector<Matches>
findBllk(const vector<vector<Sales_data>> &files,
       const string &book)
{
  vector<Matches> ret;
  for(auto it = files.cbegin(); it != files.cend(); ++it)
    {
      auto found = equal_range(it->cbegin(), it->cend(), book, compareIsbn);
      if(found.first != found.second)
      ret.push_back(Matches(it - files.cbegin(),
			       found.first, found.second));
    }
  return ret;
}

Exercise 17.7

1
2
3
4
// Prefer the one using tuple;
// using tuple makes code simple and friendly;
// it reduces complexity and saves labor work.

Exercise 17.8

 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
32
33
34
// As the operator+= and operator+ member functions defined within class Sales_data;
// if the third argument of accumulate function is Sales_data(), the return result as a Sales_data object whose bookNo is an empty string;
// suppose that the user of class should keep the arguments legal and class itself would not check the passed in arguments.
using matches = tuple<vector<Sales_data>::size_type,
		    vector<Sales_data>::const_iterator,
		    vector<Sales_data>::const_iterator>;
extern vector<matches> findBook(const vector<vector<Sales_data>> &files,
			      const string &book);
void reportResults(istream &in, ostream &os,
		 const vector<vector<Sales_data>> &files)
{
  string s;
  while(in >> s)
    {
      auto trans = findBook(files, s);
      if(trans.empty())
      {
	cout << s << " not found in any stores" << endl;
	continue;
      }
      for(const auto &store : trans)
      os << "store " << get<0>(store) << " sales: "
	 << accumulate(get<1>(store), get<2>(store), Sales_data())
	 << endl;
    }
}
int main()
{
  vector<vector<Sales_data>> total;
  vector<Sales_data> store1 = {Sales_data("1", 12, 2), Sales_data("1", 23, 2)};
  total.push_back(store1);
  reportResults(cin, cout, total);
}

Exercise 17.9

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
int main()
{
  bitset<64> bitvec(32);
  std::cout << bitvec << std::endl;
  // 58*0...100000
  bitset<32> bv(1010101);
  std::cout << bv << std::endl;
  // 25*0...1010101
  // guess expression in textbook misses '0b';
  // but if not so:
  // 12*0...11110110100110110101
  std::string bstr;
  std::cin >> bstr;
  bitset<8> bv2(bstr);
  std::cout << bv2 << std::endl;
  // the result has 8 bits and content depends on input string;
}

Exercise 17.10

 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
void to_fibo_7(bitset<35> &b)
{
  b.reset();
  b.set(0);
  b.set(6);
  b.set(10);
  b.set(11);
  b.set(15);
  b.set(17);
  b.set(23);
  b.set(25);
  b.set(27);
  b.set(28);
  b.set(30);
  b.set(32);
  b.set(34);
}
int main()
{
  std::string fibo = "10101011010100000101000110001000001";
  bitset<35> fibonacci(fibo);
  std::cout << fibonacci << std::endl;
  bitset<35> test;
  to_fibo_7(test);
  std::cout << test << std::endl;
}

Exercise 17.11

1
2
3
4
// bitset<10> results;
// if this test has 100 questions:
// bitset<100> results;

Exercise 17.12

1
2
3
4
5
6
template <size_t n>
void update_results(bitset<n> &results, size_t index, bool result)
{
  results.set(index, result);
}

Exercise 17.13

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
template <size_t n>
void update_results(bitset<n> &results, size_t index, bool result)
{
  results.set(index, result);
}
int main()
{
  bitset<10> right_answers(0b0111000101);
  bitset<10> results;
  update_results(results, 0, true);
  update_results(results, 2, true);
  update_results(results, 6, true);
  update_results(results, 7, true);
  update_results(results, 8, true);
  unsigned score = 0;
  for(size_t n = 0; n != results.size(); ++n)
    if(right_answers[n] == results[n])
      ++score;
  std::cout << score << std::endl;
}

Exercise 17.14

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
int main()
{
  try
    {
      // regex r("[[:alnum:]+\\.(cpp|cxx|cc)$", regex::icase); // error code 4;
      regex r("[[:alnum:]]+\\.(cpp|cxx|cc)$", regex::icase);
      cmatch results;		// compiler error if using smatch;
      if(regex_search("myfile.cc", results, r))
	      cout << results.str() << endl;
    }
  catch(regex_error e)
    {
      cout << e.what() << "\ncode: " << e.code() << endl;
    }
}

Exercise 17.15

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
int main()
{
  string pattern("[[:alpha:]]*[^c]ei[[:alpha:]]*", regex::icase);
  regex r(pattern);
  smatch results;
  string test;
  while(cin >> test)
    (regex_match(test, results, r))
      ? cout << test << " illegal" << endl
      : cout << test << " legal" << endl;
}

Exercise 17.16

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// Still able to find out the illegal word;
// but this version would just match the three-character part of a word, but not the whole word.
int main()
{
  regex r("[^c]ei", regex::icase);
  smatch results;
  string test;
  while(cin >> test)
    // if using regex_match, only three-character word would match
    (regex_search(test, results, r))
      ? cout << results.str() << " illegal" << endl
      : cout << test << " legal" << endl;
}

Exercise 17.17

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
int main()
{
  string pattern("[[:alpha:]]*[^c]ei[[:alpha:]]*");
  regex r(pattern, regex::icase);
  string sample, word;
  while(cin >> word)
    sample += (word + " ");
  sregex_iterator it(sample.begin(), sample.end(), r), end_it;
  cout << "Illegal words: " << endl;
  while(it != end_it)
    {
      cout << it->str() << endl;
      ++it;
    }
}

Exercise 17.18

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// This exercise is nonsense.
int main()
{
  vector<string> legal = {"albeit", "neighbor"};
  string pattern("[[:alpha:]]*[^c]ei[[:alpha:]]*");
  regex r(pattern, regex::icase);
  string sample, word;
  while(cin >> word)
    sample += (word + " ");
  sregex_iterator it(sample.begin(), sample.end(), r), end_it;
  cout << "Illegal words: " << endl;
  while(it != end_it)
    {
      if(count(legal.begin(), legal.end(), it->str()) == 0)
	cout << it->str() << endl;
      ++it;
    }
}

Exercise 17.19

1
2
// Even the ssub_match object returned by m[4] does not match(its matched data member is false), it's legal to call m[4].str(), for this expression wourld return an empty string.

Exercise 17.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
bool valid(const smatch& m)
{
  if(m[1].matched)
    return m[3].matched && (m[4].matched == 0 || m[4].str() == " ");
  else
    return !m[3].matched && m[4].str() == m[6].str();
}
int main()
{
  string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
  regex r(phone);
  smatch m;
  string s;
  while(getline(cin, s))
    {
      for(sregex_iterator it(s.begin(), s.end(), r), end_it;
	it != end_it; ++it)
      if(valid(*it))
	cout << "valid: " << it->str() << endl;
      else
	cout << "not valid: " << it->str() << endl;
    }
}

Exercise 17.21

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
bool valid(const smatch& m)
{
  if(m[1].matched)
    return m[3].matched && (m[4].matched == 0 || m[4].str() == " ");
  else
    return !m[3].matched && m[4].str() == m[6].str();
}
struct PersonInfo
{
  string name;
  string phones;
};
int main(int argc, char *argv[])
{
  if(argc != 2)
    {
      cerr << "Incorrect command-line args, needs 2 now "
	 << argc << endl;
      return -1;
    }
  ifstream ifs(argv[argc - 1]);
  if(!ifs)
    {
      cerr << "Invalid arg " << argv[argc - 1] << endl;
      return -1;
    }
  string line, word;
  vector<PersonInfo> people;
  istringstream record;
  while(getline(ifs, line))
    {
      PersonInfo info;
      record.str(line);
      record >> info.name;
      info.phones = line.substr(info.name.size());
      people.push_back(info);
      record.clear();
    }
  // regex
  string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
  regex r(phone);
  for(const auto &entry : people)
    {
      ostringstream formatted, badNums;
      for(sregex_iterator it(entry.phones.begin(), entry.phones.end(), r), end_it; it != end_it; ++it)
      if(!valid(*it))
	badNums << " " << it->str();
      else
	formatted << " " << it->str();
      if(badNums.str().empty())
      cout << entry.name << formatted.str() << endl;
      else
      cerr << "input error: " << entry.name
	   << " invalid number(s) " << badNums.str() << endl;
    }
}

Exercise 17.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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
bool valid(const smatch& m)
{
  if(m[1].matched)
    return m[3].matched && (m[4].matched == 0 || m[4].str() == " ");
  else
    return !m[3].matched && m[4].str() == m[7].str();
}
struct PersonInfo
{
  string name;
  string phones;
};
int main(int argc, char *argv[])
{
  if(argc != 2)
    {
      cerr << "Incorrect command-line args, needs 2 now "
	 << argc << endl;
      return -1;
    }
  ifstream ifs(argv[argc - 1]);
  if(!ifs)
    {
      cerr << "Invalid arg " << argv[argc - 1] << endl;
      return -1;
    }
  string line, word;
  vector<PersonInfo> people;
  istringstream record;
  while(getline(ifs, line))
    {
      PersonInfo info;
      record.str(line);
      record >> info.name;
      info.phones = line.substr(info.name.size());
      people.push_back(info);
      record.clear();
    }
  // regex
  string phone = "(\\()?(\\d{3})(\\))?([-.])?([ ]*)(\\d{3})([-.])?([ ]*)(\\d{4})";
  regex r(phone);
  for(const auto &entry : people)
    {
      ostringstream formatted, badNums;
      for(sregex_iterator it(entry.phones.begin(), entry.phones.end(), r), end_it; it != end_it; ++it)
      if(!valid(*it))
	badNums << " " << it->str();
      else
	formatted << " " << it->str();
      if(badNums.str().empty())
      cout << entry.name << formatted.str() << endl;
      else
      cerr << "input error: " << entry.name
	   << " invalid number(s) " << badNums.str() << endl;
    }
}

Exercise 17.23

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
bool valid(const smatch& m)
{
  if(m[2].matched)
    {
      return m[3].matched;
    }
  return true;
}
int main()
{
  string postcode = "(\\d{5})([-])?(\\d{4})?";
  regex r(postcode);
  string s;
  while(getline(cin, s))
    {
      for(sregex_iterator it(s.begin(), s.end(), r), end_it;
	it != end_it; ++it)
      if(valid(*it))
	cout << "valid: " << it->str() << endl;
      else
	cout << "not valid: " << it->str() << endl;
    }
}

Exercise 17.24

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
int main()
{
  string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
  regex r(phone);
  smatch m;
  string s;
  string fmt = "$2.$5.$7";
  while(getline(cin, s))
    cout << regex_replace(s, r, fmt) << endl;
}

Exercise 17.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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
bool valid(const smatch& m)
{
  if(m[1].matched)
    return m[3].matched && (m[4].matched == 0 || m[4].str() == " ");
  else
    return !m[3].matched && m[4].str() == m[6].str();
}
struct PersonInfo
{
  string name;
  string phones;
};
int main(int argc, char *argv[])
{
  if(argc != 2)
    {
      cerr << "Incorrect command-line args, needs 2 now "
	 << argc << endl;
      return -1;
    }
  ifstream ifs(argv[argc - 1]);
  if(!ifs)
    {
      cerr << "Invalid arg " << argv[argc - 1] << endl;
      return -1;
    }
  string line, word;
  vector<PersonInfo> people;
  istringstream record;
  while(getline(ifs, line))
    {
      PersonInfo info;
      record.str(line);
      record >> info.name;
      info.phones = line.substr(info.name.size());
      people.push_back(info);
      record.clear();
    }
  // regex
  string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
  regex r(phone);
  smatch m;
  for(const auto &entry : people)
    {
      if(regex_search(entry.phones, m, r))
      {
	if(valid(m))
	  cout << entry.name << m.str() << endl;
	else
	  cerr << "input error: " << entry.name
	       << " invalid number(s) " << m.str() << endl;
      }
    }
}

Exercise 17.26

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// Really an odd way to solve this exercise.
bool valid(const smatch& m)
{
  if(m[1].matched)
    return m[3].matched && (m[4].matched == 0 || m[4].str() == " ");
  else
    return !m[3].matched && m[4].str() == m[6].str();
}
struct PersonInfo
{
  string name;
  string phones;
};
int main(int argc, char *argv[])
{
  if(argc != 2)
    {
      cerr << "Incorrect command-line args, needs 2 now "
	 << argc << endl;
      return -1;
    }
  ifstream ifs(argv[argc - 1]);
  if(!ifs)
    {
      cerr << "Invalid arg " << argv[argc - 1] << endl;
      return -1;
    }
  string line, word;
  vector<PersonInfo> people;
  istringstream record;
  while(getline(ifs, line))
    {
      PersonInfo info;
      record.str(line);
      record >> info.name;
      info.phones = line.substr(info.name.size() + 1);
      people.push_back(info);
      record.clear();
    }
  // regex
  string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
  regex r(phone);
  for(auto &entry : people)
    {
      if(entry.phones.size() > 10)
      entry.phones = regex_replace(entry.phones, r, "", format_first_only);
      ostringstream formatted, badNums;
      for(sregex_iterator it(entry.phones.begin(), entry.phones.end(), r), end_it; it != end_it; ++it)
      if(!valid(*it))
	badNums << " " << it->str();
      else
	formatted << " " << it->str();
      if(badNums.str().empty())
      cout << entry.name << formatted.str() << endl;
      else
      cerr << "input error: " << entry.name
	   << " invalid number(s) " << badNums.str() << endl;
    }
}

Exercise 17.27

 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 valid(const smatch& m)
{
  if(m[2].matched)
    {
      return m[3].matched;
    }
  return true;
}
int main()
{
  string postcode = "(\\d{5})([-])?(\\d{4})?";
  regex r(postcode);
  smatch m;
  string s;
  string fmt = "$1-$3";
  while(getline(cin, s))
    {
      for(sregex_iterator it(s.begin(), s.end(), r), end_it;
	it != end_it; ++it)
      if(valid(*it))
	{
	  if(it->str().size() >= 9)
	    cout << "valid: " << it->format(fmt) << endl;
	  else
	    cout << "valid: " << it->str() << endl;
	}
      else
	cout << "not valid: " << it->str() << endl;
    }
}

Exercise 17.28

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
unsigned random_unsigned()
{
  static default_random_engine e;
  static uniform_int_distribution<unsigned> u;
  return u(e);
}
int main()
{
  for(int i = 10; i != 0; --i)
    cout << random_unsigned() << endl;
}

Exercise 17.29

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
unsigned random_unsigned(unsigned s = time(0))
{
  static default_random_engine e(s);
  static uniform_int_distribution<unsigned> u;
  return u(e);
}
int main()
{
  cout << "Please input a seed of unsigned int type: " << endl;
  unsigned s;
  cin >> s;
  for(int i = 10; i != 0; --i)
    cout << random_unsigned(s) << endl;
}

Exercise 17.30

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
unsigned random_unsigned(unsigned min = 0, unsigned max = 9, unsigned s = time(0))
{
  static default_random_engine e(s);
  static uniform_int_distribution<unsigned> u(min, max);
  return u(e);
}
int main()
{
  cout << "Please input a seed of unsigned int type\n"
       << "and specify the min and max values of output range: "
       << endl;
  unsigned s, min, max;
  cin >> s >> min >> max;
  for(int i = 10; i != 0; --i)
    cout << random_unsigned(min, max, s) << endl;
}

Exercise 17.31

1
2
// For the game program in this section, if variable b and e are defined within do-while loop, outputs stay exactly same when loop running.

Exercise 17.32

1
2
3
// If resp is defined within loop body, there would be a compile error;
// when the loop body ends, the variables defined within it would be destructed, after that, it's illegal to get access to such variables in outer scope.

Exercise 17.33

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Random two-way conversion.
map<string, vector<string>> buildMap(ifstream &map_file)
{
  map<string, vector<string>> trans_map;
  string key, value;
  while(map_file >> key && getline(map_file, value))
    {
      if(value.size() > 1)
      {
	istringstream is(value.substr(1));
	string word;
	while(is >> word)
	  trans_map[key].push_back(word);
      }
      else
      throw runtime_error("no rule for " + key);
    }
  return trans_map;
}
const string &transform(const string &s, const map<string, vector<string>> &m)
{
  static default_random_engine e(time(0));
  static bernoulli_distribution u;
  auto map_it = m.find(s);
  if(map_it != m.cend())
    return map_it->second[u(e)];
  else
    return s;
}
void word_transfrom(ifstream &map_file, ifstream &input)
{
  auto trans_map = buildMap(map_file);
  string text;
  while(getline(input, text))
    {
      istringstream stream(text);
      string word;
      bool firstword = true;
      while(stream >> word)
      {
	if(firstword) firstword = false;
	else cout << " ";
	cout << transform(word, trans_map);
      }
      cout << endl;
    }
}
int main(int argc, char *argv[])
{
  if(argc != 3) return -1;
  auto map_file = ifstream(argv[1]);
  auto input = ifstream(argv[2]);
  word_transfrom(map_file, input);
}

Exercise 17.34

1
2
3
// Won't do this;
// this is pure labor work.

Exercise 17.35

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int main()
{
  cout << "default format: " << 100 * sqrt(2.0) << '\n'
       << "scientific: " << scientific << 100 * sqrt(2.0) << '\n'
       << "fix decimal: " << fixed << 100 * sqrt(2.0) << '\n'
       << "hexadecimal: " << hexfloat << uppercase << 100 * sqrt(2.0) << '\n'
       << nouppercase
       << "use defaults: " << defaultfloat << 100 * sqrt(2.0) << '\n';
}

Exercise 17.36

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
int main()
{
  cout << setw(20) << 100 * sqrt(2.0) << '\n'
       << scientific << setw(20) << 100 * sqrt(2.0) << '\n'
       << fixed << setw(20) << 100 * sqrt(2.0) << '\n'
       << hexfloat << uppercase << setw(20)
       << 100 * sqrt(2.0) << '\n' << nouppercase
       << defaultfloat << setw(20)
       <<  100 * sqrt(2.0) << '\n';
}

Exercise 17.37

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// Program processing ends when encounters a line whose length is larger than specified array size;
// while if the size of array is set really large, there would be garbleds in outpus.
int main(int argc, char *argv[])
{
  char sample[250];
  ifstream ifs(argv[1]);
  while(ifs)
    {
      ifs.getline(sample, 250, '\n');
      cout << sample << endl;
    }
}

Exercise 17.38

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
int main(int argc, char *argv[])
{
  char sample[30];
  ifstream ifs(argv[1]);
  while(ifs)
    {
      ifs.getline(sample, 30, ' ');
      cout << sample;
    }
}

Exercise 17.39

 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
int main()
{
  fstream inOut("copyOut", fstream::ate | fstream::in | fstream::out);
  if(!inOut)
    {
      cerr << "Unable to open file!" << endl;
      return EXIT_FAILURE;
    }
  auto end_mark = inOut.tellg();
  inOut.seekg(0, fstream::beg);
  size_t cnt = 0;
  string line;
  while(inOut && inOut.tellg() != end_mark
      && getline(inOut, line))
    {
      cnt += line.size() + 1;
      auto mark = inOut.tellg();
      inOut.seekp(0, fstream::end);
      inOut << cnt;
      if(mark != end_mark)
      inOut << " ";
      inOut.seekg(mark);
    }
  inOut.seekp(0, fstream::end);
  inOut << "\n";
  return 0;
}