#include<stdio.h>
#include<malloc.h>
#define MAX 100
typedef struct charStack
{
char data[MAX];
int top;
}cStack;
typedef struct DoubleStack
{
int top;
double data[MAX];
}dStack;
int now(char );
int last(char );
void Initc(cStack *);
void Pushc(cStack *,char);
char Gettopc(cStack *);
char Popc(cStack *);
void Initd(dStack *);
int Pushd(dStack *,double);
double Popd(dStack *);
void Trans(char*,char*);
double Calc(char*);
int main()
{
char middle[MAX];//中缀
char behind[MAX];
printf("请输入表达式\n");
scanf("%s",&middle);//输入中缀表达式
Trans(middle,behind);//将中缀表达为后缀存进后缀里
printf("计算的结果为:%f",Calc(behind));//计算后缀
}
void Trans(char *middle,char*behind)
{
int i=0;
int j=0;
int flag1=-1; //flag1为0表示上次输出为数字,flag1为1表示上次输出为字符
int flag2=-1; //flag2为0表示上次扫描为数字,flag为1表示上次扫描为运算符,用于区分数字后加空格
cStack st1;
Initc(&st1);
while(middle[i]!='\0')
{
if(middle[0]=='-')
{
j=strlen(middle);
while(j>0)
{
middle[j+5]=middle[j];
j--;
}
middle[j++]='(';
middle[j++]='0';
middle[j++]='-';
middle[j++]='1';
middle[j++]=')';
middle[j]='*';
}
if(middle[i]=='('&&middle[i+1]=='-') //非第一位负数时
{
j=strlen(middle);
while(j>i+1)
{
middle[j+5]=middle[j];
j--;
}
middle[j++]='(';
middle[j++]='0';
middle[j++]='-';
middle[j++]='1';
middle[j++]=')';
middle[j]='*';
i=i+5;
}
i++;
}
i=0;
j=0;
while(middle[i]!='\0')
{
if(flag1==0&&flag2==1) //若上次的输出为数字,上次循环扫描为字符,则表示该数字串结束,则在数字后加空格区分
{
behind[j++]=' ';
flag1=1;
}
if(middle[i]>='0'&&middle[i]<='9'||middle[i]=='.')
{
behind[j++]=middle[i];
flag2=0;
flag1=0;
}
else if(middle[i]=='+'||middle[i]=='-'||middle[i]=='*'||middle[i]=='/'||middle[i]=='(')
{
flag2=1;
if(st1.top<0||now(middle[i])>last(Gettopc(&st1)))
{
Pushc(&st1,middle[i]);
}
else
{
while(st1.top>=0&&now(middle[i])<last(Gettopc(&st1))) //当前扫描字符优先级不断与栈顶字符优先级比较,当前字符小于栈顶字符时出栈并输出
{
behind[j++]=Popc(&st1);
flag1=1;
}
if(st1.top<0||now(middle[i])>last(Gettopc(&st1))) //当前字符优先级大于栈顶优先级或栈空时当前字符压入字符栈内
{
Pushc(&st1,middle[i]);
}
}
}
else if(middle[i]==')')
{
flag2=1;
if(Gettopc(&st1)!='(') //若括号仅包含数字则没有输出运算符
{
flag1=1;
}
while(Gettopc(&st1)!='(')
{
behind[j++]=Popc(&st1);
}
Popc(&st1); //将'('出栈
}
i++;
}
while(st1.top>=0) //将栈内剩余的运算符依次退栈输出
{
behind[j++]=Popc(&st1);
}
behind[j]='\0';
}
void Initc(cStack * cP)
{
cP->top = -1;
}
void Initd(dStack *d1)
{
d1->top=-1;
}
void Pushc(cStack* c,char val)
{
if(c->top < MAX)
{
c->data[++c->top] = val;
}
}
int Pushd(dStack *d1,double data)
{
if(d1->top<MAX)
{
d1->data[++d1->top]=data;
return 1;
}
else return 0;
}
char Popc(cStack* cP)
{
return cP->data[cP->top--];
}
double Popd(dStack *d1)
{
return d1->data[d1->top--];
}
char Gettopc(cStack *c1)
{
return c1->data[c1->top];
}
int now(char a) //当前扫描运算符优先级
{
switch(a)
{
case '(': return 6;
case '+': case '-': return 2;
case '*': case '/': return 4;
}
}
int last(char a) //之前扫描运算符优先级
{
switch(a)
{
case '(': return 1;
case '+': case '-': return 3;
case '*': case '/': return 5;
}
}
double Calc(char *s1)
{
int i=0;
int flag; //char类型转换为double类型数据标记
double data1,data2;
double sum;
dStack ds1;
Initd(&ds1);
while(s1[i]!='\0')
{
if(s1[i]=='+'||s1[i]=='-'||s1[i]=='*'||s1[i]=='/') //若为运算符,获取栈顶两个元素进行计算
{
data1=Popd(&ds1);
data2=Popd(&ds1);
if(s1[i]=='+') Pushd(&ds1,data2+data1);
else if(s1[i]=='-') Pushd(&ds1,data2-data1);
else if(s1[i]=='*') Pushd(&ds1,data2*data1);
else if(s1[i]=='/') Pushd(&ds1,data2/data1);
}
else //为数据时转化为double类型压栈
{
flag=0; //初始化为0为整数部分标记,1为小数部分标记
sum=0;
double d=1;
while(s1[i]!=' '&&s1[i]!='+'&&s1[i]!='-'&&s1[i]!='*'&&s1[i]!='/')
{
if(s1[i]=='.') //若有小数点,进入小数转化模式
{
flag=1;
i++;
continue;
}
if(flag==0)
{
sum=sum*10+(double)(s1[i]-'0');
}
else
{
d=d*10;
sum=sum+((double)(s1[i]-'0'))/d;
}
i++;
}
if(s1[i]=='+'||s1[i]=='-'||s1[i]=='*'||s1[i]=='/') i--; //转化成功一个数据,若下个字符为运算符,则i--,回到当前运算的数据位置
Pushd(&ds1,sum);
}
i++; //i++准备下一个字符的转换
}
return Popd(&ds1);
}
运用了栈的相关知识,需要灵活运用出栈入栈,注意点:后缀表达式每个数据必须要拿一个字符分割,否则小数没法计算。优先级也要考虑清楚。