问题描述:使用键盘输入表达式,计算表达式的值并输出;将表达式转化成后缀表达式输出,利用后缀表达式求表达式的值并输出。
测试数据:
3*(7-2)
2*(6+2*(3+6*(6+6)))+(6+6)*3+2
8/(9-9)
#include<stdio.h>
#include<stdlib.h>
#define MAX 30
typedef struct tagNode{
char data;
struct tagNode *next;
}Node,*LinkList;
//用结构体数组实现顺序栈
typedef struct tagStack1{
char S[MAX];
int top;
}Stack1; //存储运算符
typedef struct tagStack2{
float S[MAX];
int top;
}Stack2; //存储运算数
int SEmpty1(Stack1 s) //判运算符栈空
{
if(s.top==-1)return 1;
else return 0;
}//SEmpty1
int SEmpty2(Stack2 s) //判运算数栈空
{
if(s.top==-1)return 1;
else return 0;
}//SEmpty2
int Push1(Stack1 *s,char x) //运算符入栈
{
if(s->top==MAX-1)return 0; //栈满不能入栈,返回0
else{
s->top++;
s->S[s->top]=x; //栈不满则压入数据x
return 1; //进栈成功,返回1
}
}//Push1
int Push2(Stack2 *s,float x) //运算数入栈
{
if(s->top==MAX-1)return 0;
else{
s->top++;
s->S[s->top]=x;
return 1;
}
}//Push2
int Pop1(Stack1 *s,char *x) //运算符出栈
{
if(SEmpty1(*s))return 0; //若栈空不能出栈,返回0
else{
*x=s->S[s->top];
s->top--;
return 1; //出栈成功,返回1
}
}//Pop1
int Pop2(Stack2 *s,float *x) //运算数出栈
{
if(SEmpty2(*s))return 0;
else{
*x=s->S[s->top];
s->top--;
return 1;
}
}//Pop2
char Precede(char a,char b) //优先级判断
{
int i,c,d;
static char bijiao[7][7]={'>','>','<','<','<','>','>',
'>','>','<','<','<','>','>',
'>','>','>','>','<','>','>',
'>','>','>','>','<','>','>',
'<','<','<','<','<','=',' ',
'>','>','>','>',' ','>','>',
'<','<','<','<','<',' ','='};
char h[7]={'+','-','*','/','(',')','#'};
for(i=0;i<=6;i++){
if(a==h[i])
c=i;
if(b==h[i])
d=i;
}
return bijiao[c][d];
}//Precede
char ReadTop1(Stack1 s) //读运算符栈顶元素
{
if(SEmpty1(s))return 0;
else return s.S[s.top]; //读栈顶元素,但指针没有移动
}//ReadTop1
float ReadTop2(Stack2 s) //读运算数栈顶元素
{
if(SEmpty2(s))return 0;
else return s.S[s.top];
}//ReadTop1
float Count(float m,char the,float n,int *d) //运算函数
{
switch(the){
case '*':return m*n;
case '+':return m+n;
case '-':return m-n;
case '/':if(n!=0)return m/n;
else *d=*d+1;
break;
}//switch
return 0;
}//Count
void Operate1(LinkList L)
{
int d=0;
char x,theta;float a,b;
LinkList p=L->next;
Stack1 OPTR;Stack2 OPND; //OPTR为运算符栈,OPND为操作数栈
OPTR.top=0;OPND.top=-1;
OPTR.S[0]='#';
while(p->data!='#'||ReadTop1(OPTR)!='#'){
if(p->data>='0'&&p->data<='9'){
Push2(&OPND,(float)(p->data-48));p=p->next;
}//if
else{
switch(Precede(ReadTop1(OPTR),p->data)){
case '<'://栈顶元素优先级低
Push1(&OPTR,p->data);p=p->next;break;
case '='://脱括号
Pop1(&OPTR,&x);p=p->next;break;
case '>'://退栈并将运算结果入栈
Pop1(&OPTR,&theta);
Pop2(&OPND,&b);Pop2(&OPND,&a);
Push2(&OPND,Count(a,theta,b,&d));
break;
}//switch
}//else
}//while
if(d!=0){printf("ERROR!!!\n");return;}
else printf("=%.2f\n",ReadTop2(OPND));
}//Operate1
void Operate2(LinkList L)
{
int i,j,d=0;
float a,b;
Stack1 OPTR1;Stack2 OPND1,OPND3;//OPND3用作对后缀表达式求值
LinkList p=L->next;
OPTR1.top=0;OPND1.top=-1,OPND3.top=-1;
OPTR1.S[0]='#';
while(p->data!='#'||ReadTop1(OPTR1)!='#'){
if(p->data>='0'&&p->data<='9'){
Push2(&OPND1,(float)(p->data-48));
Push2(&OPND3,(float)(p->data-48));
p=p->next;
}//if
else{
switch(Precede(ReadTop1(OPTR1),p->data)){
case '<'://栈顶元素优先级低
Push1(&OPTR1,p->data);p=p->next;break;
case ' ':p=p->next;break;
case '>'://输出栈中元素,并将栈清空
for(i=0;i<=OPND1.top;i++)
printf("%.0f ",OPND1.S[i]);
OPND1.top=-1;
if(p->data==')'&&(p->next->data=='*'||p->next->data=='/')){
j=OPTR1.top;
while(OPTR1.S[j]!='('){
printf("%c ",OPTR1.S[j]);
Pop2(&OPND3,&b);Pop2(&OPND3,&a);//对后缀表达式进行求值
Push2(&OPND3,Count(a,OPTR1.S[j],b,&d));
j--;
}//while
OPTR1.top=j-1;
}//if
else{
for(j=OPTR1.top;j>=1;j--){
if(OPTR1.S[j]!='('){
printf("%c ",OPTR1.S[j]);
Pop2(&OPND3,&b);Pop2(&OPND3,&a);//对后缀表达式进行求值
Push2(&OPND3,Count(a,OPTR1.S[j],b,&d));
}
}//for
OPTR1.top=0;
}//else
if(p->data!=')')Push1(&OPTR1,p->data);
if(p->data!='#')p=p->next;
break;
}//switch
}//else
}//while
if(d!=0){printf("ERROR!!!\n");return;}
else printf("=%.2f\n",ReadTop2(OPND3));
}//Operate2
int main()
{
char i;
LinkList L,p,s;
p=L=(LinkList)malloc(sizeof(Node));
printf("请输入中缀表达式(以#结束):\n");
while(p->data!='#'){
s=(LinkList)malloc(sizeof(Node));
scanf("%c",&s->data);
p->next=s;p=s;
}
p->next=NULL;
p=L->next;
while(p->data!='#'){printf("%c",p->data);p=p->next;}
scanf("%c",&i);
Operate1(L);
printf("转化为后缀表达式并求值为(输入Y or N):\n");
scanf("%c",&i);
switch(i){
case 'Y':Operate2(L);break;
case 'N':printf("谢谢使用!\n");break;
}
return 0;
}//main