建立2个栈来分别存放构造的后缀表达式和输入的运算符,通过判断原栈顶的运算符和新输入的运算符优先级来选择是否弹出运算符(弹出优先级较低或者相等的运算符),并将弹出的运算符放入后缀表达式的栈中(数字则直接放入)。遇到“(”则直接输入进运算符的栈,然后遇到")"时弹出栈中"("和")"直接的所有剩余运算符。
将输入的负数转化为“0-数字”的形式,比如“-1”改为“0-1”,来支持负数的运算。负数判断是输入的表达式第一个字符不是数字(请不要无聊的在开头输入+1而不是1)或者连续3个字符不是数字,比如1-(-1)中的“-(-”。
计算后缀表达式时,建立一个新的临时栈用于计算。以p指针,从后缀表达式栈底向上查找,并将所有数字输入到临时栈中,若遇到运算符则对临时栈的栈顶与栈顶前面一位数字进行运算,储存在栈顶前一位并将栈顶转移到前一位。最后栈底的数字就是表达式最终的值
#define STACKSIZE 100
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct{
char st; //存放数字或者运算符
double sum; //存放计算时的数字
} DataType;
typedef struct{
DataType items[STACKSIZE];
int top;
} SqStack;
void push(SqStack *L,char s) //输入
{
L->items[++L->top].st=s;
if(s>='0'&&s<='9') L->items[L->top].sum=L->items[L->top].st-'0';
}
int check(char s1,char s2) //判断运算符优先级
{
if(s1=='('||s2=='(') return 0;
else if(s1=='*'||s1=='/') return 1;
else if(s2=='+'||s2=='-') return 1;
else return 0;
}
void pop(SqStack *L,SqStack *L2) //弹出运算符的栈中的运算符并输入进数字的栈,构成后缀表达式
{
if(L->items[L->top].st==')')
{
L->top--;
}
while(L->top>=0&&L->items[L->top].st!='(')
{
push(L2,L->items[L->top].st);
L->top--;
}
if(L->top>=0)
{
L->top--;
}
}
double js(SqStack *L) //运算后缀表达式
{
SqStack pass;
int p=0;
pass.top=-1;
while(L->top>=p)
{
while(L->items[p].st<='9'&&L->items[p].st>='0')
{
push(&pass,L->items[p].st);
p++;
}
switch (L->items[p].st)
{
case '+':
pass.items[pass.top-1].sum+=pass.items[pass.top].sum;
pass.top--;
break;
case '-':
pass.items[pass.top-1].sum-=pass.items[pass.top].sum;
pass.top--;
break;
case '*':
pass.items[pass.top-1].sum*=pass.items[pass.top].sum;
pass.top--;
break;
case '/':
pass.items[pass.top-1].sum/=pass.items[pass.top].sum;
pass.top--;
break;
default:
break;
}
p++;
}
return pass.items[0].sum;
}
int main()
{
int k=0; //k负责对连续的运算符计数
SqStack bds,yszf;
bds.top=-1;
yszf.top=-1;
char s;
s=getchar();
while(s!='\n')
{
if(s>='0'&&s<='9') {push(&bds,s);k=0;}
else if(s>'9'||s<'0')
{
if(k==2||bds.top<0) {push(&bds,'0');k=0;} //如果连续的运算符达到3个或者首个数字为负数,例1-(-1)中存在负数,额外输入一个0
push(&yszf,s);
k++;
if(s==')') pop(&yszf,&bds); //弹出括号之间的表达式
else while(yszf.top>=1&&check(yszf.items[yszf.top-1].st,yszf.items[yszf.top].st)) //判断是否弹出运算符
{
push(&bds,yszf.items[yszf.top-1].st);
yszf.items[yszf.top-1]=yszf.items[yszf.top];
yszf.top--;
}
}
s=getchar();
}
while(yszf.top>=0)
push(&bds,yszf.items[yszf.top--].st);
for(int i=0;i<=bds.top;i++)
{
printf("%c ",bds.items[i].st);
}
printf("\n%.2lf",js(&bds));
return 0;
}