栈-表达式求值

#include <cstdio>
#include <malloc.h>
#include <cstring>
#define MAXSIZE 101

//运算符栈
struct OpStack
{
    char data[MAXSIZE];
    int top; //栈顶元素下一个元素的下标
};

//初始化运算符栈
OpStack *Init_Op()
{
    OpStack *sOp;
    sOp = (OpStack *)malloc(sizeof(OpStack));
    sOp->top = 0;
    return sOp;
}

//入运算符栈
int Push_Op(OpStack *sOp, char ch)
{
    if (sOp->top == MAXSIZE)
    {
        return 0;
    }
    else
    {
        sOp->data[sOp->top] = ch;
        sOp->top++;
        return 1;
    }
}

//出运算符栈
int Pop_Op(OpStack *sOp, char *ch)
{
    if (sOp->top == 0)
    {
        return 0;
    }
    else
    {
        *ch = sOp->data[sOp->top-1];
        sOp->top--;
        return 1;
    }
}

//获取运算符栈栈顶元素
char GetTop_Op(OpStack *sOp)
{
    return sOp->data[sOp->top-1];
}

//判断运算符栈是否为空
int IsEmpty_Op(OpStack *sOp)
{
    return sOp->top == 0;
}

//操做数栈
struct NumStack
{
    float data[MAXSIZE];
    int top; //栈顶元素下一个元素的下标
};

//初始化操做数栈
NumStack *Init_Num()
{
    NumStack *sNum;
    sNum = (NumStack *)malloc(sizeof(NumStack));
    sNum->top = 0;
    return sNum;
}

//入操做数栈
int Push_Num(NumStack *sNum, float num)
{
    if (sNum->top == MAXSIZE)
    {
        return 0;
    }
    else
    {
        sNum->data[sNum->top] = num;
        sNum->top++;
        return 1;
    }
}

//出操做数栈
int Pop_Num(NumStack *sNum, float *num)
{
    if (sNum->top == 0)
    {
        return 0;
    }
    else
    {
        *num = sNum->data[sNum->top-1];
        sNum->top--;
        return 1;
    }
}

//获取操做数栈栈顶元素
float GetTop_Num(NumStack *sNum)
{
    return sNum->data[sNum->top-1];
}

//判断操做数栈是否为空
int IsEmpty_Num(NumStack *sNum)
{
    return sNum->top == 0;
}

//判断运算符的优先级
int priority(char ch)
{
    if (ch=='=' || ch=='(')
    {
        return 0; //使左括号和等号的优先级最低
    }
    else if (ch=='+' || ch=='-')
    {
        return 1;
    }
    else if (ch=='*' || ch=='/')
    {
        return 2;
    }
}

//计算结果
float result(float x, float y, char ch)
{
    if (ch == '+')
    {
        return y+x;
    }
    else if (ch == '-')
    {
        return y-x;
    }
    else if (ch == '*')
    {
        return y*x;
    }
    else if (ch == '/')
    {
        return y/x;
    }
}

//中缀表达式转换为后缀表达式
void toPostfix(char inf[], char post[])
{
    //post为存放后缀表达式的字符数组
    int index = 0; //用于动态的表示post数组的下标
    bool isNum = false; //用于判断以前是否出现过数字
    OpStack *sOp; //定义运算符栈
    sOp = Init_Op(); //初始化运算符栈
    char ch;//接收出栈的左括号

    //循环遍历中缀表达式
    for (int i=0; i<strlen(inf); i++)
    {
        //判断是否为数字或者小数点
        if (inf[i]>='0' && inf[i]<='9' || inf[i]=='.')
        {
            isNum = true; //将布尔值置为真
            post[index++] = inf[i]; //直接将数字加入到post数组中
        }
        else
        {
            //若是输入空格,结束本次循环
            if (inf[i] == ' ')
            {
                continue ;
            }

            //判断以前是否出现了数字
            if (isNum)
            {
                post[index++] = '#';
                isNum = false; //将布尔值置为假
            }

            //判断是否结束
            if (inf[i] == '=')
            {
                break;
            }

            //判断是否为'('或者栈空
            if (inf[i]=='(' || IsEmpty_Op(sOp))
            {
                //将其入栈
                Push_Op(sOp, inf[i]);
            }
            else if (inf[i]==')')
            {
                //循环到左括号
                while (GetTop_Op(sOp) != '(')
                {
                    //依次出栈,并加入到post数组中
                    Pop_Op(sOp, &post[index++]);
                }

                Pop_Op(sOp, &ch);//将左括号出栈
            }
            else if (!IsEmpty_Op(sOp) && priority(inf[i])<=priority(GetTop_Op(sOp)))
            {
                //栈不为空,且此运算符的优先级低于或等于栈顶元素优先级
                while (!IsEmpty_Op(sOp) && priority(inf[i])<=priority(GetTop_Op(sOp)))
                {
                    //出栈加post
                    Pop_Op(sOp, &post[index++]);
                }

                //循环完毕,把此运算符压入栈中
                Push_Op(sOp, inf[i]);
            }
            else
            {
                //直接把此运算符压入栈中
                Push_Op(sOp, inf[i]);
            }
        }
    }

    //遍历完成
    //将栈顶运算符出栈,加入到post中
    Pop_Op(sOp, &post[index++]);

    //字符串末尾加上'\0'
    post[index] = '\0';
    return ;
}

//计算后缀表达式
float caPostfix(char post[])
{
    NumStack *sNum; //定义一个操做数栈
    sNum = Init_Num();//初始化操做数栈
    float res; //存放结果
    bool isPoint;//判断是否有小数点
    float pos;//10的倍数
    float temp1; //存放操做数1
    float temp2;//存放操做数2

    for (int i=0; i<strlen(post); i++)
    {
        res = 0;
        isPoint = false;
        pos = 10;

        //判断是否为数字
        if (post[i]>='0' && post[i]<='9')
        {
            //数字没结束前
            for (; post[i]!='#'; i++)
            {
                if (post[i]=='.')
                {
                    isPoint = true;
                    i++;
                }

                //若是没有小数点,整数部分
                if (!isPoint)
                {
                    res = res*10+post[i]-'0';
                }
                else
                {
                    res += (post[i]-'0')/pos;
                    pos *= 10;
                }
            }

            //把结果入栈
            Push_Num(sNum, res);
        }
        else
        {
            Pop_Num(sNum, &temp1);//出栈第一个操做数
            Pop_Num(sNum, &temp2);//出栈第二个操做数
            Push_Num(sNum, result(temp1, temp2, post[i]));//结果入栈
        }
    }
    return GetTop_Num(sNum);
}

int main()
{
    printf("|-----------表达式求解----------|\n");
    printf("|1.该程序支持浮点数运算         |\n");
    printf("|2.该程序支持空格输入           |\n");
    printf("|3.该程序支持多重小括号运算     |\n");
    printf("|注:此程序使用的是后缀表达式计算|\n");
    printf("|-------------------------------|\n");
    char inf[MAXSIZE];//定义一个存放中缀表达式的字符数组
    printf("请输入你须要计算的中值表达式(eg:(2*(2*(3+1))+1=,注意末尾有一个=号.):\n");
    gets(inf);//输入中缀表达式字符数组

    char post[MAXSIZE];
    toPostfix(inf, post);
    printf("Postfix:%s\n", post);

    float res;
    res = caPostfix(post);
    printf("Result:%s%.2f\n", inf, res);

    return 0;
}