【练习】算术表达式求值

  在编译系统中都必须提供算术表达式求值功能,也是通过栈来实现。下面介绍一个简单的算术表达式求值功能的实现,只能对整数的四则混合运算表达式求值。下图为算法流程图。


这里写图片描述

  • 栈头文件
typedef struct stack
{
    DATA data[SIZE+1]; //数据元素 
    int top; //栈顶 
}SeqStack;
SeqStack *SeqStackInit()
{
    SeqStack *p;
    if(p=(SeqStack *)malloc(sizeof(SeqStack))) //申请栈内存 
    {
        p->top=0; //设置栈顶为0 
        return p;//返回指向栈的指针 
    }
    return NULL;
}
int SeqStackIsEmpty(SeqStack *s) //判断栈是否为空 
{
    return(s->top==0);
}
void SeqStackFree(SeqStack *s) //释放栈所占用空间 
{
    if(s)
        free(s);
}
void SeqStackClear(SeqStack *s)  //清空栈 
{
    s->top=0;
} 
int SeqStackIsFull(SeqStack *s) //判断栈是否已满
{
    return(s->top==SIZE);
} 
int SeqStackPush(SeqStack *s,DATA data) //入栈操作 
{
     if((s->top+1)>SIZE)
     {
         printf("栈溢出!\n"); 
         return 0;
     }
     s->data[++s->top]=data;//将元素入栈
     return 1; 
}
DATA SeqStackPop(SeqStack *s) //出栈操作 
{
     if(s->top==0)
     {
         printf("栈为空!");
         exit(0);
     }
     return (s->data[s->top--]);
}
DATA SeqStackPeek(SeqStack *s) //读栈顶数据
{
     if(s->top==0)
     {
         printf("栈为空!");
         exit(0);
     }
     return (s->data[s->top]);
} 
  • 表达式求值文件
#include<stdio.h> 
#include<stdlib.h>
#define SIZE 50
typedef int DATA;
int IsOperator(char c) //检查字符是否为运算符 
{
    switch(c)
    {
        case'+':
        case'-':
        case'*':
        case'/':
        case'(':
        case')':
        case'=':
            return 1;
            break;
        default:
            return 0;
            break;
    } 
}

  在计算表达式时,为了方便判断,增设了一个等号“=”作为表达式的定界符,即表达式以“=”开头,以“=”结束。
  在计算表达式的值时,需要比较前后两个运算符的优先级。

int PRI(char oper1,char oper2) //判断两个运算符的优先级
// oper1>oper2返回1 
//oper1<oper2返回-1
//oper1=oper2返回0 
{
    int pri;
    switch(oper2) //判断运算符优先级 
    {
        case '+':
        case '-':
            if(oper1=='('||oper1=='=') //为左括号或表达式开始符号 
                pri=-1; //返回小于 
            else 
                pri=1;
            break;
        case '*':
        case '/':
            if(oper1=='*'||oper1=='/'||oper1==')')
                pri=1;
            else
                pri=-1;
            break;
        case '(':
            if(oper1==')') //右括号右侧不能马上出现左括号 
            {
                printf("语法错误!\n");
                exit(0);
            }else
                pri=-1;
            break;
        case')':
            if(oper1=='(')
                pri=0;
            else if (oper1=='=')
            {
                printf("括号不匹配!\n");
                exit(0);
            }else
                pri=1;
            break;
        case '=' :
            if(oper1=='(')
            {
                printf("括号不匹配!\n");
                exit(0);
            }else if(oper1=='=')
                pri=0;
            else
                pri=1;
            break;
    }
    return pri; 
}

  该函数中,根据传入的两个运算符进行判断,得到不同的优先级。在主调函数中再根据优先级决定是入栈还是计算。
  对于优先级高的运算符,需将运算符两侧的数据进行计算。

int Calc(int a,int oper,int b) //计算两个操作数的结果 
{
    switch(oper)
    {
        case'+':return a+b;
        case'-':return a-b;
        case'*':return a*b;
        case'/':
            if(b!=0)
               return a/b;
            else
            {
                printf("除0溢出!\n");
                exit(0); 
            }  
    }
} 

  编写好以上辅助函数就可以编写计算表达式值的函数了

int CalcExp(char exp[]) //表达式计算函数 
{
    SeqStack *StackOper,*StackData;
    int i=0,flag=0;
    DATA a,b,c,q,x,t,oper;

    StackOper=SeqStackInit(); //初始化两个栈 
    StackData=SeqStackInit();

    q=0;
    x='=';
    SeqStackPush(StackOper,x); //首先将等号(=)进入操作符栈 
    x=SeqStackPeek(StackOper); //获取操作符栈的首元素  
    c=exp[i++];
    while(c!='=' || x!='=')
    {
        if(IsOperator(c)) //若输入的是运算符 
        {
            if(flag){
                SeqStackPush(StackData,q);//将操作数入栈 
                q=0;
                flag=0;
            }
            switch(PRI(x,c)) //判断运算符的优先级 
            {
                case -1:
                    SeqStackPush(StackOper,c);//运算符进栈 
                    c=exp[i++];
                    break;
                case 0:
                    c=SeqStackPop(StackOper); //运算符出栈 (抛弃)
                    c=exp[i++];
                    break;
                case 1:
                    oper=SeqStackPop(StackOper); //运算符出栈 
                    b=SeqStackPop(StackData);//两个操作数出栈 
                    a=SeqStackPop(StackData);
                    t=Calc(a,oper,b);
                    SeqStackPush(StackData,t);//将运算结果入栈 
                    break;
            }
        }else if(c>='0'&&c<='9') //若输入字符在0~9之间 
        {
            c-='0';
            q=q*10+c;
            c=exp[i++];
            flag=1;
        }
        else
        {
            printf("输入错误!\n");
            getch();
            exit(0);
        }
        x=SeqStackPeek(StackOper);//获取栈顶的运算符 
    }
    q=SeqStackPop(StackData);
    SeqStackFree(StackOper);    //释放栈所占用的空间 
    SeqStackFree(StackData);
    return q; //出栈,返回结果 
} 

  主函数只需提示用户输入一个表达式字符串,然后调用CalExp函数即可。

int main() 
{
    int c;
    char exp[80];
    printf("请输入要计算的表达式(以=结束):"); 
    scanf("%s",exp);
    printf("%s%d\n",exp,CalcExp(exp));
    getch();
    return 0;
}
  • 测试结果

这里写图片描述

  • 6
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值