C语言实现用栈解决表达式求值(中缀转后缀+后缀求值)

1、在vscode实现的,文件后缀是C++,写的时候纯C。

2、关于加入负数的计算,有BUG,因为操作数的缺省,导致栈空,会出错。但是可以实现(0-2)*(0-3)这样的含负数表达式。

3.关于小数的计算,看了其他文章,改下栈数据的类型,没试。

4、prinf1111\2222\5555之类,作为个人对代码的验证

5、代码编写参考:发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/149219.html原文链接:https://javaforall.cn

#include <bits/stdc++.h>

typedef struct node
{
    int data;
    struct node *next;
}StackNode,*PStackNode;

typedef struct 
{
    PStackNode top;
}LinkStack,*PLinkStack;

PLinkStack InitStack(void)
{
    PLinkStack S;
    S = (PLinkStack)malloc(sizeof(LinkStack));
    if(S) S->top = NULL;
    return S;
}

bool IsEmpty(PLinkStack S)
{
    if(!S)
    {
        printf("栈不存在!\n");
        return false;
    }
    if(S->top == NULL)
        return true;
    else
        return false;
}

bool PushStack(PLinkStack S,int x)
{
    if(!S)
    {
        printf("栈不存在!\n");
        return false;
    }
    PStackNode p;
    p = (PStackNode)malloc(sizeof(StackNode));
    if(!p)
    {
        printf("申请内存失败!\n");
        return false;
    }
    p->data = x;
    p->next = S->top;
    S->top = p;
    return true;
}

bool PopStack(PLinkStack S,int *x)
{
    if(!S)
    {
        printf("栈不存在!\n");
        true;
    }
    if(IsEmpty(S))
    {
        printf("栈空!\n");
        true;
    }
    PStackNode p;
    p = S->top;
    *x = p->data;
    S->top = p->next;
    free(p);
    return true;
}

int GetTopElem(PLinkStack S)
{
    if(!S)
    {
        printf("栈不存在!\n");
        return -9999;
    }
    if(IsEmpty(S))
    {
        printf("栈空!\n");
        return -9999;
    }
    return (S->top->data);
}

bool DestroyStack(PLinkStack *S)
{
    PStackNode p,q;
    if(*S)
    {
        p = (*S)->top;
        while(p)
        {
            q = p;
            p = p->next;
            free(q);
        }
        free(*S);
    }
    *S = NULL;
    return true;
}

//怕是否为数字
int IsNum(char c)
{
    if(c>='0' && c<='9') return(1);
    else return(0);
}

//判断是否为运算符
int IsOperation(char c)
{
    switch(c)
    {
        case '+':
        case '-':
        case '*':
        case '#':
        case '/':return(1);
        case '(':return(2);
        case ')':return(3);
        default:
                return(0);
    }
}

//定义运算符优先级
int Priority(char c)
{
    switch(c)
    {
        case '#':return(1);
        case ')':return(2);
        case '+':
        case '-':return(3);
        case '*':
        case '/':return(4);
        case '(':return(5);
        default:return(0);
    }
}

//定义运算操作
int operate(int a,char c,int b)
{
    switch(c)
    {
        case '+':return a+b;
        case '-':return a-b;
        case '*':return a*b;
        case '/':
                if(b == 0)
                {
                    printf("除数不能为0!\n");
                    exit(0);
                }
                else
                    return a/b;
    }
}

int evaluate(char str[])
{
    PLinkStack S1,S2;
    int op;//存放弹出栈的运算符
    int x = 0,a = 0,b = 0,x1 = 0,x2 =0;//存放计算中间值
    int i = 0;
    int result= 0;
    S1 = InitStack();//存放操作符
    S2 = InitStack();//存放操作数
    if(PushStack(S1,'#'))
        printf("操作符#已入栈!\n");
    while(str[i] != '#' || GetTopElem(S1) != '#')
    {
        if(IsOperation(str[i]))//如果扫描的结果是运算符
        {
            printf("1111\n");
            if(GetTopElem(S1) == '(' && IsOperation(str[i]) == 3)
            {
                PopStack(S1,&x);
                i++;
            }
            else 
            {
                if(GetTopElem(S1) == '(' || Priority(str[i]) > Priority(GetTopElem(S1)))
                {
                    printf("2222\n");
                    PushStack(S1,str[i]);
                    i++;
                }
                else
                {
                    while(Priority(str[i]) <= Priority(GetTopElem(S1)))
                    {
                        if(GetTopElem(S1) != '(')
                        {
                            PopStack(S1,&op);
                            printf("%c\n",op);
                            if(op == '#')
                            {
                                PushStack(S1,op);
                                break;
                            }
                            PopStack(S2,&a);
                            PopStack(S2,&b);//先弹出栈的是右操作数
                            PushStack(S2,operate(b,op,a));
                        }
                        else
                        {
                            if(str[i] == ')')
                            {
                                PopStack(S1,&op);
                                i++;
                                break;
                            }
                            else
                            {
                                PushStack(S1,str[i]);
                                i++;
                                break;
                            }    
                        }
                    }
                }
                
            }   
        }
        else if(IsNum(str[i]))//如果扫描的结果是操作数
        {
            printf("5555\n");
            x1 = str[i]-'0';//字符型转换为数字
            printf("%d\n",x1);
            PushStack(S2,x1);
            x2 = x1;
            i++;

            while(IsNum(str[i]))//归并思想组合多位数
            {
                x1 = str[i] - '0';
                x2 = 10*x2 + x1;
                PopStack(S2,&x);
                PushStack(S2,x2);
                i++;
            }
        }
        else if(str[i] == ' ')//如过扫描的是空格
        {
            while(str[i] == ' ')
            {
                i++;
            }
        }
        else//除以上三种情况之外,为非法数据
        {
            printf("error!\n");
            printf("%d\n",i);
            exit(0);
        }
    }
    result = GetTopElem(S2);
    DestroyStack(&S1);
    DestroyStack(&S2);
    return result;
}

int main()
{
    char str[100]; //定义一个字符数组用于存储表达式,如果足够复杂的话也可以考虑单链表存储表达式
    int result;
    printf("Please Enter Expression:");//输入一定要以#结尾,因为while循环的判断条件为栈顶为#并且当前扫描的字符为#
    gets(str);
    puts(str);
    result=evaluate(str);
    printf("\n");
    printf("%s\n%d\n",str,result);
    return 0;
}

本文作为学习交流使用,欢迎大家指正与交流。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值