考研机试:C++栈实现简单计算器的实现

        本文记录了简单计算器的实现思路、易错点以及cpp的代码实现

题目描述

        输入输出描述:实现一个没有括号的计算器,输入中没有空格输出计算结果。

实现思路

        总体的实现思路是借助栈,当遇见数字时压入数字栈,遇见符号时候压入符号栈之前进行比较,比栈顶高级就压入,比栈顶低级就弹出栈顶符号以及两个数字用于计算,将计算结果重新入数字栈。

        原理其实借助了逆波兰表达式,在这里解释一下为什么要进行符号比较。假设栈中有一个+,此时来了一个*,但是*不知道后面是否有比自己优先级更高的,所以先压入栈等待。若又来了一个-,那么此时*就是最高级了,他就可以运算了,并且-还不能入栈,因为+和它是同级,但是+先来,所以按顺序来说需要先算+,所以-需要一直比较到有一个比他级别低或者栈空的情况才能入栈。

        在实现中有一个很聪明的思路,就是借助两个永不会出现在表达式中的符号来协助实现。#用于表示栈底,是优先级最低的符号;$用来加在表达式字符串之后,用于表示表达式已结束,优先级次低。这两个符号的联合使用可以简化操作并且同一逻辑。

        #优先级最低,所以面对任何符号都可以直接入栈而不用考虑是否栈空。$优先级仅高于#,所以在$入栈时表示栈中没有比他更高级的符号,也就意味着表达式中所有符号已经扫描完毕,也就是计算结果已经可以读取了。

        最后说一下如何获取数字的操作。因为是字符串,所以数字每位都是字符,所以要获取两位及以上的数字,需要定义一个函数。注意为了把string变成数字要-’0‘.

int Getnumber(string str,int&i){
    int num=0;
    while(isdigit(str[i])){
        num=num*10+str[i]-'0';
        i++;
    }
    return num;
}

易错点

        除了上面的-’0‘,在实现中,最容易错的是double会定义成int,这样会导致小数四舍五入结果出错。所以在涉及到计算的部分已经数据储存的栈或者是临时变量,都要是double类型。没注意这些细节,所以这些问题耗费了很多时间。

        还有在计算表达式时,注意参数x与y的相对位置,x在y上面,意味着其比y后出现,按从左到右的计算顺序应该是y+-*/x。

代码实现

#include <iostream>
#include<stack>
#include<string>
using namespace std;

int Getnumber(string str,int&i){
    int num=0;
    while(isdigit(str[i])){
        num=num*10+str[i]-'0';
        i++;
    }
    return num;
}

int Compare(char op){
    if(op=='#'){
        return 0;
    }
    if(op=='$'){
        return 1;
    }
    if(op=='+'||op=='-'){
        return 2;
    }
    else{
        return 3;
    }
}

double Caculate(double x,double y,char op){//注意顺序,x栈位置在y前,表示其出现在y之后
    if(op=='+'){
        return x+y;
    }
    if(op=='*'){
        return x*y;
    }
    if(op=='-'){
        return y-x;
    }
    else{
        return y/x;
    }
}

int main() {
    string str;
    stack<double>data;
    stack<char>oper;
    while(getline(cin,str)){
        int i=0;
        str+="$";
        oper.push('#');
        while(i<str.size()){
            if(isdigit(str[i])){
                data.push(Getnumber(str,i));
            }
            else{
                if(Compare(str[i])>Compare(oper.top())){
                    oper.push(str[i]);
                    i++;
                }
                else{
                    char o=oper.top();
                    oper.pop();
                    double x=data.top();//一定是double!!!
                    data.pop();
                    double y=data.top();
                    data.pop();
                    data.push(Caculate(x,y,o));
                }
            }
        }
        cout<<data.top()<<endl;
    }
}

结果示意: 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值