【数据结构】ZJNU1004 编译器中的表达式求值问题

366 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Description

按中缀形式输入一个四则运算的表达式,利用算法优选算法把其转换为后缀表达式输出,并求表达式的值。假设输入的表达式中的操作数都是1位整数。

Input

输入数据有多组 每一组测试数据为带小括号的四则运算中缀表达式,不包含空格。

Output

对于每组测试数据输出两行,第一行四则运算表达式的后缀表达式(每个数字或者操作符之间输出空格,最后一个元素后没有空格),第二行运算结果。 除法操作为整除,比如6/4=1。

Sample Input

8-(3+2*6)/5+4 (7+8)*9 Sample Output

8 3 2 6 * + 5 / - 4 + 9 7 8 + 9 * 135

tips: 定义栈时不可以使用char要用int,要不然就会出现只要大于128就会变成负数的情况,因为char只能存储那么大,再打就涉及编码变成负数了

代码区:

#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstdlib>
using namespace std;
int size = 1005;
typedef struct{
    int* top;
    int* base;
}SqStack;

char op[][8] = {//不同符号的优先级,为了方便所以用二维数组的形式来存储
        //分别为+-*/()#
        {">><<<>>"},
        {">><<<>>"},
        {">>>><>>"},
        {">>>><>>"},
        {"<<<<<=>"},
        {">>>>>>>"},
        {"<<<<<<="}
};

char oop[8] = "+-*/()#";//符号查询对应的数字
char Precede(char a, char b){//比较函数,比较两数的大小,返回>或<等
    int temp1 = 0;
    int temp2 = 0;
	for(int i = 0;i < 8;i++){
	    if(a == oop[i])temp1 = i;//取出对应符号的数字,来获取大小优先关系
	    if(b == oop[i])temp2 = i;
    }
    return op[temp1][temp2];
}

int Operate(int a, char theta, int b){//运算函数,很简单
    if (theta == '+'){
        return a+b;
    }else if(theta == '-'){
        return a-b;
    }else if(theta == '*'){
        return a*b;
    }else if(theta == '/'){
        return a/b;
    }
}

int InitStack(SqStack &s){//初始化栈函数
    s.base = (int*) malloc(size*sizeof(int));//开辟空间来给栈,这里先随便来一个1005,应该够用了,小了可能会Runtimeerror
    s.top = s.base;//top和base初始设为一样的
    return 1;
}
int GetTop(SqStack &s){//获取栈顶的元素
    if(s.top == s.base)return 0;//这就说明栈是空的
    return *(s.top - 1);//因为栈的top是不存在的数,所以需要往下-1
}
int Push(SqStack &s,int e){//将数字推入栈
    *s.top ++ = e;//此处先将e的值存储栈,然后将top++,先后顺序注意
    return 1;
}
int Pop(SqStack &s,int &e){//弹出栈顶的数字元素同时将那元素存入e中
    if(s.top == s.base)return 0;
    e = (int)*(--s.top);//因为s中存的是char型,所以要用int强转一下
    return 1;
}
int Cpop(SqStack &s,char &e){//弹出栈顶的字符元素同时将那元素存入e中
    if(s.top == s.base)return 0;
    e = *(--s.top);//注意这里的顺序是先执行--再是取top的值
    return 1;
}
void Evaluate(char ch){//转化函数,将中序表达式转化成后序表达式
    SqStack opnd,optr,rear;//opnd栈储存操作数,optr栈存储操作符,rear存后序表达式
    InitStack(opnd);//初始化栈
    InitStack(optr);
    InitStack(rear);
    int a,b;
    char x;
    char theta;
    Push(optr,'#');//先把#退入optr中,作为判断栈空的条件
    while(ch!='#'||GetTop(optr)!='#'){//当读入的字符不为#同时操作符栈顶元素不是#时
        if((ch >= '0') && (ch <= '9')){//
            Push(opnd,ch - '0');//因为ch是字符型所以需要减去'0'来转化成数字型存入opnd
            Push(rear,ch);//如果是数字就直接推入后续表达式中
            ch = getchar();//获取下一个字符
            if(ch == '\n')ch = '#';//由题目知,只有一行所以当读到的字符是回车时判断输入结束,将之替换成#
        }
        else
            switch(Precede(GetTop(optr),ch)){//判断ch和操作符栈顶的元素之间的优先关系
                case '=':
                    Cpop(optr,x);//当优先级相同时也就意味着是一对括号,所以直接取出optr中的(就好了,所以就直接弹出
                    ch = getchar();
                    if(ch == '\n')ch = '#';
                    break;
                case '>'://如果栈顶的优先级高就进行运算
                    Cpop(optr,theta);//弹出栈顶的操作符
                    Pop(opnd, b);//这里有先后顺序,先弹出b再是a
                    Pop(opnd, a);
                    Push(rear, theta);//将即将进行运算的操作符存入后续表达式中
                    Push(opnd, Operate(a, theta, b));//将运算后的结果再存入操作数中
                    break;
                case '<':
                    Push(optr,ch);//如果优先级高于栈顶元素就推入栈
                    ch = getchar();
                    break;
            }
    }
    opnd.top = opnd.base;//将opnd栈置空,这里将top和base相等也可以达到这个效果
    int *p = rear.base;//新定义一个p指针来获取后缀表达式
    while(p!=rear.top)//意思是当rear栈不为空时
    {
        cout << (char)*p << " ";//因为是int型所以需要强转成char
        if(*p >= '0' && *p <= '9')
            Push(opnd,*p - '0');//是数字就直接推入操作数栈
        else//是操作符就直接进行运算
        {
            Pop(opnd,b);
            Pop(opnd,a);
            Push(opnd, Operate(a,*p,b));
        }
        p++;//取下一个字符
    }
    cout << endl << GetTop(opnd) << endl;//此处的opnd中只有一个数,也就是我们需要求的结果
}
int main(){
    char ch;
    while(cin >> ch){
        if(ch != '\n')Evaluate(ch);//当读入数据不是回车符时,进行转化函数
    }
    return 0;
}

新手上路,有错请指正.