This post series is the Solutions of the Programming — Principles and Practice Using C++ (Second Edition) written by Bjarne Stroustrup
Chapter 6: Writing a Program
Drill
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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
#include <iostream> #include "../std_lib_facilities.h" using namespace std; double primary(); double term(); double expression(); double primary(); class Token { public: char kind; // what kind of token double value; // for numbers: a value Token(char ch) // make a Token from a char :kind(ch), value(0) { } Token(char ch, double val) // make a Token from a char and a double :kind(ch), value(val) { } }; class Token_stream{ public: Token_stream(); Token get(); void putback(Token t); private: bool full{false}; Token buffer; }; void Token_stream::putback(Token t){ if (full) error("putback() into a full bufer"); buffer = t; full = true; } Token_stream::Token_stream() :full(false), buffer(0) // no Token in buffer { } Token Token_stream::get(){ if (full) { full = false; return buffer; } char ch; cin >> ch; switch (ch) { case ';': case 'q': case '(': case ')': case '+': case '-': case '*': case '/': return Token(ch); case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { cin.putback(ch); double val; cin >> val; return Token('8',val); } default: error("Bad Token"); } } Token_stream ts; double primary(){ Token t = ts.get(); switch (t.kind) { case '(': { double d = expression(); t = ts.get(); if (t.kind != ')')error("')' expected"); return d; } case '8': return t.value; default: error("primary expected"); } } double term(){ double left = primary(); Token t = ts.get(); while (true) { switch (t.kind) { case '*': left *= primary(); t = ts.get(); break; case '/': { double d = primary(); if (d==0)error("divide by zero"); left /= d; t = ts.get(); break; } default: ts.putback(t); return left; } } } double expression(){ double left = term(); Token t = ts.get(); while (true){ switch (t.kind) { case '+': left += term(); t = ts.get(); break; case '-': left -= term(); t = ts.get(); break; default: ts.putback(t); return left; } } } int main(int argc, char const *argv[]) { try{ double val = 0; while (cin){ Token t = ts.get(); if (t.kind == 'q') break; if (t.kind == ';') cout << "=" << val << "\n"; else ts.putback(t); val = expression(); } keep_window_open(); } catch (exception& e){ } catch(...){ cerr << "exception \n"; keep_window_open(); return 2; } } |
Example 2
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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
#include <iostream> #include "../std_lib_facilities.h" using namespace std; double primary(); double term(); double expression(); double primary(); class Token { public: char kind; // what kind of token double value; // for numbers: a value Token(char ch) // make a Token from a char :kind(ch), value(0) { } Token(char ch, double val) // make a Token from a char and a double :kind(ch), value(val) { } }; class Token_stream{ public: Token_stream(); Token get(); void putback(Token t); private: bool full{false}; Token buffer; }; void Token_stream::putback(Token t){ if (full) error("putback() into a full bufer"); buffer = t; full = true; } Token_stream::Token_stream() :full(false), buffer(0) // no Token in buffer { } Token Token_stream::get(){ if (full) { full = false; return buffer; } char ch; cin >> ch; switch (ch) { case ';': case 'q': case '(': case ')': case '{': case '}': case '+': case '-': case '*': case '/': return Token(ch); case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { cin.putback(ch); double val; cin >> val; return Token('8',val); } default: error("Bad Token"); } } Token_stream ts; double primary(){ Token t = ts.get(); switch (t.kind) { case '(': case '{': { double d = expression(); t = ts.get(); if (t.kind != ')' && t.kind != '}')error("')' expected"); return d; } case '8': return t.value; default: error("primary expected"); } } double term(){ double left = primary(); Token t = ts.get(); while (true) { switch (t.kind) { case '*': left *= primary(); t = ts.get(); break; case '/': { double d = primary(); if (d==0)error("divide by zero"); left /= d; t = ts.get(); break; } default: ts.putback(t); return left; } } } double expression(){ double left = term(); Token t = ts.get(); while (true){ switch (t.kind) { case '+': left += term(); t = ts.get(); break; case '-': left -= term(); t = ts.get(); break; default: ts.putback(t); return left; } } } int main(int argc, char const *argv[]) { try{ double val = 0; while (cin){ Token t = ts.get(); if (t.kind == 'q') break; if (t.kind == ';') cout << "=" << val << "\n"; else ts.putback(t); val = expression(); } keep_window_open(); } catch (exception& e){ } catch(...){ cerr << "exception \n"; keep_window_open(); return 2; } } |
Example 3
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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
#include <iostream> #include "../std_lib_facilities.h" using namespace std; double primary(); double term(); double expression(); double primary(); class Token { public: char kind; // what kind of token double value; // for numbers: a value Token(char ch) // make a Token from a char :kind(ch), value(0) { } Token(char ch, double val) // make a Token from a char and a double :kind(ch), value(val) { } }; class Token_stream{ public: Token_stream(); Token get(); void putback(Token t); private: bool full{false}; Token buffer; }; void Token_stream::putback(Token t){ if (full) error("putback() into a full bufer"); buffer = t; full = true; } Token_stream::Token_stream() :full(false), buffer(0) // no Token in buffer { } Token Token_stream::get(){ if (full) { full = false; return buffer; } char ch; cin >> ch; switch (ch) { case ';': case 'q': case '(': case ')': case '{': case '}': case '+': case '-': case '*': case '/': case '!': return Token(ch); case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { cin.putback(ch); double val; cin >> val; return Token('8',val); } default: error("Bad Token"); } } Token_stream ts; double primary(){ Token t = ts.get(); switch (t.kind) { case '(': case '{': { double d = expression(); t = ts.get(); if (t.kind != ')' && t.kind != '}')error("')' expected"); return d; } case '8': return t.value; default: error("primary expected"); } } double fact(){ double left = primary(); Token t = ts.get(); while (true) { switch (t.kind) { case '!': { if (left!=ceil(left))error("factorial must be integer"); if (int(left) == 0) left = 1.0; for(int i = int(left-1); i >=1; --i) { left *= i; } t = ts.get(); break; } default: ts.putback(t); return left; } } } double term(){ double left = fact(); Token t = ts.get(); while (true) { switch (t.kind) { case '*': left *= fact(); t = ts.get(); break; case '/': { double d = primary(); if (d==0)error("divide by zero"); left /= d; t = ts.get(); break; } default: ts.putback(t); return left; } } } double expression(){ double left = term(); Token t = ts.get(); while (true){ switch (t.kind) { case '+': left += term(); t = ts.get(); break; case '-': left -= term(); t = ts.get(); break; default: ts.putback(t); return left; } } } int main(int argc, char const *argv[]) { try{ double val = 0; while (cin){ Token t = ts.get(); if (t.kind == 'q') break; if (t.kind == ';') cout << "=" << val << "\n"; else ts.putback(t); val = expression(); } keep_window_open(); } catch (exception& e){ } catch(...){ cerr << "exception \n"; keep_window_open(); return 2; } } |
Example 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 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 74 75 76 77 78 79 80 81 |
#include "std_lib_facilities.h" vector<string> nouns; vector<string> verbs; vector<string> conjunctions; void init() { nouns.push_back("birds"); nouns.push_back("fish"); nouns.push_back("C++"); verbs.push_back("rules"); verbs.push_back("fly"); verbs.push_back("swim"); conjunctions.push_back("and"); conjunctions.push_back("or"); conjunctions.push_back("but"); } bool is_noun(string w) { for(int i = 0; i<nouns.size(); ++i) if (w==nouns[i]) return true; return false; } bool is_verb(string w) { for(int i = 0; i<verbs.size(); ++i) if (w==verbs[i]) return true; return false; } bool is_conjunction(string w) { for(int i = 0; i<conjunctions.size(); ++i) if (w==conjunctions[i]) return true; return false; } bool sentence() { string w; cin >> w; if (!is_noun(w)) return false; string w2; cin >> w2; if (!is_verb(w2)) return false; string w3; cin >> w3; if (w3 == ".") return true; if (!is_conjunction(w3)) return false; return sentence(); } int main() try { cout << "enter a sentence of the simplified grammar (terminated by a dot):\n"; init(); while (cin) { bool b = sentence(); if (b) cout << "OK\n"; else cout << "not OK\n"; cout << "Try again: "; } keep_window_open("~"); catch (runtime_error e) { cout << e.what() << '\n'; keep_window_open("~"); } |
Example 7
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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
#include <iostream> #include "../std_lib_facilities.h" using namespace std; bool primary(); bool term(); bool expression(); bool primary(); class Token { public: char kind; // what kind of token bool value; // for numbers: a value Token(char ch) // make a Token from a char :kind(ch), value(false) { } Token(char ch, bool val) // make a Token from a char and a bool :kind(ch), value(val) { } }; class Token_stream{ public: Token_stream(); Token get(); void putback(Token t); private: bool full{false}; Token buffer; }; void Token_stream::putback(Token t){ if (full) error("putback() into a full bufer"); buffer = t; full = true; } Token_stream::Token_stream() :full(false), buffer(false) // no Token in buffer { } Token Token_stream::get(){ if (full) { full = false; return buffer; } char ch; cin >> ch; switch (ch) { case ';': case 'q': case '!': case '~': case '&': case '|': case '^': return Token(ch); case '.': case '0': case '1': { cin.putback(ch); bool val; cin >> val; return Token('8',val); } default: error("Bad Token"); } } Token_stream ts; bool primary(){ Token t = ts.get(); switch (t.kind) { case '!': case '~': { t = ts.get(); bool d =! t.value; return d; } case '8': return t.value; default: error("primary expected"); } } bool fact(){ bool left = primary(); Token t = ts.get(); while (true) { switch (t.kind) { case '&': { left &= primary(); t = ts.get(); break; } default: ts.putback(t); return left; } } } bool term(){ bool left = fact(); Token t = ts.get(); while (true) { switch (t.kind) { case '^': left ^= fact(); t = ts.get(); break; default: ts.putback(t); return left; } } } bool expression(){ bool left = term(); Token t = ts.get(); while (true){ switch (t.kind) { case '|': left |= term(); t = ts.get(); break; default: ts.putback(t); return left; } } } int main(int argc, char const *argv[]) { try{ bool val = 0; while (cin){ Token t = ts.get(); if (t.kind == 'q') break; if (t.kind == ';') cout << "=" << val << "\n"; else ts.putback(t); val = expression(); } keep_window_open(); } catch (exception& e){ } catch(...){ cerr << "exception \n"; keep_window_open(); return 2; } } |
Example 9
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 |
#include "std_lib_facilities.h" int main() try { vector<int> digit; // collect digits here vector<string> unit; // unit names go here unit.push_back(" ones "); unit.push_back(" tens "); unit.push_back(" hundreds ");; unit.push_back(" thousands "); unit.push_back(" tens of thousands "); unit.push_back(" hundreds of thousands "); unit.push_back(" millions "); unit.push_back(" tens of millions "); unit.push_back(" hundreds of millions "); cout << "Please enter an integer with no more than " << unit.size() << "\ndigits followed by semicolon and a newline: "; char ch; while (cin>>ch) { // remember cin>>ch skips whitespace (this could be simpler written using cin.get(ch) ) if (ch<'0' || '9'<ch) break; // actually: any non-digit acts as a terminator digit.push_back(ch-'0'); } if (digit.size()==0) error("no digits"); if (unit.size()<digit.size()) error("Sorry, cannot handle that many digits"); for (int i =0; i<digit.size(); ++i) cout << char('0'+digit[i]); cout << '\n'; int num = 0; for (int i = 0; i<digit.size(); ++i) { if (digit[i]) cout << digit[i] << unit[digit.size()-i-1]; num = num*10+digit[i]; } cout << "\nthat is " << num << '\n'; keep_window_open("~"); } catch (runtime_error e) { cout << e.what() << '\n'; keep_window_open("~"); } |
Example 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 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 |
#include "std_lib_facilities.h" int factorial(int n) { int fac = 1; while (1<n) { fac *= n; --n; if (fac<1) error("factorial overflow"); } return fac; } int n_permutations(int a, int b) { if (a<b || a<1 || b<1) error("bad permutation sizes"); return factorial(a)/factorial(a-b); } int n_combinations(int a, int b) { return n_permutations(a,b)/factorial(b); } int main() try { cout << "I can calculate the number of combinations and permutations for sets of numbers\n"; cout << "Please enter two numbers (separated by whitespace)\n"; cout << "first the number of elements in the set and then the number of elements in a subset thereof: "; int a, b; if (!(cin>>a>>b)) error("that wasn't two integers"); cout << "enter 'c' to get the number of combinations,\n'p' to get the number of permutations,\nor 'b' to get both: "; bool perm = false; bool comb = false; string s; cin >> s; if (s=="p") perm = true; else if (s=="c") comb = true; else if (s=="b") { perm = true; comb = true; } else error("bad input instruction"); if (perm) cout << "P(" << a << ',' << b << ") = " << n_permutations(a,b) << '\n'; if (comb) cout << "C(" << a << ',' << b << ") = " << n_combinations(a,b) << '\n'; keep_window_open("~"); // For some Windows(tm) setups } catch (runtime_error e) { // this code is to produceerror messages; it will be described in Chapter 5 cout << e.what() << '\n'; keep_window_open("~"); // For some Windows(tm) setups } |