代码清单
1 // binarytree.h 2 #ifndef BINARYTREE_H 3 #define BINARYTREE_H 4 5 template <typename T> class BinaryTree; 6 7 template <typename T> 8 class BinaryTreeNode 9 { 10 public: 11 friend class BinaryTree<T>; 12 friend class Calculator; 13 T _data; 14 15 private: 16 BinaryTreeNode<T> * _leftChild; 17 BinaryTreeNode<T> * _rightChild; 18 }; 19 20 template <typename T> 21 class BinaryTree 22 { 23 public: 24 BinaryTree() 25 { 26 _root = nullptr; 27 } 28 29 ~BinaryTree() 30 { 31 destory(); 32 } 33 34 void preOrder() 35 { 36 preOrder(_root); 37 } 38 39 void inOrder() 40 { 41 inOrder(_root); 42 } 43 44 void postOrder() 45 { 46 postOrder(_root); 47 } 48 49 protected: 50 BinaryTreeNode<T> * _root; 51 52 void destory() 53 { 54 if (_root) 55 { 56 destory(_root); 57 delete _root; 58 } 59 } 60 61 void destory(BinaryTreeNode<T> * node) 62 { 63 if (node) 64 { 65 destory(node->_leftChild); 66 destory(node->_rightChild); 67 // visit binary tree data 68 if (node->_leftChild) 69 { 70 delete node->_leftChild; 71 } 72 if (node->_rightChild) 73 { 74 delete node->_rightChild; 75 } 76 } 77 } 78 79 virtual void preOrder(BinaryTreeNode<T> * node) 80 { 81 if (node) 82 { 83 // visit binary tree data 84 preOrder(node->_leftChild); 85 preOrder(node->_rightChild); 86 } 87 } 88 89 virtual void inOrder(BinaryTreeNode<T> * node) 90 { 91 if (node) 92 { 93 inOrder(node->_leftChild); 94 // visit binary tree data 95 inOrder(node->_rightChild); 96 } 97 } 98 99 virtual void postOrder(BinaryTreeNode<T> * node) 100 { 101 if (node) 102 { 103 postOrder(node->_leftChild); 104 postOrder(node->_rightChild); 105 // visit binary tree data 106 } 107 } 108 }; 109 110 #endif // BINARYTREE_H 111 112 // calculator.h 113 #ifndef CALCULATOR_H 114 #define CALCULATOR_H 115 116 #include <cassert> 117 #include <string> 118 #include <stack> 119 #include <iostream> 120 #include "binarytree.h" 121 122 using namespace std; 123 124 typedef enum 125 { 126 BEGIN, 127 NUMBER, 128 OPERATOR, 129 LEFT_BRAC, 130 RIGHT_BRAC 131 } TokenType; 132 133 class Token 134 { 135 public: 136 TokenType _type; 137 union 138 { 139 char op; 140 double num; 141 } _data; 142 }; 143 144 class Calculator : public BinaryTree<Token> 145 { 146 public: 147 void parseExpression(string expression) throw(string); 148 double calculate(); 149 150 private: 151 stack<char> _stkOperators; 152 stack<BinaryTreeNode<Token> *> _stkNodes; 153 stack<double> _stkNumbers; 154 155 static int priority(char op); 156 static double calculate(double d1, char op, double d2) throw(string); 157 158 void postOrder(BinaryTreeNode<Token> * node); 159 void calculateStack() throw(string); 160 void dealWithNumber(char *&pToken) throw(string); 161 void dealWithOperator(char *&pToken) throw(string); 162 void dealWithLeftBrac(char *&pToken) throw(string); 163 void dealWithRightBrac(char *&pToken) throw(string); 164 }; 165 166 #endif // CALCULATOR_H 167 168 // calculator.cpp 169 #include "calculator.h" 170 171 int Calculator::priority(char op) 172 { 173 assert(op == '+' || op == '-' || op == '*' || op == '/' || op == '('); 174 175 if (op == '+' || op == '-') 176 { 177 return 1; 178 } 179 else if (op == '*' || op == '/') 180 { 181 return 2; 182 } 183 else 184 { 185 return 0; 186 } 187 } 188 189 double Calculator::calculate(double d1, char op, double d2) throw(string) 190 { 191 assert(op == '+' || op == '-' || op == '*' || op =='/'); 192 193 cout << d1 << op << d2 << endl; 194 195 if (op == '+') 196 { 197 return d1 + d2; 198 } 199 else if (op == '-') 200 { 201 return d1 - d2; 202 } 203 else if (op == '*') 204 { 205 return d1 * d2; 206 } 207 else 208 { 209 if (!d2) 210 { 211 throw string("divided by 0"); 212 } 213 return d1 / d2; 214 } 215 } 216 217 void Calculator::calculateStack() throw(string) 218 { 219 BinaryTreeNode<Token> * node = new BinaryTreeNode<Token>(); 220 assert(node); 221 node->_data._type = OPERATOR; 222 node->_data._data.op = _stkOperators.top(); 223 _stkOperators.pop(); 224 assert(!_stkNodes.empty()); 225 node->_rightChild = _stkNodes.top(); 226 _stkNodes.pop(); 227 assert(!_stkNodes.empty()); 228 node->_leftChild = _stkNodes.top(); 229 _stkNodes.pop(); 230 _stkNodes.push(node); 231 } 232 233 void Calculator::parseExpression(string expression) throw(string) 234 { 235 destory(); 236 while (!_stkNodes.empty()) 237 { 238 _stkNodes.pop(); 239 } 240 while (!_stkOperators.empty()) 241 { 242 _stkOperators.pop(); 243 } 244 TokenType lastToken = BEGIN; 245 246 char * pToken = &expression[0]; 247 while (*pToken) 248 { 249 switch (lastToken) 250 { 251 case BEGIN: 252 if (*pToken == '(') 253 { 254 // an expression begin with a left bracket 255 dealWithLeftBrac(pToken);; 256 lastToken = LEFT_BRAC; 257 } 258 else 259 { 260 // or a number 261 dealWithNumber(pToken); 262 lastToken = NUMBER; 263 } 264 break; 265 case NUMBER: 266 // after a number 267 if (*pToken == ')') 268 { 269 // it may be a right bracket 270 dealWithRightBrac(pToken); 271 lastToken = RIGHT_BRAC; 272 } 273 else 274 { 275 // it may be an operator 276 dealWithOperator(pToken); 277 lastToken = OPERATOR; 278 } 279 break; 280 case OPERATOR: 281 case LEFT_BRAC: 282 // after an operator or a left bracket 283 if (*pToken == '(') 284 { 285 // it may be a left bracket 286 dealWithLeftBrac(pToken); 287 lastToken = LEFT_BRAC; 288 } 289 else 290 { 291 // it may be a number 292 dealWithNumber(pToken); 293 lastToken = NUMBER; 294 } 295 break; 296 case RIGHT_BRAC: 297 // after a right bracket 298 if (*pToken == ')') 299 { 300 // it may be another right bracket 301 dealWithRightBrac(pToken); 302 lastToken = RIGHT_BRAC; 303 } 304 else 305 { 306 // it may be an perator 307 dealWithOperator(pToken); 308 lastToken = OPERATOR; 309 } 310 break; 311 } 312 } 313 314 while (!_stkOperators.empty()) 315 { 316 if (_stkOperators.top() == '(') 317 { 318 throw string("bad token '('"); 319 } 320 calculateStack(); 321 } 322 323 assert(!_stkNodes.empty()); 324 _root = _stkNodes.top(); 325 } 326 327 void Calculator::postOrder(BinaryTreeNode<Token> *node) 328 { 329 if (node) 330 { 331 postOrder(node->_leftChild); 332 postOrder(node->_rightChild); 333 // visit binary tree data 334 if (node->_data._type == NUMBER) 335 { 336 _stkNumbers.push(node->_data._data.num); 337 } 338 else 339 { 340 assert(!_stkNumbers.empty()); 341 double d2 = _stkNumbers.top(); 342 _stkNumbers.pop(); 343 assert(!_stkNumbers.empty()); 344 double d1 = _stkNumbers.top(); 345 _stkNumbers.pop(); 346 char op = node->_data._data.op; 347 _stkNumbers.push(calculate(d1, op, d2)); 348 } 349 } 350 } 351 352 double Calculator::calculate() 353 { 354 while (!_stkNumbers.empty()) 355 { 356 _stkNumbers.pop(); 357 } 358 359 BinaryTree::postOrder(); 360 361 assert(!_stkNumbers.empty()); 362 return _stkNumbers.top(); 363 } 364 365 void Calculator::dealWithNumber(char *&pToken) throw(string) 366 { 367 if (!isdigit(*pToken) && *pToken != '-') 368 { 369 throw string("bad token '") + *pToken + "'"; 370 } 371 372 BinaryTreeNode<Token> * node = new BinaryTreeNode<Token>(); 373 assert(node); 374 node->_data._type = NUMBER; 375 node->_data._data.num = strtod(pToken, &pToken); 376 node->_leftChild = node->_rightChild = nullptr; 377 _stkNodes.push(node); 378 } 379 380 void Calculator::dealWithOperator(char *&pToken) throw(string) 381 { 382 if (*pToken != '+' && *pToken != '-' && *pToken != '*' && *pToken != '/') 383 { 384 throw string("bad token '") + *pToken + "'"; 385 } 386 387 if (!_stkOperators.empty() 388 && priority(_stkOperators.top()) >= priority(*pToken)) 389 { 390 calculateStack(); 391 } 392 _stkOperators.push(*pToken++); 393 } 394 395 void Calculator::dealWithLeftBrac(char *&pToken) throw(string) 396 { 397 if (*pToken != '(') 398 { 399 throw string("bad token '") + *pToken + "'"; 400 } 401 402 _stkOperators.push(*pToken++); 403 } 404 405 void Calculator::dealWithRightBrac(char *&pToken) throw(string) 406 { 407 if (*pToken != ')') 408 { 409 throw string("bad token '") + *pToken + "'"; 410 } 411 412 while (!_stkOperators.empty() && _stkOperators.top() != '(') 413 { 414 calculateStack(); 415 if (_stkOperators.empty()) 416 { 417 throw string("bad token ')'"); 418 } 419 } 420 _stkOperators.pop(); 421 pToken++; 422 } 423 424 // main.cpp 425 #include "calculator.h" 426 427 int main(int argc, char *argv[]) 428 { 429 Calculator calculator; 430 431 if (argc > 1) 432 { 433 if (argc == 2) 434 { 435 calculator.parseExpression(string(argv[1])); 436 cout << calculator.calculate() << endl; 437 } 438 else 439 { 440 cout << "too many arguments" << endl; 441 } 442 } 443 else 444 { 445 while (1) 446 { 447 string expression; 448 cout << ">" << flush; 449 cin >> expression; 450 if (expression == "quit;") 451 { 452 cout << "Bye." << endl; 453 return 0; 454 } 455 try 456 { 457 calculator.parseExpression(expression); 458 cout << calculator.calculate() << endl; 459 } 460 catch (string ex) 461 { 462 cout << ex << endl; 463 } 464 } 465 } 466 }