Advertisement
Korotkodul

calculator

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