应用栈实现表达式求值,具体思路如下:
创建两个栈,一个用来存数字,一个用来存符号。起始,数字栈为空,符号栈底先存一个’\n’用来标记开始,用输入的’\n’标记结尾。
开始处理输入的字符,当字符是运算符号时,根据运算符的优先关系:如果当前符号优先关系大于栈顶符号,入栈;如果小于,则拿出栈顶符号,再从数字栈拿出两个数字进行运算,将结果放在数字栈里;如果等于,说明是两个括号相遇,此时括号内的运算已经完成,将括号脱栈。
代码如下:
#include
#include
#define STACKMAX 100
#define STACKADD 10
/**********************************符号栈****************************/
typedef struct StackChar
{
char *base;
char *top;
int stacksize;
}SC;
void InitStackSC(SC *S)
{
S->base = (char*)malloc(STACKMAX*sizeof(char));
S->top = S->base;
S->stacksize = STACKMAX;
}
void PushSC(SC *S,char e)
{
if(S->top - S->base >= S->stacksize)
{
S->base = (char*)realloc(S->base,(S->stacksize+STACKADD)*sizeof(char));
if(!S->base)
return;
S->top = S->base + S->stacksize;
S->stacksize += STACKADD;
}
*S->top++ = e;
}
int StackEmptySC(SC* S)
{
if(S->base == S->top)
return 1;
return 0;
}
void PopSC(SC *S,char *e)
{
*e = *--S->top;
}
char GetTopSC(SC *S)
{
if(StackEmptySC(S))
return 0;
return *(S->top-1);
}
/**************************************数字栈******************/
typedef struct StackData
{
double *base;
double *top;
int stacksize;
}SD;
void InitStackSD(SD *S)
{
S->base = (double*)malloc(STACKMAX*sizeof(double));
S->top = S->base;
S->stacksize = STACKMAX;
}
int StackEmptySD(SD* S)
{
if(S->base == S->top)
return 1;
return 0;
}
void PushSD(SD *S,double e)
{
if(S->top - S->base >= S->stacksize)
{
S->base = (double*)realloc(S->base,(S->stacksize+STACKADD)*sizeof(double));
if(!S->base)
return;
S->top = S->base + S->stacksize;
S->stacksize += STACKADD;
}
*S->top++ = e;
}
void PopSD(SD *S,double *e)
{
*e = *--S->top;
}
double GetTopSD(SD *S)
{
if(StackEmptySD(S))
return 0;
return *(S->top-1);
}
/*******************************************/
char Precede(char x,char y)//判断操两个操作符优先度
{
int i,j;
char ch[7] = {'+','-','*','/','(',')','\n'};
char cmp[7][7] = {
//+ - * / ( ) \n
{'>','>','<','<','<','>','>',},// +
{'>','>','<','<','<','>','>',},// -
{'>','>','>','>','<','>','>',},// *
{'>','>','>','>','<','>','>',},// /
{'<','<','<','<','<','=',' ',},// (
{'>','>','>','>',' ','>','>',},// )
{'<','<','<','<','<',' ','=',},// \n
};
for(i=0; i<7; i++)
{
if(ch[i] == x) break;
}
for(j=0; j<7; j++)
{
if(ch[j] == y) break;
}
return cmp[i][j];
}
double Operate(double a,char op,double b)//计算函数
{
switch(op)
{
case'+':
return a+b;
break;
case'-':
return a-b;
break;
case'*':
return a*b;
break;
case'/':
return a/b;
break;
default:
return 0;
}
}
int In(char c)//检查是否为符号,是返回1,否则返回0
{
if(c=='+' || c=='-' || c=='*' || c=='/' || c=='(' || c==')' || c=='\n')
return 1;
return 0;
}
double EvaluateExpression()
{
SC C;//运算符
SD D;//操作数
SD *OPND = &D;
SC *OPTR = &C;
double a,b;
char c,oper,tmp;
InitStackSC(OPTR);//运算符
PushSC(OPTR,'\n');
InitStackSD(OPND);//操作数
c = getchar();
while(c!='\n' || GetTopSC(OPTR)!='\n')
{
if(!In(c))//不是运算符,进栈
{
c -= '0';//将字符转化为数字
PushSD(OPND,c);
c = getchar();
}
else
{
switch(Precede(GetTopSC(OPTR),c))
{
case'>'://栈顶元素优先权大,退栈并将运算结果入栈
PopSC(OPTR,&oper);
PopSD(OPND,&b);
PopSD(OPND,&a);
PushSD(OPND,Operate(a,oper,b));
break;
case'='://脱括号并且接受下一个字符
PopSC(OPTR,&tmp);
c = getchar();
break;
case'<'://入符号栈并接收下一个字符
PushSC(OPTR,c);
c = getchar();
break;
}
}
}
return GetTopSD(OPND);
}
int main()
{
printf("%0.2lf\n",EvaluateExpression());
return 0;
}
此程序没有检测输入,如果多出空格或者乱输会得到错误答案,添加一个函数检测c即可,留坑,日后来填。