您的位置:首页 > 其它

利用栈的原理计算一个表达式的值

2015-12-09 19:58 465 查看
#include<stdio.h>

#include <stdio.h>

#include <malloc.h>

#include <ctype.h>

#define TRUE 1

#define FALSE 0

#define OK 1

#define ERROR 0

#define INFEASIBLE -1

#define OVERFLOW -2

#define STACK_INIT_SIZE 100

#define STACKINCREMENT 10

typedef int Status;

/*计算整数表达式的值

*表达式必须以#结束

*表达式中可以出现多位数字,

*表达式中可以出现空格

*运算符包括+,-,*,/,(,)

*运算结果可以是多位整数,并以整数的形式返回

*/

typedef int SElemType;/*放入堆栈的元素的类型*/

/*判断输入的某个字符是否是运算符

*c表示输入的字符

*op数组中存放系统能识别的运算符

*/

Status in(char c,char op[]){

char *p; //指针,用于指向op数组

p=op; //将op数组的地址给p,数组中的数组名一般表示数组的头地址,只要知道了头地址那么就可以访问数组了。

while(*p != '\0'){ //当

if(c == *p)

return TRUE;

p++;

}

return FALSE;

}

/*比较两个运算符的优先级

*a,b中存放待比较的运算符

*'>'表示a>b

*'0'表示不可能出现的比较

*/

char Precede(char a, char b){

int i,j;

char pre[][7]={

/*运算符之间的优先级制作成一张表格*/

{'>','>','<','<','<','>','>'},

{'>','>','<','<','<','>','>'},

{'>','>','>','>','<','>','>'},

{'>','>','>','>','<','>','>'},

{'<','<','<','<','<','=','0'},

{'>','>','>','>','0','>','>'},

{'<','<','<','<','<','0','='}};

switch(a){

case '+': i=0; break;

case '-': i=1; break;

case '*': i=2; break;

case '/': i=3; break;

case '(': i=4; break;

case ')': i=5; break;

case '#': i=6; break;

}

switch(b){

case '+': j=0; break;

case '-': j=1; break;

case '*': j=2; break;

case '/': j=3; break;

case '(': j=4; break;

case ')': j=5; break;

case '#': j=6; break;

}

return pre[i][j];

}

/*进行实际的运算

*a,b中分别以整数的形式存放两个待运算的操作数

*thea中存放代表操作符的字符

*结果以整数的形式返回

*/

int Operate(int a, char thea, int b){

int i,j,result;

i=a; //a,b中分别以整数的形式存放两个待运算的操作数

j=b;

switch(thea) {

case '+': result = i + j; break; //加法运算

case '-': result = i - j; break; //减法运算

case '*': result = i * j; break; //乘法运算

case '/': result = i / j; break; //除法运算

}

return result;

}

/*从输入缓冲区中获得下一个整数或运算符,并通过n带回到主调函数

*返回值为1表示获得的是运算符

*返回值为0表示获得的是整形操作数

*/

int getNext(int *n){

char c;

*n=0;

while((c=getchar())==' '); /*跳过一个或多个空格*/

if(!isdigit(c)){ /*通过函数判断如果字符不是数字,那么只能是运算符*/

*n=c;

return 1;

}

do { /*能执行到该条语句,说明字符是数字,此处用循环获得连续的数字*/

*n=*n*10+(c-'0'); /*把连续的数字字符转换成相对应的整数*/

c=getchar();

} while(isdigit(c)); /*如果下一个字符是数字,进入下一轮循环*/

ungetc(c,stdin); /*新读入的字符不是数字,可能是运算符,为了不影响下次读入,把该字符放回到输入缓冲区*/

return 0;

}

typedef struct{

SElemType *base;

SElemType *top;

int stacksize;

}SqStack;

//构造一个空栈

Status InitStack(SqStack *S){

S->base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));

if(!S->base)

printf("OVERFLOW");// exit(OVERFLOW);

S->top=S->base;

S->stacksize=STACK_INIT_SIZE;

return OK;

}

//判断是否为空栈

Status StackEmpty(SqStack S){

if(S.top == S.base)

return TRUE;

else

return FALSE;

}

//用e返回S的顶元素

Status GetTop(SqStack S, SElemType *e){

if(S.top == S.base)

return ERROR;

*e = *(S.top-1);

return OK;

}

//插入e为新的顶元素

Status Push(SqStack *S, SElemType e){

if((S->top - S->base) >= S->stacksize){

S->base = (

SElemType*)realloc(S->base,

(S->stacksize+STACKINCREMENT)*sizeof(SElemType)

);

if(!S->base)

return ERROR;// exit(OVERFLOW);

S->top = S->base +S->stacksize;

S->stacksize += STACKINCREMENT;

}

*(S->top)=e;

S->top++;

return OK;

}

//删除S的顶元素,并用e返回其值

Status Pop(SqStack *S, SElemType *e){

if(S->top == S->base)

return ERROR;

S->top--;

*e = *(S->top);

return OK;

}

//从栈底到栈顶依次对S的每个元素调用函数Visit(),一旦失败操作无效

Status ListTraverse(SqStack S,Status (*visit)(SElemType)){

SElemType *p;

p=S.base;

for(p=S.base;p<S.top;p++)

(*visit)(*p);

return OK;

}

//输出元素e

Status output(SElemType e){

printf("%d ",e);

return OK;

}

int EvaluateExpression()//操作函数

{

// int n;

int flag; //0,1标志

int c;

SElemType x,thea;

int a,b;

char OP[]="+-*/()#";

SqStack OPTR;

SqStack OPND;

InitStack(&OPTR);//构造空栈

Push(&OPTR,'#'); //元素入栈

InitStack(&OPND);

flag=getNext(&c);//调用getNext函数

GetTop(OPTR,&x); //调用GetTop函数,获得栈顶元素值给x

while(c!='#' || x != '#') //当c不是结束标志并且x也不是结束标识时

{

if(flag == 0)

{

Push(&OPND,c); //调用Push函数,新元素入栈

flag = getNext(&c); //调用getNext函数

} else

{

GetTop(OPTR, &x); //调用GetTop函数,获得栈顶元素值给x

switch(Precede(x,c))

{

case '<'://栈顶元素优先级低

Push(&OPTR,c);

flag = getNext(&c);

break;

case '='://脱括号并接受下一字符

Pop(&OPTR,&x);

flag = getNext(&c);

break;

case '>':// 退栈并将运算结果入栈

Pop(&OPTR, &thea);

Pop(&OPND,&b);

Pop(&OPND,&a);

Push(&OPND, Operate(a, thea, b));

break;

}

}

GetTop(OPTR, &x);

}

GetTop(OPND, &c);

return c; //返回值c

}

void main(){

int c;

printf("请输入您想输入的符号或数字:");

c=EvaluateExpression(); //调用EvaluateExpression函数

printf("计算结果=%d\n",c); //输出c

fflush(stdin);//以下这两个函数是为了解决程序有时闪屏而用的

getchar();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: