Advertisement
chevengur

Chapter 6: excercise 2-3

Aug 21st, 2023 (edited)
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.47 KB | None | 0 0
  1. //
  2. // Stroustrup - Programming Principles & Practice
  3. //
  4. // Chapter 6 - Calculator
  5. //
  6. // упражнение 2 - Добавить в использование {} {(4+5)*6}/(3+4)};
  7. //
  8. // упражнение 3 - Добавить факториал '!'.
  9. //
  10.  
  11. #include "std_lib_facilities.h"
  12.  
  13. class Token {
  14. public:
  15.     char kind;
  16.     double value;
  17.  
  18.     Token(char k) : kind{ k }, value{ 0 } { }
  19.     Token(char k, double v) : kind{ k }, value{ v } { }
  20. };
  21.  
  22. class Token_stream {
  23. public:
  24.     Token get();                // get a Token
  25.     void putback(Token t);      // put a token back
  26. private:
  27.     bool full { false };        // is there a Token in the buffer?
  28.     Token buffer{ '0' };         // here is where putback() stores a Token
  29. };
  30.  
  31. void Token_stream::putback(Token t)
  32. {
  33.     buffer = t;                 // copy t to buffer
  34.     full = true;                // buffer is now full
  35. };
  36.  
  37. Token Token_stream::get()
  38. // ex 2 - added '{' & '}'
  39. // ex 3 - added '!'
  40. {
  41.     if (full) {             // do we already have a Token?
  42.         full = false;       // remove Token from buffer
  43.         return buffer;
  44.     }
  45.  
  46.     char ch;
  47.     cin >> ch;              // note that >> skips whitespace
  48.  
  49.     switch (ch) {
  50.     case ';':           // for "print"
  51.     case 'q':           // for "quit"
  52.     case '(': case ')': case '{': case '}': case '!':
  53.     case '+': case '-': case '*': case '/':
  54.         return Token{ ch };
  55.     case '.':
  56.     case '0': case '1': case '2': case '3': case '4':
  57.     case '5': case '6': case '7': case '8': case '9':
  58.     {
  59.         cin.putback(ch);    // put digit back into input stream
  60.         double val;
  61.         cin >> val;
  62.         return Token{ '8', val };  // let '8' represent a number
  63.     }
  64.     default:
  65.         error("Bad token");
  66.     }
  67. };
  68.  
  69. Token_stream ts;            // provides get() and putback()
  70. double expression();        // forward declaration for primary to call
  71.  
  72. double primary()            // deal with numbers and parenthesis
  73. // ex 2 - added '{' case
  74. {
  75.     Token t = ts.get();
  76.     switch (t.kind) {
  77.     case '(':                   // handle '(' expression ')'
  78.     {
  79.         double d = expression();
  80.         t = ts.get();
  81.         if (t.kind != ')')
  82.             error("')' expected");
  83.         return d;
  84.     }
  85.     case '{':
  86.     {
  87.         double d = expression();
  88.         t = ts.get();
  89.         if (t.kind != '}')
  90.             error("'}' excepted");
  91.         return d;
  92.     }
  93.     case '8':                   // we use '8' to represent a number
  94.         return t.value;         // return the number's value
  95.     default:
  96.         error("primary expected");
  97.     }
  98. }
  99.  
  100. double secondary(){
  101.     double left = primary();
  102.     Token t = ts.get();
  103.  
  104.     while (true) {
  105.         if (t.kind == '!') {
  106.             if (left == 0)
  107.                 return 1;
  108.  
  109.             for (int i = left - 1; i > 0; --i)
  110.                 left *= i;
  111.  
  112.             t = ts.get();
  113.         }
  114.         else {
  115.             ts.putback(t);
  116.             return left;
  117.         }
  118.     }
  119. }
  120.  
  121. double term()              
  122. {
  123.     double left = secondary();
  124.     Token t = ts.get();            
  125.  
  126.     while (true) {
  127.         switch (t.kind) {
  128.         case '*':
  129.             left *= secondary();
  130.             t = ts.get();
  131.             break;
  132.         case '/':
  133.         {
  134.             double d = secondary();
  135.             if (d == 0) error("divide by zero");
  136.             left /= d;
  137.             t = ts.get();
  138.             break;
  139.         }
  140.         default:
  141.             ts.putback(t);      
  142.             return left;
  143.         }
  144.     }
  145. }
  146.  
  147. double expression()        
  148. {
  149.     double left = term();          
  150.     Token t = ts.get();            
  151.  
  152.     while (true) {
  153.         switch (t.kind) {
  154.         case '+':
  155.             left += term();    
  156.             t = ts.get();
  157.             break;
  158.         case '-':
  159.             left -= term();    
  160.             t = ts.get();
  161.             break;
  162.         default:
  163.             ts.putback(t);      
  164.             return left;
  165.         }
  166.     }
  167. }
  168.  
  169. int main()
  170. try {
  171.     double val = 0;
  172.     while (cin) {
  173.         Token t = ts.get();
  174.  
  175.         if (t.kind == 'q') break;       // 'q' for "quit"
  176.         if (t.kind == ';')              // ';' for "print now"
  177.             cout << "=" << val << '\n';
  178.         else
  179.             ts.putback(t);
  180.         val = expression();
  181.     }
  182. }
  183. catch (exception& e) {
  184.     cerr << "Exception: " << e.what() << '\n';
  185.     return 1;
  186. }
  187. catch (...) {
  188.     cerr << "Unknown exception\n";
  189.     return 2;
  190. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement