读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
输入描述:
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
输出描述:
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
这个题目主要使用栈来写,与此同时还要注意符号的优先级,利用汇编语言学到知识,构造符号栈顺利完成表达式的求值。
#include <stdio.h>
#include <string.h>
#define MAX 205
/*
这道题目主要采用栈来求解
为了锻炼使用C语言解决问题的能力,这里通过数组来模拟栈
*/
struct Node
{
double num;
char op;
int flag;
};
struct Node Stack[MAX];//符号栈
struct Node Queue[MAX];//用来存放后缀表达式
char str1[MAX];
char str2[MAX];
int op[256];
//将中缀表达式转化为后缀表达式
int Change(int length)
{
double num;
struct Node temp;
int i;
int cnt=0;
int top=0;
for(i=0;i<length;)
{
//如果是操作数
if(str2[i]>='0'&&str2[i]<='9')
{
temp.flag=1;
temp.num=0;
while(str2[i]!='\0'&&str2[i]>='0'&&str2[i]<='9')
{
temp.num=temp.num*10+str2[i]-'0';
i++;
}
Queue[cnt++]=temp;
}
//如果是运算符,则需要先比较运算符与当前栈顶符号的优先级
//如果栈顶符号优先级更高,则要加入到队列数组当中
//如果优先级较低的话,则将符号压入到符号栈当中
else
{
temp.flag=0;
while(top!=0&&op[str2[i]]<=op[Stack[top-1].op])//这里注意栈顶指针等于栈顶位置+1
{
Queue[cnt++]=Stack[--top];
}
temp.op=str2[i];
Stack[top++]=temp;
i++;
}
}
while(top!=0)//清空栈,构造完整的后缀表达式
{
Queue[cnt++]=Stack[--top];
}
return cnt;
}
double Cal(int cnt)//计算后缀表达式
{
double temp1,temp2;
struct Node cur,temp;
int top=0;
int i,j;
for(i=0;i<cnt;i++)
{
cur=Queue[i];
if(cur.flag==1) Stack[top++]=cur;
else
{
//特别注意top必须加入前缀--,因为top指针总是等于栈顶元素位置+1
temp2=Stack[--top].num;//操作数2
temp1=Stack[--top].num;//操作数1
temp.flag=1;
if(cur.op=='+') temp.num=temp1+temp2;
else if(cur.op=='-') temp.num=temp1-temp2;
else if(cur.op=='*') temp.num=temp1*temp2;
else temp.num=temp1/temp2;
Stack[top++]=temp;
}
}
return Stack[top-1].num;
}
int main()
{
op['+']=op['-']=1;
op['*']=op['/']=2;
while(fgets(str1,205,stdin)&&strcmp(str1,"0\n")!=0)
{
int len=strlen(str1);
int i,j=0;
for(i=0;i<len;i++)
{
if(str1[i]==' '||str1[i]=='\n') continue;
else str2[j++]=str1[i];
}
str2[j]='\0';
int cnt=Change(j);
printf("%.2f\n",Cal(cnt));
}
return 0;
}