表达式求值(栈方法/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 }
posted @ 2017-08-02 20:46  Lets_Blu  阅读(306)  评论(0编辑  收藏  举报