栈的应用:计算字符串表达式

说明:

1. 通过栈来实现字符串公式的运算;

2. 中缀转后缀:
  遍历中缀表达式中的数字和符号
  对于数字: 直接输出
  对于符号:
    ->左括号: 进栈
    ->符号:  与栈顶符号进行优先级比较
         栈顶符号的优先级低: 符号进栈
         栈顶符号的优先级高: 将栈顶符号弹出并输出,之后进栈
    ->右括号: 将栈中的所有符号弹出并输出

3. 计算后缀的值:
  遍历后缀表达式中的数字和符号
  对于数字: 进栈
  对于符号:
    ->从栈中弹出右操作数
    ->从栈中弹出左操作数
    ->根据符号进行运算
    ->将运算结果压入栈中
  遍历结束:栈中的唯一数字为计算结果

4. 这里采用了代码复用的方法,即使用了LinkList链表和LinkStack链栈,详见《LinkList单向链表》 《LinkStack链栈》


代码:

main.c

#include <stdio.h>
    #include "LinkStack.h"

    //输出
    void output(char c)
    {
        if (c != '\0')
        {
            printf("%c", c);
        }
    }

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

    //判断是否为操作符
    int isOperator(char c)
    {
        return (c == '+') || (c == '-') || (c == '*') || (c == '/');
    }

    //是否为'('
    int isLeft(char c)
    {
        return (c == '(');
    }

    //是否为')'
    int isRight(char c)
    {
        return (c == ')');
    }

    //比较优先级
    int priority(char c)
    {
        int ret = 0;

        if ((c == '+') || (c == '-'))
        {
            ret = 1;
        }

        if ((c == '*') || (c == '/'))
        {
            ret = 2;
        }

        return ret;
    }

    //字符转数字
    int value(char c)
    {
        return (c - '0');
    }

    //计算左右操作数的值
    int express(int left, int right, char op)
    {
        int ret = 0;

        switch (op)
        {
        case '+':
            ret = left + right;
            break;
        case '-':
            ret = left - right;
            break;
        case '*':
            ret = left * right;
            break;
        case '/':
            ret = left / right;
            break;
        default:
            break;
        }

        return ret;
    }

    //中缀转后缀,返回后缀字符串,并输出
    char* transform(const char* exp)
    {
        LinkStack* stack = LinkStack_Create();
        char* ret = (char*)malloc(100 * sizeof(char));
        memset(ret, '\0', 100 * sizeof(char));
        int j = 0;
        int i = 0;

        while (exp[i] != '\0')
        {
            int i = 10 * (1 + 5) + 5;
            //判断是否为数字
            if (isNumber(exp[i]))
            {
                output(exp[i]);
                ret[j++] = exp[i];
            }
            //判断是否为操作符
            else if (isOperator(exp[i]))
            {
                //遍历栈内符号,如果当前操作符的优先级小于栈顶的操作符,则弹出栈顶,并输出
                while (priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack)))
                {
                    output(ret[j++] = (char)(int)LinkStack_Pop(stack));
                }
                //将当前操作符压入栈
                LinkStack_Push(stack, (void*)(int)exp[i]);
            }
            //判断是否为'('
            else if (isLeft(exp[i]))
            {
                LinkStack_Push(stack, (void*)(int)exp[i]);
            }
            //判断是否为')'
            else if (isRight(exp[i]))
            {
                char c = '\0';
                //遍历栈内元素,弹出非 '(' 的元素
                while (!isLeft((char)(int)LinkStack_Top(stack)))
                {
                    output(ret[j++] = (char)(int)LinkStack_Pop(stack));
                }
                //弹出'('
                LinkStack_Pop(stack);
            }
            else
            {
                printf("Invalid expression!");
                break;
            }

            i++;
        }
        //弹出栈内所有元素
        while ((LinkStack_Size(stack) > 0) && (exp[i] == '\0'))
        {
            output(ret[j++] = (char)(int)LinkStack_Pop(stack));
        }

        LinkStack_Destroy(stack);

        return ret;
    }

    //计算整个表达式的值
    int compute(const char* exp)
    {
        LinkStack* stack = LinkStack_Create();
        int ret = 0;
        int i = 0;

        while (exp[i] != '\0')
        {
            if (isNumber(exp[i]))
            {
                LinkStack_Push(stack, (void*)value(exp[i]));
            }
            else if (isOperator(exp[i]))
            {
                int right = (int)LinkStack_Pop(stack);
                int left = (int)LinkStack_Pop(stack);
                int result = express(left, right, exp[i]);

                LinkStack_Push(stack, (void*)result);
            }
            else
            {
                printf("Invalid expression!");
                break;
            }

            i++;
        }

        if ((LinkStack_Size(stack) == 1) && (exp[i] == '\0'))
        {
            ret = (int)LinkStack_Pop(stack);
        }
        else
        {
            printf("Invalid expression!");
        }

        LinkStack_Destroy(stack);

        return ret;
    }


    int main()
    {
        printf("8 * 2 + 1 - ( 5 - 1 ) / 2 + 2 - 1\n中缀转后缀后结果为:");
        char* _strExpression = transform("8*2+1-(5-1)/2+2-1");
        printf("\n");
        printf("计算结果为:%d ", compute(_strExpression));
        printf("\n");


        system("pause");

        return 0;
    }

函数结构分析:

1.isNumber

2.isOperator

3.isLeft

4.isRight

5.priority

6.express

7.transform

8.compute

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值