一、问题描述

中缀表达式求值
例如:2*(3+5)-7

二、解题思路

定义两个栈,一个操作数栈,一个运算符栈,首先需要定义运算符的优先级,如图。
在这里插入图片描述

将表达式的前后都加上‘#’方便操作。#2*(3+5)-7#
首先从前往后扫描字符串,当遇到操作数时,就将其压入操作数栈。当遇到运算符时,首先和运算符栈的栈顶元素比较,当小于,压栈(运算符),大于,出栈(运算符)并且从运算符栈出两个字符,先出做后件,后出做前件,运算完后将其压入操作数栈,注意并不继续扫描下一个字符,当等于时,若为括号弹出括号但不从操作数栈弹出两个操作数。当且仅当扫描的字符为‘#’并且栈顶元素为‘#’时,停止扫描。此时操作数栈的栈顶元素即是表达式的结果。

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

int OPND[100];
char OPTR[100]; //操作数栈、操作符栈
int topN=-1,topT=-1;

//栈的基本操作
//压栈,弹栈,取栈顶元素
void push(char *OPTR,char ch){
        OPTR[++topT]=ch;
}
void push(int *OPND,int val){
        OPND[++topN]=val;
}
char pop(char *OPTR){
        return OPTR[topT--];
}
int pop(int *OPND){
        return OPND[topN--];
}
int getTop(int *OPND){
    return OPND[topN];
}
char getTop(char *OPTR){
    return OPTR[topT];
}

//定义一个二维字符数组存放优先级表
char arr[7][7]= {'>','>','<','<','<','>','>',
                 '>','>','<','<','<','>','>',
                 '>','>','>','>','<','>','>',
                 '>','>','>','>','<','>','>',
                 '<','<','<','<','<','=','\0',
                 '>','>','>','>','\0','>','>',
                 '<','<','<','<','<','\0','='
                };
//定义数组下标的字符
int opCH(char ch){
    int i;
        switch(ch){
    case '+':{
        i=0;
        break;
    }
    case '-':{
        i=1;
        break;
    }
    case '*':{
        i=2;
        break;
    }
    case '/':{
        i=3;
        break;
    }
    case '(':{
        i=4;
        break;
    }
    case ')':{
        i=5;
        break;
    }
    case '#':{
        i=6;
        break;
    }
 }
 return i;
}
//比较运算符的优先级
char percede(char ch1,char ch2){
    int i,j;
    i=opCH(ch1);
    j=opCH(ch2);
    return arr[i][j];
}
//运算
int operate(int a,char theta,int b){
    switch(theta){
    case '+':{
            return a+b;
    }
    case '-':{
            return a-b;
    }
    case '*':{
            return a*b;
    }
    case '/':{
            return a/b;
    }
 }
 return 0;
}

int main(){
    string s;//表达式
    char theta;//运算符
    int a,b,c;
    push(OPTR,'#');//先将操作符栈压入一个‘#’
    cout<<"请输入中缀表达式,以#符号结束"<<endl;
    cin>>s;
    for(int i=0;s[i]!='#'||getTop(OPTR)!='#';i++){
    //比较ASCII码 49-57为数字1-9
        if(s[i]>48&&s[i]<58){
            c=s[i]-48; //转换成整型数
            //压入操作数栈
            push(OPND,c);
        }else if(s[i]=='*'||s[i]=='/'||s[i]=='+'||s[i]=='-'||
                 s[i]=='('||s[i]==')'||s[i]=='#'){
                 //比较扫描到的字符和栈顶元素的优先级
            switch(percede(getTop(OPTR),s[i])){
        case '>':{
        		//栈顶元素优先级高,操作符栈弹出一个操作符,操作数栈弹出两个操作数,先弹做后件,后弹做前件
                theta=pop(OPTR);
                b=pop(OPND);
                a=pop(OPND);
                //将运算结果压入操作数栈
                push(OPND,operate(a,theta,b));
                //注意一定要将i--因为大于不扫描下一个字符
                i--;
                break;
        }
        case '<':{
        //栈顶元素优先级低,压入操作符栈
                push(OPTR,s[i]);
                break;
        }
        case '=':{
        //当为括号时,从操作符栈弹出,但不从操作数栈弹出两个数
                if(s[i]==')'){
                    pop(OPTR);
                }
        }
        }
    }
 }
 cout<<getTop(OPND)<<endl;
    return 0;
}

三、结果展示

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

四、局限

  • 只能运算个位数,不能运算大于个位数的数
  • 必须保证表达式格式正确
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐