数据结构大作业 用二叉树实现计算器算法

模拟计算器.算术表达式的求解

【问题描述】

给定一个算术表达式,通过程序求出最后的结果。

【实现要求】

(1)数值:包括整数和实数,数值可带正、负号。

(2)运算符:正号、负号、加、减、乘、除、求模和乘方,其中可以包含括号。

【实现提示】

(1)从键盘输入要求解的算术表达式;

(2)采用二叉树进行算术表达式的求解过程;

(3)能够判断算术表达式正确与否;

(4)对于错误表达式给出提示;

(5)对于正确的表达式给出最后的结果;

【程序代码】

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <ctype.h>

#define num_MAX 10000000

typedef struct  TNode{

    int flag;

    int data;//flag=0

    char ch;//flag=1

    struct TNode * lChild;//左孩子

    struct  TNode * rChild;//右孩子

}BiNode,*BiTree;

int cal(BiTree T)

{//判断是数字还是符号

    if(T->flag==1)        //如果是字符,进行switch分支选择语句       

{

        switch(T->ch)

{

            case '+':    //加运算

                return cal(T->lChild)+cal(T->rChild);

                break;

            case '-':   //减运算

                return cal(T->lChild)-cal(T->rChild);

                break;

            case '/':   //除运算,除号不为零

if(cal(T->rChild)!=0)

                return cal(T->lChild)/cal(T->rChild);

                break;

            case '*':    //乘运算

                return cal(T->lChild)*cal(T->rChild);

                break;

            case '%':    //模运算

return cal(T->lChild)%cal(T->rChild);

break;

case '^':    //乘方运算

float sum=1;

for(int i=0;i<cal(T->rChild);i++)

{

sum*=cal(T->lChild);

 }

return sum;

break;

        }

    }

    return T->data;

}

int check(char s[],int start,int end)       //检查输入情况

{

    int i;

    int sum=0;

    int flag=1; //正数

for(int i=start;i<=end;i++)

    {

     if((s[i]>='a'&&s[i]<='z')||(s[i]>='A'&&s[i]<='Z')) //当输入字母时,返回-1

return -1;

    }

    for(int i=start;i<=end;i++)

    {

     if(s[i]=='#')

     return 1;

}

    if(s[start]=='-')       //如果一开始为负数

{

        flag=-1;

        start++;

    }

    for(i=start;i<=end;i++)

{

        if(!isdigit(s[i])) //如果不是是数字

return num_MAX;

        sum=sum*10+s[i]-'0';//如果是数字

    }

    return sum*flag;

    

}

BiTree buildTree(char s[],int start,int end)//建立二叉树

{

    BiTree T=(BiTree)malloc(sizeof(BiNode));//向内存申请空间

    if(start>end)

return NULL;

    int pos1=0;//加减号位置

    int num1=0;//加减号个数

    int pos2=0;//乘除号位置

    int num2=0;//乘除号个数

    int pos3=0;//模乘方位置

    int num3=0;//模乘方个数

    int num;

    num=check(s,start,end);    

    if(num!=num_MAX)         //只有数字

{

        T->flag=0;

        T->data=num;

        T->lChild=NULL;

        T->rChild=NULL;

        return T;

    }

    //有操作符

    int in_brackets=0;//在括号里的标识符

    for(int k=start;k<=end;k++)

{

        if(s[k]=='(') //括号

{

            in_brackets++;

        }

        else if(s[k]==')')

{

            in_brackets--;

        }

        else if(!in_brackets)      //括号之外 或者没有括号的算式

{

            if(s[k]=='+'||s[k]=='-')

{

                pos1=k;

                num1++;

            }

            else if(s[k]=='*'||s[k]=='/')

{

                pos2=k;

                num2++;

            }

            else if(s[k]=='%' || s[k]=='^')

            {

             pos3=k;

             num3++;

}  

        }

    }

    int pos_T;

    //寻找根节点 有加减用加减没加减用乘除        //(1+1)*2

    if(num1)

{

        pos_T=pos1;

    }

    else if(num2)

{

        pos_T=pos2;

    }

    else if(num3)

    {

     pos_T=pos3;

}

    else{//找不到根 递归再找一次

        return buildTree(s,start+1,end-1);            // 11+22*3-16/4

    }

    T->flag=1;

    T->ch=s[pos_T];

    T->lChild = buildTree(s,start,pos_T-1);

    T->rChild = buildTree(s,pos_T+1,end);

    return T;

}

int main()

 {

    while(1){

     int m;

        char a[200];

        printf("请输入表达式:");        //键盘输入算术表达式

        scanf("%s",a);

        m=check(a,0,strlen(a));

        if(m==-1)                    //判断算术表达式是否正确

        {

         printf("输入错误表达式!"); //错误表达式提示

         return 0;

}

if(m==1) //判断用户是否要求退出,#为退出指示

{

printf("程序结束运行!"); //程序退出提示

return 0;

}

printf("你输入的表达式结果为:%s=",a);//正确输出结果

        BiTree b=(BiTree)malloc(sizeof(BiTree));

        b=buildTree(a,0,strlen(a)-1);

        printf("%d\n",cal(b));     

    }

    return 0;

}

【运行结果】

程序主界面如图所示

错误表达式提示如图所示

cal加减乘除乘方模运算如图所示

程序退出如图所示

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我要半糖zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值