代码改变世界

一个c++做的计算器

2008-11-27 17:17  Iron  阅读(1008)  评论(0编辑  收藏  举报
今天看了一本书,有个用c++写的计算器,简洁明了,共享出来
  1 #include <iostream>
  2 #include <stack>
  3 #include <cstdlib>
  4 #include <cstring>
  5 using namespace std;
  6 double read_and_evaluate(istream & ins);
  7 void evaluate_stack_tops(stack <double> &numbers, stack<char> &operations);
  8 int main()
  9 {
 10     double answer;
 11     cout << "input a expression:" << endl;
 12     answer = read_and_evaluate(cin);
 13     cout << "The result of your expression is :" << answer << endl;
 14     return 1;
 15 }
 16 double read_and_evaluate(istream & ins)
 17 {
 18     const char DECIMAL = '.';
 19     const char RIGHT_PARENTHESIS = ')';
 20     stack<double> numbers;
 21     stack<char> operations;
 22     double number;
 23     char symbol;
 24     while(ins && ins.peek() != '\n')
 25     {
 26         if( isdigit(ins.peek()) || (ins.peek() == DECIMAL) )
 27         {
 28             ins >> number;
 29             //测试
 30             cout << number <<endl;
 31             numbers.push(number);
 32         }
 33         else if(strchr( "+-*/", ins.peek() ) != NULL)
 34         {
 35             ins >> symbol;
 36             operations.push(symbol);
 37         }
 38         else if( ins.peek() == RIGHT_PARENTHESIS )
 39         {
 40             ins.ignore();
 41             evaluate_stack_tops( numbers, operations );
 42         }
 43         else
 44         {
 45             ins.ignore();
 46         }
 47     }
 48     return numbers.top();
 49 }
 50 void evaluate_stack_tops(stack <double> &numbers, stack<char> &operations)
 51 {
 52     double operand1, operand2;
 53 
 54     operand2 = numbers.top();
 55     numbers.pop();
 56     operand1 = numbers.top();
 57     numbers.pop();
 58     switch(operations.top())
 59     {
 60         case '+':
 61             numbers.push(operand1 + operand2);
 62             break;
 63         case '-':
 64             numbers.push(operand1 - operand2);
 65             break;
 66         case '*':
 67             numbers.push(operand1 * operand2);
 68             break;
 69         case '/':
 70             numbers.push(operand1 / operand2);
 71             break;
 72     }
 73     operations.pop();
 74 }
 75 //以下是自己写的,算是做个笔记
 76 #include <iostream>
 77 #include <stack>
 78 using namespace std;
 79 const int EXIT_SUCESS = 1;
 80 //判断是否为数字
 81 bool isNumber(char single_char)
 82 {
 83     if(single_char >= '0' && single_char <= '9')
 84         return true;
 85     else
 86         return false;
 87 }
 88 //计算器类
 89 class Calculator
 90 {
 91     public:
 92         char decimalPoint;
 93         char rightBracket;
 94         string operationString;
 95         double result;
 96         stack<double> numbers;
 97         stack<char> operations;
 98         Calculator();
 99         void getAndtranslateexpression(istream & ins);
100         double calculate();
101         void clear();//清空堆栈
102 };
103 //计算类构造函数
104 Calculator::Calculator()
105 {
106     decimalPoint = '.';
107     rightBracket = ')';
108     operationString = "+-*/";
109 }
110 void Calculator::getAndtranslateexpression( istream & ins )
111 {
112     double number;
113     char operation;
114     //清理堆栈
115     this->clear();
116     //进行计算
117     while( ins && ins.peek() != '\n')
118     {
119         if( isNumber(ins.peek()) || ins.peek() == decimalPoint )
120         {
121             ins >> number;
122             numbers.push(number);
123         }
124         else if( operationString.find( ins.peek() ) != string::npos )
125         {
126             ins >> operation;
127             operations.push( operation );
128         }
129         else if( ins.peek() == ')' )
130         {
131             ins.ignore();
132             calculate();
133         }
134         else
135         {
136             ins.ignore();
137         }
138     }
139     ins.ignore();
140     //末尾没加括号处理
141     while( numbers.size() != 1 )
142     {
143         calculate();
144     }
145     //赋结果给result
146     result = numbers.top();
147 }
148 //计算处理函数
149 double Calculator::calculate()
150 {
151     double number1 , number2;
152     char operation;
153     number2 = numbers.top();
154     numbers.pop();
155     number1 = numbers.top();
156     numbers.pop();
157     operation = operations.top();
158     operations.pop();
159     switch(operation)
160     {
161         case '+':
162             numbers.push(number1 + number2);
163             break;
164         case '-':
165             numbers.push(number1 - number2);
166             break;
167         case '*':
168             numbers.push(number1 * number2);
169             break;
170         case '/':
171             numbers.push(number1 / number2);
172             break;
173     }
174 }
175 void Calculator::clear()
176 {
177     //清理堆栈
178     while( !numbers.empty() )
179     {
180         numbers.pop();
181     }
182     while( !operations.empty() )
183     {
184         operations.pop();
185     }
186 }
187 int main()
188 {
189     double expressionAnswer;
190     cout << "Input a expression:" <<endl;
191     Calculator* myCalculator = new Calculator();
192     while(1)
193     {
194         myCalculator->getAndtranslateexpression(cin);
195         cout << "The expression's result is " << myCalculator->result <<endl;
196     }
197     delete myCalculator;
198     return EXIT_SUCESS;
199 }
200 以上两个都是直接接收控制台输入而进行计算的,而且必须输入全括号的,这样的话C++就比java或其他语言有了优势,因为c++的cin很强大,但是全括号不符合人们的习惯,cin高级使用也使程序移植产生很大困难,于是我写了一个基于处理字符串表达式的计算器,参考了上面提到的那本书和严蔚敏的《数据结构》,现把c++源码贴出来,希望大家批评指正:
201 //============================================================================
202 // Name        : myCalculator.cpp
203 // Author      :
204 // Version     :
205 // Copyright   : Your copyright notice
206 // Description : Hello World in C++, Ansi-style
207 //============================================================================
208 
209 #include <iostream>
210 #include <stack>
211 #include <vector>
212 #include <cstdlib>
213 using namespace std;
214 //主函数执行完毕返回EXIT_SUCESS
215 const int EXIT_SUCESS = 1;
216 
217 //判断是否为数字
218 bool isNumberorpoint(char single_char)
219 {
220     if((single_char >= '0' && single_char <= '9') || (single_char == '.'))
221         return true;
222     else
223         return false;
224 }
225 //过滤字符串,将空格过滤掉
226 void trimString(string& myString)
227 {
228     //建立新字符串,接收过滤后的字符,然后将字串值返回给原来字串
229     string tempString;
230     for( unsigned i = 0; i < myString.length(); ++i )
231     {
232         if(myString.at(i) != ' ')
233         {
234             tempString += myString.at(i);
235         }
236     }
237     myString = tempString;
238 }
239 //判断运算符优先级
240 char compare(char topChar , char newTopChar)
241 {
242     char operationAera[7][7] = {
243             {'>' , '>' , '<' , '<' , '<' , '>' , '>'},
244             {'>' , '>' , '<' , '<' , '<' , '>' , '>'},
245             {'>' , '>' , '>' , '>' , '<' , '>' , '>'},
246             {'>' , '>' , '>' , '>' , '<' , '>' , '>'},
247             {'<' , '<' , '<' , '<' , '<' , '=' , ' '},
248             {'>' , '>' , '>' , '>' , ' ' , '>' , '>'},
249             {'<' , '<' , '<' , '<' , '<' , ' ' , '='}
250         };
251     int topCharindex,newTopCharindex;
252     switch(topChar)
253     {
254         case '+':
255             topCharindex = 0;
256             break;
257         case '-':
258             topCharindex = 1;
259             break;
260         case '*':
261             topCharindex = 2;
262             break;
263         case '/':
264             topCharindex = 3;
265             break;
266         case '(':
267             topCharindex = 4;
268             break;
269         case ')':
270             topCharindex = 5;
271             break;
272         case '#':
273             topCharindex = 6;
274             break;
275     }
276     switch(newTopChar)
277         {
278             case '+':
279                 newTopCharindex = 0;
280                 break;
281             case '-':
282                 newTopCharindex = 1;
283                 break;
284             case '*':
285                 newTopCharindex = 2;
286                 break;
287             case '/':
288                 newTopCharindex = 3;
289                 break;
290             case '(':
291                 newTopCharindex = 4;
292                 break;
293             case ')':
294                 newTopCharindex = 5;
295                 break;
296             case '#':
297                 newTopCharindex = 6;
298                 break;
299         }
300     //cout << operationAera[topCharindex][newTopCharindex]<<endl;
301     return operationAera[topCharindex][newTopCharindex];
302 }
303 //计算器类
304 class Calculator
305 {
306     public:
307         char decimalPoint;
308         char rightBracket;
309         string operationString;
310         double result;
311         stack<double> numbers;
312         stack<char> operations;
313         Calculator();
314         //void getAndtranslateexpression(istream & ins);
315         void getAndtranslateexpression( string & insString );
316         void calculate();
317         void clear();//清空堆栈
318 };
319 //计算类构造函数
320 Calculator::Calculator()
321 {
322     //以下三句都是为cin版的getAndtranslateexpression服务的
323     decimalPoint = '.';
324     rightBracket = ')';
325     operationString = "+-*/";
326 }
327 //直接接收cin而进行计算,但这样就只能是全括号的表达式才能正确求值
328 /*void Calculator::getAndtranslateexpression( istream & ins )
329 {
330     double number;
331     char operation;
332     //清理堆栈
333     this->clear();
334     //进行计算
335     while( ins && ins.peek() != '\n')
336     {
337         if( isNumberorpoint(ins.peek()) || ins.peek() == decimalPoint )
338         {
339             ins >> number;
340             numbers.push(number);
341         }
342         else if( operationString.find( ins.peek() ) != string::npos )
343         {
344             ins >> operation;
345             operations.push( operation );
346         }
347         else if( ins.peek() == ')' )
348         {
349             ins.ignore();
350             calculate();
351         }
352         else
353         {
354             ins.ignore();
355         }
356     }
357     ins.ignore();
358     //末尾没加括号处理
359     while( numbers.size() != 1 )
360     {
361         calculate();
362     }
363     //赋结果给result
364     result = numbers.top();
365 }*/
366 //getAndtranslateexpression函数string版
367 void Calculator::getAndtranslateexpression( string & insString )
368 {
369     unsigned currentPosOfinsString = 0;
370     unsigned numberEndpos = 0;
371     trimString(insString);
372     insString += '#';
373     double number;
374     char operation , lastOperation;
375     operations.push('#');
376     for( currentPosOfinsString = 0; currentPosOfinsString < insString.length(); ++currentPosOfinsString )
377     {
378         numberEndpos = currentPosOfinsString;
379         loop:
380         currentPosOfinsString = numberEndpos;
381         operation = insString.at(currentPosOfinsString);
382         if( currentPosOfinsString == 0 )
383         {
384             lastOperation = '1';//这里是数字说小数点字符就行
385         }
386         else
387         {
388         lastOperation = insString.at(currentPosOfinsString - 1);
389         }
390         //cout <<operation<<endl;
391         if( operation == '-' && !isNumberorpoint( lastOperation ) )
392         {
393             //如果为负数,则特别处理
394             ++numberEndpos;
395             for( int j = currentPosOfinsString + 1; currentPosOfinsString < insString.length(); j++ )
396                         {
397                             if( isNumberorpoint( insString.at( j ) ) )
398                             {
399                                 ++numberEndpos;//标记向后移
400                             }
401                             else
402                             {
403                                 break;
404                             }
405                         }
406             //cout << currentPosOfinsString <<endl;
407             //cout<< insString.substr(currentPosOfinsString , numberEndpos - currentPosOfinsString) <<endl;
408             number = atof(insString.substr(currentPosOfinsString , numberEndpos - currentPosOfinsString).c_str());
409             numbers.push(number);
410             cout <<number<<endl;
411             currentPosOfinsString = numberEndpos;
412             goto loop;//用当前非数字字符继续进行判断,这里如果用continue,那当前的非数字字符,将不被下一次读取,也就是,处理过程将它漏掉了,这是程序所不允许的
413         }
414         else if( isNumberorpoint( operation ) )
415         {
416             for( int j = currentPosOfinsString; currentPosOfinsString < insString.length(); j++ )
417             {
418                 if( isNumberorpoint( insString.at( j ) ) )
419                 {
420                     ++numberEndpos;//标记向后移
421                 }
422                 else
423                 {
424                     break;
425                 }
426             }
427             //cout << currentPosOfinsString <<endl;
428             //cout<< insString.substr(currentPosOfinsString , numberEndpos - currentPosOfinsString) <<endl;
429             number = atof(insString.substr(currentPosOfinsString , numberEndpos - currentPosOfinsString).c_str());
430             numbers.push(number);
431             cout <<number<<endl;
432             currentPosOfinsString = numberEndpos;
433             goto loop;//用当前非数字字符继续进行判断,这里如果用continue,那当前的非数字字符,将不被下一次读取,也就是,处理过程将它漏掉了,这是程序所不允许的
434         }
435         else
436         {
437             //++numberEndpos;
438             //currentPosOfinsString = numberEndpos;
439             //cout<< operation <<endl;
440             switch(compare( operations.top() , operation ))
441             {
442                 //算术过程
443                 case '<':
444                     operations.push( operation );
445                     break;
446                 case '=':
447                     operations.pop();
448                     break;
449                 case '>':
450                     calculate();
451                     goto loop;//用当前非数字字符继续进行判断,例如如果当前是')',那么括号内算完后还得执行一次此过程,使得左括号从栈中消去
452                     break;
453             }
454         }
455     }
456     result = numbers.top();
457 }
458 //计算处理函数
459 void Calculator::calculate()
460 {
461     double number1 , number2;
462     char operation;
463     number2 = numbers.top();
464     numbers.pop();
465     number1 = numbers.top();
466     numbers.pop();
467     operation = operations.top();
468     operations.pop();
469     switch(operation)
470     {
471         case '+':
472             numbers.push(number1 + number2);
473             break;
474         case '-':
475             numbers.push(number1 - number2);
476             break;
477         case '*':
478             numbers.push(number1 * number2);
479             break;
480         case '/':
481             numbers.push(number1 / number2);
482             break;
483     }
484 }
485 void Calculator::clear()
486 {
487     //清理堆栈
488     while( !numbers.empty() )
489     {
490         numbers.pop();
491     }
492     while( !operations.empty() )
493     {
494         operations.pop();
495     }
496 }
497 int main()
498 {
499     cout << "Input a expression:" <<endl;
500     Calculator* myCalculator = new Calculator();
501     string expression;// = "3-(7.2*2)";
502     cin >> expression;
503     myCalculator->getAndtranslateexpression(expression);
504     cout << "The expression's result is " << myCalculator->result <<endl;
505     delete myCalculator;
506     return EXIT_SUCESS;
507 }