时间限制:3000 ms | 内存限制:65535 KB
难度:4
描述
ACM队的mdd想做一个计算器,但是,他要做的不仅仅是一计算一个A+B的计算器,他想实现随便输入一个表达式都能求出它的值的计算器,现在请你帮助他来实现这个计算器吧。
比如输入:“1+2/4=”,程序就输出1.50(结果保留两位小数)
输入
第一行输入一个整数n,共有n组测试数据(n<10)。
每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。
数据保证除数不会为0
输出
每组都输出该组运算式的运算结果,输出结果保留两位小数。
样例输入
2
1.000+2/4=
((1+2)*5+1)/4=
样例输出
1.50
4.00
题解:利用栈求解表达式求解问题,注意本题中对浮点数的处理。
程序代码:
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 1000
#define MaxOp 7
struct //设定运算符优先级
{
char ch; //运算符
int pri; //优先级
} lpri[]={{'=',0},{'(',1},{'*',5},{'/',5},{'+',3},{'-',3},{')',6}},
rpri[]={{'=',0},{'(',6},{'*',4},{'/',4},{'+',2},{'-',2},{')',1}};
int leftpri(char op) //求左运算符op的优先级
{
int i;
for (i=0;i<MaxOp;i++)
if (lpri[i].ch==op)
return lpri[i].pri;
}
int rightpri(char op) //求右运算符op的优先级
{
int i;
for (i=0;i<MaxOp;i++)
if (rpri[i].ch==op)
return rpri[i].pri;
}
int InOp(char ch) //判断ch是否为运算符
{
if (ch=='(' || ch==')' || ch=='+' || ch=='-' || ch=='*' || ch=='/')
return 1;
else
return 0;
}
int Precede(char op1,char op2) //op1和op2运算符优先级的比较结果
{
if (leftpri(op1)==rightpri(op2))
return 0;
else if (leftpri(op1)<rightpri(op2))
return -1;
else
return 1;
}
void trans(char *exp,char postexp[])
//将算术表达式exp转换成后缀表达式postexp
{
struct
{
char data[MaxSize];//存放运算符
int top;//栈指针
} op;//定义运算符栈
int i=0;//i作为postexp的下标
op.top=-1;
op.top++; //将'='进栈
op.data[op.top]='=';
while (*exp!='\0')//exp表达式未扫描完时循环
{
if(*exp=='=')
break;
if (!InOp(*exp))//为数字字符的情况
{
while (*exp>='0' && *exp<='9' || *exp=='.') //判定为数字
{
postexp[i++]=*exp;
exp++;
}
postexp[i++]='#';//用#标识一个数值串结束
}
else//为运算符的情况
switch(Precede(op.data[op.top],*exp))
{
case -1: //栈顶运算符的优先级低:进栈
op.top++;
op.data[op.top]=*exp;
exp++; //继续扫描其他字符
break;
case 0: //只有括号满足这种情况
op.top--; //将(退栈
exp++; //继续扫描其他字符
break;
case 1: //退栈并输出到postexp中
postexp[i++]=op.data[op.top];
op.top--;
break;
}
} //while (*exp!='\0')
while (op.data[op.top]!='=')
//此时exp扫描完毕,退栈到'='为止
{
postexp[i++]=op.data[op.top];
op.top--;
}
postexp[i]='\0';//给postexp表达式添加结束标识
}
float compvalue(char exp[])//计算后缀表达式的值
{
struct
{
double data[MaxSize];//存放数值
int top;//栈指针
} st;//定义数值栈
double d,y; char ch; int t=0; //t作为exp的下标
st.top=-1; ch=exp[t];t++;
while (ch!='\0')//exp字符串未扫描完时循环
{
switch (ch)
{
case '+':
st.data[st.top-1]=st.data[st.top-1]+st.data[st.top];
st.top--;
break;
case '-':
st.data[st.top-1]=st.data[st.top-1]-st.data[st.top];
st.top--;
break;
case '*':
st.data[st.top-1]=st.data[st.top-1]*st.data[st.top];
st.top--;
break;
case '/':
if(st.data[st.top]!=0)
st.data[st.top-1]=st.data[st.top-1]/st.data[st.top];
st.top--;
break;
default:
d=0; //将数字字符转换成数值存放到d中
while (ch>='0' && ch<='9') //为数字字符
{
d=10*d+ch-'0';
ch=exp[t];t++;
}
if(ch == '.')
{
double k = 10.0;
y = 0;
while (exp[t]>='0' && exp[t]<='9')
{
y += ((exp[t]-'0')/k);
t++;
k *= 10;
}
d+=y;
t++;
}
st.top++; st.data[st.top]=d;
}
ch=exp[t];t++;
}
return st.data[st.top];
}
int main()
{
int n;
scanf("%d",&n);
getchar();
while(n--)
{
char exp[MaxSize];
scanf("%s",exp);
char postexp[MaxSize];
trans(exp,postexp);
printf("%0.2lf\n",compvalue(postexp));
}
system("pause");
return 0;
}