/*---------------------------------------------------------------------------------------------------
目的:编程实现表达式的求值,例如:4+2*3-10/5 = 8
思路:1.表达式是由操作数(operand),运算符(operator)和定界符组成的。
2.用顺序栈来实现,那么就需要构造两个栈:OPTR栈和OPND栈
3.扫描表达式,遇到operand就压入栈OPND,遇到operator就压入栈OPTR
4.判断运算符的优先级,当后一个运算符的优先级高于前一个运算符的优先级时,就弹出运算符和操作数,
运算后的结构压入到opnd中.
----------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define STACK_INTI_SIZE 100 //存储空间初始分配量
#define STACKINCREMENT 10 //存储空间的分配增量
#define N 11
typedef int SElemType;
/*算符间的优先关系表(+,-,*,/,(,),#)*/
char cpri[7][7]={
{'>','>','<','<','<','>','>' },
{'>','>','<','<','<','>','>' },
{'>','>','>','>','<','>','>' },
{'>','>','>','>','<','>','>' },
{'<','<','<','<','<','=',' '},
{'>','>','>','>',' ','>','>'},
{'<','<','<','<','<',' ','='}
};
/*定义栈的函数*/
typedef struct
{
SElemType *base; //栈底指针
SElemType *top; //栈顶指针
int stacksize; //当前已分配的存储空间,以元素为单位
}Sqstack;
/*栈的初始化,分配失败返回0,否则返回让栈顶指针指向栈顶指针,并返回1*/
int InitStack(Sqstack &s)
{
s.base = (SElemType *)malloc(STACK_INTI_SIZE * sizeof(SElemType));
if(!s.base)
return 0; //存储分配失败,返回error
s.top = s.base; //分配成功则让栈顶指针指向栈底指针
s.stacksize = STACK_INTI_SIZE;
return 1;
}
/*若栈不为空,则用e返回s的栈顶元素,并返回OK,否则返回error*/
int Gettop(Sqstack &s)
{ int e;
if(s.top == s.base) return 0;
e = *(s.top - 1); //注意这条语句,是先让top-1指向栈顶元素,再取元素的。
return e;
}
/*插入元素e为新的栈顶元素,注意栈满的操作*/
int push(Sqstack &s,SElemType e)
{
if(s.top - s.base >= s.stacksize) //栈满,追加存储空间
{
//新分配空间的栈底
s.base = (int*)realloc(s.base, (s.stacksize +STACKINCREMENT)*sizeof(int)) ;
if(!s.base) return 0; //存储分配失败
/*realloc函数分配内存的方式:开辟一个新的空间,并且将原有空间的内容复制到新分配的空间中,
*但新分配的空间s.base = s.top的,所以才有s.top= s.base+ s.stacksize*/
s.top = s.base + s.stacksize;
s.stacksize += STACKINCREMENT;//给新分配的存储空间分配存储容量
}
*s.top++ = e; //注意指针*与++的优先级,top指针先上移
return 1;
}
/*出栈操作:若栈不为空,则删除栈顶元素,用e返回其值,否则返回error*/
int pop(Sqstack &s,SElemType *e)
{
if(s.top == s.base) return 0;//栈空
*e = *(--s.top);//注意此步操作
return 1;
}
/*判断输入的是否为包含在指定字符集中,如果是则返回1,否则返回0*/
int is_optr(char c)
{
switch(c)
{
case '+':
case '-':
case '*':
case '/':
case '(':
case ')':
case '#':
return 1;
default:
return 0;
}
}
/*返回运算符在数组中的索引*/
int index(char c)
{
int in;
switch(c)
{
case '+':
in = 0;
break;
case '-':
in = 1;
break;
case '*':
in = 2;
break;
case '/':
in = 3;
break;
case '(':
in = 4;
break;
case ')':
in = 5;
break;
case '#':
in = 6;
break;
}
return in;
}
/*运算符优先级的判定*/
char precede(char top,char c)
{
int i,j;
i=index(top);
j=index(c);
return cpri[i][j];
}
//运算函数
int operate(int a,char theta,int b)
{
int result;
switch(theta)
{
case '+':
result = a+b;
break;
case '-':
result = a-b;
break;
case '*':
result = a*b;
break;
case '/':
result = a/b;
break;
}
return result;
}
/*算术表达式的求值过程*/
int evaluate()
{
int k = 0;
int num = 0;
char c=0,theta=0;
char a=0,b=0;
Sqstack OPND;
Sqstack OPTR;
InitStack(OPTR);
InitStack(OPND);
push(OPTR,'#');
char exp[11]; //表达式
gets(exp);
c = exp[k];
k++;
while(c != '#' || Gettop(OPTR) != '#')
{
//不是运算符则进操作数栈
if(!is_optr(c))
{
num = c - '0'; //字符转换成十进制数
c = exp[k]; //读取下一字符
k++;
while(!is_optr(c)) //下一字符仍是数字
{
num = num * 10 + c - '0'; //转换成多位整数
c = exp[k];
k++;
}
push(OPND,num);
}
else
switch(precede(Gettop(OPTR),c))
{
case '<':
push(OPTR,c);
c = exp[k];//栈顶元素的优先权低
k++;
break;
case '=': //脱括号并接受下一字符
pop(OPTR,(int*)&c);
c = exp[k];
k++;
break;
case '>': //退栈并将运算结果入栈
pop(OPTR,(int*)&theta);
pop(OPND,(int*)&b);
pop(OPND,(int*)&a);
push(OPND,operate(a,theta,b));
break;
}
}
return Gettop(OPND);
}
void main()
{
printf("请输入表达式以#结尾: ");
printf("%d\n",evaluate());
}