栈的应用——实现简易计算器(一)
来源:互联网 发布:多益网络 人事工资 编辑:程序博客网 时间:2024/05/16 08:43
周日晚上心血来潮,想用栈做个简单的计算器,于是便动手鼓捣了。参照书上的思想,我用了两个栈来解决这个问题。
1)栈S1用来存放运算符,栈S2用来存放操作数。由于运算符为char型而操作数为int型,因此,需要使用类模板来声明两个不同数据类型的栈。
2)为简单起见,只能计算0-9之内的数(由于每次只能读入一个字符入栈,如果是大于等于10的任意数,就要设计另外的算法使“相邻”的两个数字组合为一个数)。
3)运算符涉及优先级的问题,为此,需要一个判断优先级的函数Priority(),该函数返回运算符的优先级。现在的问题是,对于最初输入以及最后入栈的运算符,它与谁进行比较?为此,先将一符号“#”压入栈中作为栈底,并且在输入表达式时以“#”号结尾。一开始我在Priority()函数中令“#”的优先级最低,但之后我发现有更为简便的方法:在该函数中只要遇到“#”或“(”或“)”,就返回-1,对于“(”还有另一更简单的处理方式:只要一读入“(”,就让其入栈。从代码中可以知道,这两种处理方式是不冲突的。
这是本人做的第一个“小程序”,虽然到了这一步仍然只能计算10以内的整数的加减乘除,但是这毕竟是多次调试、改错并优化后的结果,在这个过程中也得到了很多经验,对栈的理解也更透彻了。本来想把之前阶段性的代码贴出来,并附上解决方法,但由于没有保存之前的代码,那些碰到的问题以及解决方法都无法分享了sigh。
以下为完整代码:
#include"SeqStack.h" //该头文件的声明在另一篇博客中int Calculate(SeqStack<char>&);int Priority(char);int Priority(char op) //判断输入的运算符的优先级{ switch(op){ case '+': case '-':return 1; case '*': case '/':return 2; default: return -1; }}int Calculate(SeqStack<char>& S1) //S1为char型的栈,用于存放运算符{ SeqStack<int>S2; //S2为int型的栈,用于存放操作数 char ch,a,b,c,d,m,n,p,t; int op1,op2,op3,op4,op5,op6,op7,op8,a1,a2,n1,n2; S1.push('#'); //先将#存入栈S1中 cout<<"请输入需要计算的表达式(表达式需以#结尾):\n"; do{ ch = getchar(); switch(ch){ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': S2.push(ch - '0'); //将char型的数值转换为int型并压入栈S2中 break; case ' ': //若输入的表达式含有空格,则转入下一字符 break; case '+': if(Priority(S1.get_top()) < Priority('+')) //若当前栈顶运算符优先级低于‘+’,则将当前扫描到的字符‘+’入栈 S1.push('+'); else{ S2.pop(op1); S2.pop(op2); //将栈S2最外面的两个数字弹出 if(S1.get_top() == '+') //判断S1栈顶的运算符,以做出相应的运算 S2.push(op2 + op1); else if(S1.get_top() == '-') S2.push(op2 - op1); else if(S1.get_top() == '*') S2.push(op2 * op1); else S2.push(op2 / op1); S1.pop(c); //该运算符已做过相应的运算,出栈 S1.push('+'); //将‘+’压入栈中,作为S1新的栈顶 } break; case '-': if(Priority(S1.get_top()) < Priority('-')) S1.push('-'); else{ S2.pop(op3); S2.pop(op4); if(S1.get_top() == '+') S2.push(op4 + op3); else if(S1.get_top() == '-') S2.push(op4 - op3); else if(S1.get_top() == '*') S2.push(op4 * op3); else S2.push(op4 / op3); S1.pop(d); S1.push('-'); } break; case '*': if(Priority(S1.get_top()) < Priority('*')) S1.push('*'); else{ S2.pop(op5); S2.pop(op6); if(S1.get_top() == '+') S2.push(op6 + op5); else if(S1.get_top() == '-') S2.push(op6 - op5); else if(S1.get_top() == '*') S2.push(op6 * op5); else S2.push(op6 / op5); S1.pop(t); S1.push('*'); } break; case '/': if(Priority(S1.get_top()) < Priority('/')) S1.push('/'); else{ S2.pop(op7); S2.pop(op8); if(S1.get_top() == '+') S2.push(op8 + op7); else if(S1.get_top() == '-') S2.push(op8 - op7); else if(S1.get_top() == '*') S2.push(op8 * op7); else S2.push(op8 / op7); S1.pop(m); S1.push('/'); } break; case '(': //只要一遇到左括号,即将其压入栈中 S1.push('('); break; case ')': do{ S2.pop(n1); S2.pop(n2); if(S1.get_top() == '+') S2.push(n2 + n1); else if(S1.get_top() == '-') S2.push(n2 - n1); else if(S1.get_top() == '*') S2.push(n2 * n1); else S2.push(n2 / n1); S1.pop(n); //将已参加过运算的运算符出栈 }while(S1.get_top() != '('); //通过该循环保证括号中的所有表达式已计算完毕 S1.pop(p); //更重要的是要将左括号退出 右括号从未进栈 break; case '#': //输入的表达式需以#结尾,方便判断运算符的优先级 S2.pop(a1); S2.pop(a2); if(S1.get_top() == '+') S2.push(a2 + a1); else if(S1.get_top() == '-') S2.push(a2 - a1); else if(S1.get_top() == '*') S2.push(a2 * a1); else S2.push(a2 / a1); S1.pop(a); //将当前运算符出栈 S1.pop(b); //将栈底的#出栈,至此,栈S1已空。 break; default: break; } }while(ch != '\n'); //若扫描至换行符,则退出循环,至此,表达式计算完成。 return S2.get_top(); //S2的栈底元素即为最终的结果}int main(){ SeqStack<char>S; cout<<Calculate(S);}
标题上加了个(一),希望之后会有(二)甚至更多的文章吧,把这个计算器再优化些,功能再丰富些:)
附一张模拟表达式出栈、入栈过程的手稿:
0 0
- 栈的应用——实现简易计算器(一)
- 简易计算器实现混合运算——栈的应用
- 简易计算器(栈的应用)
- 栈的应用之简易计算器的实现
- linux 下Qt初级教程(一)实现简易的计算器
- 栈应用之简易计算器算法的原理及实现(C语言)
- iPhone应用开发——简易计算器的设计
- 简易计算器的实现
- 简易计算器的实现
- 简易计算器的实现
- 简易计算器的实现
- 使命栈(stack)实现一个简易的四则运算计算器
- 单片机: 简易计算器的实现(键盘)
- 栈的应用:进制转换和简易计算器的实现
- 简单控件的应用(一)—prj计算器
- C# 简易计算器(一)
- 一个简易计算器的实现
- Swing实现的简易计算器
- js 文本框键盘输入事件
- 程序员编写技术文档的新手指南
- HDOJ 2011 多项式求和
- Linux入门
- java中API文档开头内容解释一下?
- 栈的应用——实现简易计算器(一)
- JFinal+amazeUI+beetl+layer+shiro+poi+restful+handlebars初认识
- GridView 中取值的方法汇总
- C++类成员的初始化
- 机器学习基础(三十一)—— 岭回归(Ridge Regression)到 LASSO
- git 版本控制 回退 修改
- Java防止xss攻击
- hdu 1286 找新朋友
- 如何判断Textview中的文字是否被截断