zoukankan      html  css  js  c++  java
  • 表达式求值(栈方法/C++语言描述)(三)

    代码清单

      1 // calculator.h
      2 #ifndef CALCULATOR_H
      3 #define CALCULATOR_H
      4 
      5 #include <stack>
      6 #include <string>
      7 #include <iostream>
      8 #include <cassert>
      9 
     10 using namespace std;
     11 
     12 typedef enum {
     13     BEGIN,
     14     NUMBER,
     15     OPERATOR,
     16     LEFT_BRAC,
     17     RIGHT_BRAC
     18 } TokenType;
     19 
     20 class Calculator
     21 {
     22 public:
     23     double calculate(string expression) throw(string);
     24 
     25 private:
     26     stack<double> _stkNumbers;
     27     stack<char> _stkOperators;
     28 
     29     static int priority(char op);
     30     static double calculate(double d1, char op, double d2) throw(string);
     31 
     32     void calculateStack() throw(string);
     33     void dealWithNumber(char *&pToken) throw(string);
     34     void dealWithOperator(char *&pToken) throw(string);
     35     void dealWithLeftBrac(char *&pToken) throw(string);
     36     void dealWithRightBrac(char *&pToken) throw(string);
     37 };
     38 
     39 #endif // CALCULATOR_H
     40 
     41 // calculator.cpp
     42 #include "calculator.h"
     43 
     44 int Calculator::priority(char op) {
     45     assert(op == '+' || op == '-' || op == '*' || op == '/' || op == '(');
     46 
     47     if (op == '+' || op == '-') {
     48         return 1;
     49     } else if (op == '*' || op == '/') {
     50         return 2;
     51     } else {
     52         return 0;
     53     }
     54 }
     55 
     56 double Calculator::calculate(double d1, char op, double d2) throw (string) {
     57     assert(op == '+' || op == '-' || op == '*' || op == '/');
     58 
     59     cout << d1 << op << d2 << endl;
     60 
     61     if (op == '+') {
     62         return d1 + d2;
     63     } else if (op == '-') {
     64         return d1 - d2;
     65     } else if (op == '*') {
     66         return d1 * d2;
     67     } else {
     68         if (!d2) {
     69             throw string("divided by 0");
     70         }
     71         return d1 / d2;
     72     }
     73 }
     74 
     75 void Calculator::calculateStack() throw (string) {
     76     double d2 = _stkNumbers.top();
     77     _stkNumbers.pop();
     78     double d1 = _stkNumbers.top();
     79     _stkNumbers.pop();
     80     char op = _stkOperators.top();
     81     _stkOperators.pop();
     82     _stkNumbers.push(calculate(d1, op, d2));
     83 }
     84 
     85 double Calculator::calculate(string expression) throw (string) {
     86     while (!_stkNumbers.empty()) {
     87         _stkNumbers.pop();
     88     }
     89     while (!_stkOperators.empty()) {
     90         _stkOperators.pop();
     91     }
     92     TokenType lastToken = BEGIN;
     93 
     94     char * pToken = &expression[0];
     95     while (*pToken) {
     96         switch (lastToken) {
     97         case BEGIN:
     98             if (*pToken == '(') {
     99                 // an expression begin with a left bracket
    100                 dealWithLeftBrac(pToken);
    101                 lastToken = LEFT_BRAC;
    102             } else {
    103                 // or a number
    104                 dealWithNumber(pToken);
    105                 lastToken = NUMBER;
    106             }
    107             break;
    108         case NUMBER:
    109             // after a number
    110             if (*pToken == ')') {
    111                 // it may be a right bracket
    112                 dealWithRightBrac(pToken);
    113                 lastToken = RIGHT_BRAC;
    114             } else {
    115                 // it may be an operator
    116                 dealWithOperator(pToken);
    117                 lastToken = OPERATOR;
    118             }
    119             break;
    120         case OPERATOR:
    121         case LEFT_BRAC:
    122             // after an operator or a left bracket
    123             if (*pToken == '(') {
    124                 // it may be a left bracket
    125                 dealWithLeftBrac(pToken);
    126                 lastToken = LEFT_BRAC;
    127             } else {
    128                 // it may be a number
    129                 dealWithNumber(pToken);
    130                 lastToken = NUMBER;
    131             }
    132             break;
    133         case RIGHT_BRAC:
    134             // after a right bracket
    135             if (*pToken == ')') {
    136                 // it may be another right bracket
    137                 dealWithRightBrac(pToken);
    138                 lastToken = RIGHT_BRAC;
    139             } else {
    140                 // it may be an operator
    141                 dealWithOperator(pToken);
    142                 lastToken = OPERATOR;
    143             }
    144             break;
    145         }
    146     }
    147 
    148     while (!_stkOperators.empty()) {
    149         if (_stkOperators.top() == '(') {
    150             throw string("bad token '('");
    151         }
    152         calculateStack();
    153     }
    154 
    155     assert(!_stkNumbers.empty());
    156     return _stkNumbers.top();
    157 }
    158 
    159 void Calculator::dealWithNumber(char *&pToken) throw (string) {
    160     if (!isdigit(*pToken) && *pToken != '-') {
    161         throw string("bad token '") + *pToken + "'";
    162     }
    163     _stkNumbers.push(strtod(pToken, &pToken));
    164 }
    165 
    166 void Calculator::dealWithOperator(char *&pToken) throw (string) {
    167     if (*pToken != '+' && *pToken != '-' && *pToken != '*' && *pToken != '/') {
    168         throw string("bad token '") + *pToken + "'";
    169     }
    170     if (!_stkOperators.empty()
    171             && priority(_stkOperators.top()) >= priority(*pToken)) {
    172         calculateStack();
    173     }
    174     _stkOperators.push(*pToken);
    175     pToken++;
    176 }
    177 
    178 void Calculator::dealWithLeftBrac(char *&pToken) throw (string) {
    179     if (*pToken != '(') {
    180         throw string("bad token '") + *pToken + "'";
    181     }
    182     _stkOperators.push(*pToken);
    183     pToken++;
    184 }
    185 
    186 void Calculator::dealWithRightBrac(char *&pToken) throw (string) {
    187     if (*pToken != ')') {
    188         throw string("bad token '") + *pToken + "'";
    189     }
    190     while (!_stkOperators.empty() && _stkOperators.top() != '(') {
    191         calculateStack();
    192         if (_stkOperators.empty()) {
    193             throw string("bad token ')'");
    194         }
    195     }
    196     _stkOperators.pop();
    197     pToken++;
    198 }
    199 
    200 // main.cpp
    201 #include "calculator.h"
    202 
    203 int main(int argc, char *argv[])
    204 {
    205     Calculator calculator;
    206 
    207     if (argc > 1) {
    208         if (argc == 2) {
    209             cout << calculator.calculate(string(argv[1])) << endl;
    210         } else {
    211             cout << "too many arguments" << endl;
    212             return -1;
    213         }
    214     } else {
    215         while (1) {
    216             string expression;
    217             cout << ">" << flush;
    218             cin >> expression;
    219             if (expression == "quit;") {
    220                 cout << "Bye." << endl;
    221                 return 0;
    222             }
    223             try {
    224             cout << calculator.calculate(expression) << endl;
    225             } catch (string ex) {
    226                 cout << ex << endl;
    227             }
    228         }
    229     }
    230 }
  • 相关阅读:
    Machine Learning/Introducing Logistic Function
    学习Machine Leaning In Action(四):逻辑回归
    极致和厚道为小米新国货的核心实质(极致不是指最好的,而是要超乎预期)
    做事要提前留有余地,否则到时候就来不及了(超市买菜,找工作,交朋友,发脾气都是如此)
    UpdateWindow API函数的作用很明显
    近几年前端技术盘点以及 2016 年技术发展方向
    使用SetLocaleInfo设置时间后必须调用广播WM_SETTINGCHANGE,通知其他程序格式已经更改
    设计模式——(Abstract Factory)抽象工厂
    从优化到再优化,最长公共子串
    与数据库打交道的Adapter----SimpleCursorAdapter
  • 原文地址:https://www.cnblogs.com/lets-blu/p/7276022.html
Copyright © 2011-2022 走看看