栈的应用——实现简易计算器(一)

来源:互联网 发布:多益网络 人事工资 编辑:程序博客网 时间: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
原创粉丝点击