//c语言版数据结构(奇迹冬瓜)-栈实战(4)表达式求值
/*
这个算法难的不是思想,而是尽可能的解决输入格式的问题
这个程序还有两个问题没有解决可以实现输出负数,但是不能输入负数,一旦输入时括号不匹配会发生错误。
主要思想:
利用两个栈,一个存放字符运算符,一个来存放整数.
其中涉及整数的转换和表达式的格式检测及算符之间的优先级.
本算法还很不工整优化.
*/
//-----头文件------
#include<stdio.h>
#include<stdlib.h>
//-----宏定义------
#define INIT_STACKSIZE 100
#define INCREMENTSIZE 10
#define TRUE 1
#define ERROR 0
#define OVERFLOW -2
//-----替换和结构体-----
typedef int Bool;
typedef struct
{
char *Base,*Top;
int stacksize;
}SqStackC,*StackC;
typedef struct
{
int *Base,*Top;
int stacksize;
}SqStackI,*StackI;
//-------函数列表-------
Bool InitStackC(StackC s);
Bool PopC(StackC s,char *e);
Bool PushC(StackC s,char e);
Bool StackEmptyC(StackC s);
Bool ClearStackC(StackC s);
char GetTopC(StackC s);
Bool InitStackI(StackI s);
Bool PopI(StackI s,int *e);
Bool PushI(StackI s,int e);
Bool StackEmptyI(StackI s);
Bool ClearStackI(StackI s);
int GetTopI(StackI s);
Bool InN(char ch);
void Expression();
Bool Rule(char ch);
char Precede(char c1,char c2);
int Operate(int a,char theta,int b);
//------主函数------
void main()
{
Expression();
}
//-----其余函数------
void Expression()
{
SqStackC sq1,*OPTR=&sq1;
SqStackI sq2,*OPND=&sq2;
int integer=0,ei,i,flag,startflag,flag1,flag2,flag3,a,b;
char ec,ch,theta;
do
{ flag3=0;
flag=1;
flag1=0;
flag2=0;
startflag=0;
InitStackC(OPTR);InitStackI(OPND);
PushC(OPTR,'#');
ch=getchar();
while('#'!=ch||'#'!=GetTopC(OPTR))
{
if(!Rule(ch)||(0==startflag&&('+'==ch||'*'==ch||'/'==ch||'-'==ch))||flag1>=2)
{
flag=0;
}
if(InN(ch))
{
flag1=0;
if(0==integer&&'0'==ch)
{
flag=0;
}
integer=integer*10+ch-'0';
}
else if(('+'==ch||'-'==ch||'*'==ch||'/'==ch||'#'==ch||')'==ch)&&(0==flag2)&&(0!=integer&&'0'!=ch))
{
flag1++;
PushI(OPND,integer);
integer=0;
}
if(Rule(ch)&&(!InN(ch)))
{
switch(Precede(GetTopC(OPTR),ch))
{
case '<':PushC(OPTR,ch);ch=getchar();flag2=0;break;
case '=':PopC(OPTR,&ec);ch=getchar();flag2=0;break;
case '>':PopI(OPND,&b);PopI(OPND,&a);PopC(OPTR,&theta);PushI(OPND,Operate(a,theta,b));flag2=1;break;
case '@':flag=0;break;
}
}
else
{
ch=getchar();
flag2=0;
}
startflag=1;
flag3++;
if(flag3>30)
{
flag=0;
}
}
if(0==flag)
{
printf("表达式格式错误!重新输入.\n");
getchar();
ClearStackC(OPTR);
ClearStackI(OPND);
}
}while(0==flag);
while(!StackEmptyI(OPND))
{
PopI(OPND,&ei);
printf("%d ",ei);
}
getchar();
getchar();
}
Bool InitStackC(StackC s)
{
if(!(s->Base=(char*)malloc(INIT_STACKSIZE*sizeof(char))))
{
exit(OVERFLOW);
}
s->Top=s->Base;
s->stacksize=INIT_STACKSIZE;
return TRUE;
}
Bool PopC(StackC s,char *e)
{
if(s->Base==s->Top)
{
return ERROR;
}
*e=*(--s->Top);
return TRUE;
}
Bool PushC(StackC s,char e)
{
if(s->Top-s->Base>=s->stacksize)
{
if(!(s->Base=(char*)realloc(s->Base,(INIT_STACKSIZE+INCREMENTSIZE)*sizeof(char))))
{
exit(OVERFLOW);
}
s->Top=s->Base+s->stacksize;
s->stacksize+=INIT_STACKSIZE;
}
*(s->Top++)=e;
return TRUE;
}
Bool StackEmptyC(StackC s)
{
return s->Base==s->Top?TRUE:ERROR;
}
Bool ClearStackC(StackC s)
{
free(s->Base);
s->Base=NULL;
s->Top=NULL;
return TRUE;
}
char GetTopC(StackC s)
{
if(!s->stacksize||s->Base==s->Top)
{
return ERROR;
}
return *(s->Top-1);
}
Bool InitStackI(StackI s)
{
if(!(s->Base=(int*)malloc(INIT_STACKSIZE*sizeof(int))))
{
exit(OVERFLOW);
}
s->Top=s->Base;
s->stacksize=INIT_STACKSIZE;
return TRUE;
}
Bool PopI(StackI s,int *e)
{
if(s->Base==s->Top)
{
return ERROR;
}
*e=*(--s->Top);
return TRUE;
}
Bool PushI(StackI s,int e)
{
if(s->Top-s->Base>=s->stacksize)
{
if(!(s->Base=(int*)realloc(s->Base,(INIT_STACKSIZE+INCREMENTSIZE)*sizeof(int))))
{
exit(OVERFLOW);
}
s->Top=s->Base+s->stacksize;
s->stacksize+=INIT_STACKSIZE;
}
*(s->Top++)=e;
return TRUE;
}
Bool StackEmptyI(StackI s)
{
return s->Base==s->Top?TRUE:ERROR;
}
Bool ClearStackI(StackI s)
{
free(s->Base);
s->Top=s->Base=NULL;
return TRUE;
}
int GetTopI(StackI s)
{
if(!s->stacksize||s->Base==s->Top)
{
return ERROR;
}
return *(s->Top-1);
}
Bool InN(char ch)
{
return ch>='0'&&ch<='9'?TRUE:ERROR;
}
Bool Rule(char ch)
{
if(ch>='0'&&ch<='9')
{
return TRUE;
}
else if('#'==ch||'('==ch||')'==ch||'+'==ch||'-'==ch||'*'==ch||'/'==ch)
{
return TRUE;
}
return ERROR;
}
char Precede(char c2,char c1)
{
char opera[8][8]={
{'@','+','-','*','/','(',')','#'},
{'+','>','>','<','<','<','>','>'},
{'-','>','>','<','<','<','>','>'},
{'*','>','>','>','>','<','>','>'},
{'/','>','>','>','>','<','>','>'},
{'(','<','<','<','<','<','=','@'},
{')','>','>','>','>','@','>','>'},
{'#','<','<','<','<','<','@','='}};
int i,j,mark_i=0,mark_j=0;
for(i=0;i<8;i++)
{
if(opera[0][i]==c2)
{
mark_i=i;
}
}
for(j=0;j<8;j++)
{
if(opera[j][0]==c1)
{
mark_j=j;
}
}
return opera[mark_i][mark_j];
}
int Operate(int a,char theta,int b)
{
int res=0;
switch(theta)
{
case '+':res=a+b;break;
case '-':res=a-b;break;
case '*':res=a*b;break;
case '/':res=a/b;break;
}
return res;
}