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;
}
新手上路,有错请指正.