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

来源:互联网 发布:儿童英语跟读软件 编辑:程序博客网 时间:2024/06/05 04:32

说明:

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