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

来源:互联网 发布:java反射得到属性 编辑:程序博客网 时间:2024/06/01 16:34
#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();


}  
0 0
原创粉丝点击