数据结构实验二简单计算器

简单计算器。

请按照四则运算加、减、乘、除、幂(^)和括号的优先关系和惯例,编写计算器程序。要求:

  • 从键盘输入一个完整的表达式,以回车作为表达式输入结束的标志。
  • 输入表达式中的数值均为大于等于零的整数。中间的计算过程如果出现小数也只取整。

例如,输入:4+2*5=                           输出:14

      输入:(4+2)*(2-10)=                输出:-48

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"
typedef struct node     //定义栈元素
{
    char val;   //数据
    struct node *next;
}pnode;
typedef struct seqstack     //定义栈顶
{
    int size;
    pnode *top;
}phead;

//创建栈
phead* InitStack()
{
    phead* istack = (phead*)malloc(sizeof(phead));
    if(istack != NULL)  //健壮性判断
    {
        istack->top = NULL;
        istack->size = 0;
    }
    return istack;
}

//判断栈是否为空,栈空为1,不空为0
int isempty(phead* istack)
{
    if(istack->top == NULL)
    {
        return 1;
    }
    return 0;
}

//获取栈顶元素的数据节点
pnode* seqstack_top(phead* istack)
{
    if(istack->size != 0)
    {
        return istack->top;
    }
    return NULL;
}

//弹出栈顶元素
pnode* seqstack_pop(phead* istack)
{
    if(isempty(istack) == 0)
    {
        pnode* account = istack->top;
        istack->top = istack->top->next;
        istack->size--;
        return account;
    }
    return NULL;
}

//压栈
void seqstack_push(phead* istack, char x)
{
    pnode* temp = (pnode*)malloc(sizeof(pnode));
    temp->val = x;
    temp->next = istack->top;
    istack->top = temp;
    istack->size++;
}

//中缀表达式转后缀表达式
//结果串
char buffer[256] = {0};     //每个元素初始化为'\n'
//将字符存入结果串
void char_put(char ch)
{
    static int index = 0; //static定义静态变量,放函数中表示index只初始化一次,但保留index的改变
    buffer[index++] = ch; 
}

//比较优先级
int priority(char ch)
{
    int ret = 0;
    switch(ch)
    {
        case '+':
        case '-':
            ret = 1;
            break;
        case '*':
        case '/':
            ret = 2;
            break;
        case '^':
            ret = 3;
            break;
        default:
            break;
    }
    return ret;
}

//判断是否为数字
int is_number(char ch)
{
    return(ch>='0'&&ch<='9');
}

//是否为操作符
int is_operator(char ch)
{
    return(ch=='+' || ch=='-' || ch=='*' || ch=='/' || ch=='^');
}

//是否为左括号
int is_left(char ch)
{
    return(ch == '(');
}

//是否为右括号
int is_right(char ch)
{
    return(ch == ')');
}

int transform(char str[])//使用const保护数据,函数用来将中缀转换成后缀
 {
     phead* istack=InitStack();//创建一个栈
     int i=0;
     while(str[i]!='\0')//遍历整个字符串
    {
        //判断是不是数字
        if(is_number(str[i])==1)
        {
            if(is_number(str[i+1])==1)//后面1也是数字,则直接放
            {
                char_put(str[i]);//数字直接放入结果串(即输出)
            }
            else//后面不是数字,添加一个空格作为分隔符
            {
                char_put(str[i]);
                char_put(' ');
            }
        }
        else if(is_operator((str[i]))==1)
        {
            if(str[i+1]=='0'&&str[i]=='/')
            {
                printf("ILLEGAL");
                return 0;
            }
            if(isempty(istack)==0)//栈不为空
            {
                while((isempty(istack)==0)&&(priority(str[i])<=(priority(seqstack_top(istack)->val))))//栈不为空并且新运算符优先级不高于栈顶
                {
                    char_put(seqstack_pop(istack)->val);//满足条件的栈顶就弹出直到不满足条件
                    char_put(' ');
                }
            }
            seqstack_push(istack,str[i]);//再将该运算符入栈
        }
        else if(is_left(str[i]))//左括号直接入栈
        {
            seqstack_push(istack,str[i]);
        }
        else if(is_right(str[i]))//判断是不是右括号
        {
            while(is_left(seqstack_top(istack)->val)!=1)//栈顶不是左括号的情况
            {
                char_put(seqstack_pop(istack)->val);//弹出并存储到结果串
                if(isempty(istack)==1)//栈为空仍未找到左括号
                {
                    printf("没有匹配到左括号\n");
                    return -1;
                }
            }
            //此时匹配到了左括号
            seqstack_pop(istack);
            //弹出左括号,这里并不用保存,即两个括号相抵消
        }
        else
        {
            printf("有不能识别的字符\n");
            return -1;
        }
        i++;
    }
    //遍历完
    if(str[i]=='\0')//成功遍历到字符串末尾
    {
        while(isempty(istack)==0)//弹出全部栈中元素
        {
            if(seqstack_top(istack)->val=='(')//栈顶元素为左括号
            {
                printf("有没有匹配到的'(',缺少')'\n");
                return -1;
            }
            char_put(seqstack_pop(istack)->val);//将栈中元素放入最终串
        }
    }
    else
    {
        printf("遍历没有完成!\n");
    }
    return 1;
 }

typedef struct node1//这里的栈是整型栈
{
    int val;//数据
    struct node1* next;//指针
}pnode1;
typedef struct seqstack1
{
    int size;//记录栈的大小
    pnode1* top;//指向栈顶元素
}phead1;
phead1*  initstack1()//创建栈
{
    phead1* istack=(phead1*)malloc(sizeof(phead1));//为头节点分配空间
    if(istack!=NULL)//健壮性判断
    {
        istack->top=NULL;
        istack->size=0;
    }
    return istack;
}
int isempty1(phead1* istack)//判断栈为空
{
    if(istack->top==NULL)
    {
        return 1;//栈为空
    }
    return 0;//栈不为空
}
int seqstack_top1(phead1* istack)//获取栈顶元素
{
    if(istack->size!=0)//栈不为空
    {
        return istack->top->val;//返回的是栈顶的数据
    }
    return 99999;
}
int seqstack_pop1(phead1* istack)//弹出栈顶元素
{
    if(isempty1(istack)==0)//栈不为空
    {
        int account=istack->top->val;//记录栈顶的数据节点
        istack->top=istack->top->next;//指向栈顶下一个元素
        istack->size--;//记录栈的大小
        return account;//返回弹出的数据节点
    }
    return 99999;
}
void seqstack_push1(phead1* istack,int x)//压栈(入栈)
{
   pnode1* temp;//进行压栈的数据节点
   temp=(pnode1*)malloc(sizeof(pnode1));
   temp->val=x;//填充数据域
   temp->next=istack->top;//连接栈顶的数据节点
   istack->top=temp;//充当栈顶
   istack->size++;//记录栈大小的变化

}
 int express(int left,int right,char op)//op为运算符,返回运算结果
 {
     switch (op)
     {
        case '+':
            return left+right;
        case '-':
            return left-right;
        case '*':
            return left*right;
        case '/':
            if(right==0)
            {
                return 999;
            }
            return left/right;
        case '^':
            return (int)pow(left,right);
        default:
            break;
     }
     return -1;
 }
 int getsize(phead1* stack)
 {
     return stack->size;
 }
 int calculate(char str[])//计算后缀表达式
 {
     phead1* istack2=initstack1();//创建栈
     int i=0;
     while(str[i]!='\0')//遍历整个后缀表达式
    {
        char a[6]={0};
        int index=0;
        if(is_number(str[i])==1)
        {
            while(is_number(str[i])==1)
            {
                a[index]=str[i];
                index++;
                i++;
            }
            //成功读取数字
            seqstack_push1(istack2,atoi(a));//将该整数入栈
        }
        else if(is_operator(str[i])==1)
        {
            int right=seqstack_pop1(istack2);
            int left=seqstack_pop1(istack2);
            int ret=express(left,right,str[i]);
            if(ret==999)//被除数为0了
            {
                printf("ILLEGAL");
                return 999;
            }
            seqstack_push1(istack2,ret);//运算结果入栈
        }
        else if(str[i]==' ')
        {
 
        }
        else
        {
            printf("error\n");
            break;
        }
        i++;
    }
    if(str[i]=='\0'&&getsize(istack2))
    {
        return seqstack_top1(istack2);
    }
    return 0;
 }
int main()
{
    char str[100]={0};//将数组每个元素赋值为'\0'
    printf("请输入四则运算表达式:\n");
    scanf("%s",str);
    int number=transform(str);
    if(number==-1)
    {
        printf("表达式转换错误:\n");
        return 0;
    }
    //成功换成后缀表达式
 
 
    //下方计算后缀表达式
    int num=calculate(buffer);
    if(num==999)
    {
        return 0;
    }
    printf("%d\n",num);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值