fork download
  1.  
  2. //
  3. // This is example code from Chapter 6.7 "Trying the second version" of
  4. // "Software - Principles and Practice using C++" by Bjarne Stroustrup
  5. //
  6.  
  7. /*
  8.   This file is known as calculator02buggy.cpp
  9.  
  10. I have inserted 5 errors that should cause this not to compile
  11. I have inserted 3 logic errors that should cause the program to give wrong results
  12.  
  13. First try to find an remove the bugs without looking in the book.
  14. If that gets tedious, compare the code to that in the book (or posted source code)
  15.  
  16. Happy hunting!
  17.  
  18. */
  19.  
  20. #include "../std_lib_facilities.h"
  21.  
  22. //------------------------------------------------------------------------------
  23.  
  24. class Token {
  25. public:
  26. char kind; // what kind of token
  27. double value; // for numbers: a value
  28. Token(char ch) // make a Token from a char
  29. :kind(ch), value(0) { }
  30. Token(char ch, double val) // make a Token from a char and a double
  31. :kind(ch), value(val) { }
  32. };
  33.  
  34. //------------------------------------------------------------------------------
  35.  
  36. class Token_stream {
  37. public:
  38. Token_stream(); // make a Token_stream that reads from cin
  39. Token get(); // get a Token (get() is defined elsewhere)
  40. void putback(Token t); // put a Token back
  41. private:
  42. bool full; // is there a Token in the buffer?
  43. Token buffer; // here is where we keep a Token put back using putback()
  44. };
  45.  
  46. //------------------------------------------------------------------------------
  47.  
  48. // The constructor just sets full to indicate that the buffer is empty:
  49. Token_stream::Token_stream()
  50. :full(false), buffer(0) // no Token in buffer
  51. {
  52. }
  53.  
  54. //------------------------------------------------------------------------------
  55.  
  56. // The putback() member function puts its argument back into the Token_stream's buffer:
  57. void Token_stream::putback(Token t)
  58. {
  59. if (full) error("putback() into a full buffer");
  60. buffer = t; // copy t to buffer
  61. full = true; // buffer is now full
  62. }
  63.  
  64. //------------------------------------------------------------------------------
  65.  
  66. Token Token_stream::get()
  67. {
  68. if (full) { // do we already have a Token ready?
  69. // remove token from buffer
  70. full=false;
  71. return buffer;
  72. }
  73.  
  74. char ch;
  75. cin >> ch; // note that >> skips whitespace (space, newline, tab, etc.)
  76.  
  77. switch (ch) {
  78. case ';': // for "print"
  79. case 'q': // for "quit"
  80. case '(': case ')': case '+': case '-': case '*': case '/':
  81. return Token(ch); // let each character represent itself
  82. case '.':
  83. case '0': case '1': case '2': case '3': case '4':
  84. case '5': case '6': case '7': case '9':
  85. {
  86. cin.putback(ch); // put digit back into the input stream
  87. double val;
  88. cin >> val; // read a floating-point number
  89. return Token('8',val); // let '8' represent "a number"
  90. }
  91. default:
  92. error("Bad token");
  93. }
  94. }
  95.  
  96. //------------------------------------------------------------------------------
  97.  
  98. Token_stream ts; // provides get() and putback()
  99.  
  100. //------------------------------------------------------------------------------
  101.  
  102. double expression(); // declaration so that primary() can call expression()
  103.  
  104. //------------------------------------------------------------------------------
  105.  
  106. // deal with numbers and parentheses
  107. double primary()
  108. {
  109. Token t = ts.get();
  110. switch (t.kind) {
  111. case '(': // handle '(' expression ')'
  112. {
  113. double d = expression();
  114. t = ts.get();
  115. if (t.kind != ')') error("')' expected");
  116. return d;
  117. }
  118. case '8': // we use '8' to represent a number
  119. return t.value; // return the number's value
  120. default:
  121. error("primary expected");
  122. }
  123. }
  124.  
  125. //------------------------------------------------------------------------------
  126.  
  127. // deal with *, /, and %
  128. double term()
  129. {
  130. double left = primary();
  131. Token t = ts.get(); // get the next token from token stream
  132.  
  133. while(true) {
  134. switch (t.kind) {
  135. case '*':
  136. left *= primary();
  137. t = ts.get();
  138. case '/':
  139. {
  140. double d = primary();
  141. if (d == 0) error("divide by zero");
  142. left /= d;
  143. t = ts.get();
  144. break;
  145. }
  146. default:
  147. ts.putback(t); // put t back into the token stream
  148. return left;
  149. }
  150. }
  151. }
  152.  
  153. //------------------------------------------------------------------------------
  154.  
  155. // deal with + and -
  156. double expression()
  157. {
  158. double left = term(); // read and evaluate a Term
  159. Token t = ts.get(); // get the next token from token stream
  160.  
  161. while(true) {
  162. switch(t.kind) {
  163. case '+':
  164. left += term(); // evaluate Term and add
  165. t = ts.get();
  166. break;
  167. case '-':
  168. left -= term(); // evaluate Term and subtract
  169. t = ts.get();
  170. break;
  171. default:
  172. ts.putback(t); // put t back into the token stream
  173. return left; // finally: no more + or -: return the answer
  174. }
  175. }
  176. }
  177.  
  178. //------------------------------------------------------------------------------
  179.  
  180. int main()
  181. try
  182. {
  183. double val = 0;
  184. while (cin) {
  185. Token t = ts.get();
  186.  
  187. if (t.kind == 'q') break; // 'q' for quit
  188. if (t.kind == ';') // ';' for "print now"
  189. cout << "=" << val << '\n';
  190. else
  191. ts.putback(t);
  192. val = expression();
  193. }
  194. keep_window_open();
  195. }
  196. catch (exception& e) {
  197. cerr << "error: " << e.what() << '\n';
  198. keep_window_open();
  199. return 1;
  200. }
  201. catch (...) {
  202. cerr << "Oops: unknown exception!\n";
  203. keep_window_open();
  204. return 2;
  205. }
  206.  
  207. //------------------------------------------------------------------------------
  208.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout

Standard output is empty