表达式求值

#include <iostream>
#include <stack>
#include <cmath>
using namespace std;
class calc{
    char* expression;
    enum token{OPAREN ,ADD ,SUB ,MULTI, DIV, EXP, CPAREN, VALUE, EOL};//已经按照优先级排列了:whyEOL:类比EOF(文档的结束),这里是表达式的结束
    void BinaryOp(token op,stack<int>&dataStack);//要是对栈操作要&
    token getOp(int &value);
public:
    calc(char *s){
        expression=new char[strlen(s)];
        strcpy(expression,s);//这两个顺序别反了
    }
    ~calc(){
        delete expression;
    }
    int result();
};
//控制计算先后
int calc::result(){
    token lastOp,topOp;
    int resultValue=0,currentValue=0;
    stack<int>dataStack;
    stack<token>opStack;//注意这个类型
    char *str=expression;//提前保留expression的第一个位置指针。
    while ((lastOp=getOp(currentValue))!=EOL) {//这里一定要加(),C++短路求值,先判断左边的条件,再右边。搞不清楚就分开来写。
        switch (lastOp) {
            case VALUE:
                dataStack.push(currentValue);
                break;
            case OPAREN:
                opStack.push(lastOp);
                    break;
            case CPAREN:
                while (!opStack.empty() && (topOp=opStack.top())!=OPAREN) {//不能写‘(’,因为栈里面存储的是token类型。
                    BinaryOp(topOp, dataStack);
                    opStack.pop();
                }
                if (topOp!=OPAREN) {
                    cerr<<"缺左括号"<<endl;
                }
                 if(opStack.top()==OPAREN)opStack.pop();//把‘(’pop
                break;
            case MULTI:case DIV: case ADD:case SUB:
                while (!opStack.empty() && (topOp=opStack.top())>=lastOp) {
                    BinaryOp(topOp, dataStack);
                    opStack.pop();
                }//注意是while!!
                opStack.push(lastOp);//最后自己肯定要入栈
                break;
            case EXP:
                opStack.push(EXP);
                break;
            default:
                break;
        }
    }
    while (!opStack.empty()) {
        BinaryOp(opStack.top(), dataStack);
        opStack.pop();
    }
    //结果处理,三种情况
    if (dataStack.empty()) {
        cerr<<"无结果"<<endl;
        return 0;
       }
    
    resultValue=dataStack.top();
    dataStack.pop();
    
    if (!dataStack.empty()) {
        cerr<<"缺操作符"<<endl;
        return 0;
    }
    expression=str;
    return resultValue;
}
//getOp:从表达式取一个合法的符号:运算符/运算数
calc::token calc::getOp(int &value){//注意:返回值token 是在calc中定义的枚举,所以要说明范围,不然找不到
    while (*expression&&*expression==' ') {//判断*expression!=NULL防止爆掉,字符串操作要注意这个
        expression++;//向后跳过空格
    }
    value=0;
    if(*expression>='0'&&*expression<='9'){
    while(*expression>='0'&&*expression<='9'){
        value=value*10+*expression-'0';
        expression++;
    }//数字处理
    return VALUE;//why return VALUE??
    }
    else{
        char e=expression[0];
        expression++;
        switch (e) {
            case '(':
                return OPAREN;
                break;
            case ')':
                return CPAREN;
                break;
            case '+':
                return ADD;
                break;
            case '-':
                return SUB;
                break;
            case '*':
                return MULTI;
                break;
            case '/':
                return DIV;
                break;
            case '^':
                return EXP;
                break;
            default:
                return EOL;
            break;
        }
    }
}
//BinaryOp:运算符与运算数的结合,也就是发生运算
void calc::BinaryOp(token op,stack<int> &dataStack){
    int num1,num2;
    if(dataStack.empty())
    {cerr<<"缺操作数!"<<endl;exit(1);}
    else {num2=dataStack.top();dataStack.pop();}
    if(dataStack.empty())
    {cerr<<"缺操作数!"<<endl;exit(1);}
    else{num1=dataStack.top();dataStack.pop();}
    switch (op) {
        case ADD:
            dataStack.push(num1+num2);
            break;
        case SUB:
            dataStack.push(num1-num2);
            break;
        case MULTI:
            dataStack.push(num1*num2);
            break;
        case DIV:
            dataStack.push(num1/num2);
            break;
        case EXP:
            dataStack.push(pow(num1,num2));
        break;
        default:
            break;
    }
}






int main() {
    char* s;
    
    cout<<"请输入要计算的表达式:"<<endl;
    cin>>s;
    calc c(s);
    cout<<c.result();
    
    return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值