表达式求值

时间限制:3000 ms | 内存限制:65535 KB
难度:4

描述
ACM队的mdd想做一个计算器,但是,他要做的不仅仅是一计算一个A+B的计算器,他想实现随便输入一个表达式都能求出它的值的计算器,现在请你帮助他来实现这个计算器吧。
比如输入:“1+2/4=”,程序就输出1.50(结果保留两位小数)
输入
第一行输入一个整数n,共有n组测试数据(n<10)。
每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。
数据保证除数不会为0
输出
每组都输出该组运算式的运算结果,输出结果保留两位小数。
样例输入
2
1.000+2/4=
((1+2)*5+1)/4=
样例输出
1.50
4.00

此题比较有代表性,搞清楚符号的优先级

代码:

#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

using namespace std;

#define STACK_INIT_SIZE 1024
#define STACKIN_INCREMENT 30

char Precede_Matrix[7][7]=
{
    {'>', '>', '<', '<', '<', '>', '>',},
    {'>', '>', '<', '<', '<', '>', '>',},
    {'>', '>', '>', '>', '<', '>', '>',},
    {'>', '>', '>', '>', '<', '>', '>',},
    {'<', '<', '<', '<', '<', '=', '0',},
    {'>', '>', '>', '>', '0', '>', '>',},
    {'<', '<', '<', '<', '<', '0', '=',}
};

char Precede(char a,char b)
{
    int i=0,j=0;
    switch(a)
    {
    case '+' :
        i = 0;
        break;
    case '-' :
        i = 1;
        break;
    case '*' :
        i = 2;
        break;
    case '/' :
        i = 3;
        break;
    case '(' :
        i = 4;
        break;
    case ')' :
        i = 5;
        break;
    case '#' :
        i = 6;
        break;
    default :
        cout << "Error1!" << endl;
    }
    switch(b)
    {
    case '+' :
        j = 0;
        break;
    case '-' :
        j = 1;
        break;
    case '*' :
        j = 2;
        break;
    case '/' :
        j = 3;
        break;
    case '(' :
        j = 4;
        break;
    case ')' :
        j = 5;
        break;
    case '#' :
        j = 6;
        break;
    default :
        cout << "Error1!" << endl;
    }
    return Precede_Matrix[i][j];
}

double Operate(double a,char oper,double b)
{
    switch(oper)
    {
    case '+':
        return a + b;
    case '-':
        return a- b;
    case '*':
        return a* b;
    case '/':
        return a / b;
    default:
        cout << "Error3!" << endl;
        return -1;
    }
}

struct stack_char
{
    char *base;
    char *top;
    int stacksize;
};

struct stack_double
{
    double *base;
    double *top;
    int stacksize;
};

template <class T2,class T1>//类模板
void InitStack(T1 &S)
{
    S.base=(T2*)malloc(STACK_INIT_SIZE*sizeof(T2));
    if(!S.base)
        cout<<"Overflow2!"<<endl;
    S.top=S.base;
    S.stacksize=STACK_INIT_SIZE;
}

template <class T2,class T1>
void Push(T1 &S,T2 e)
{
    if(S.top-S.base>=S.stacksize)
    {
        S.base=(T2*)realloc(S.base,(S.stacksize+STACKIN_INCREMENT)*sizeof(T2));
        if(!S.base)
            cout<<"Overflow3!"<<endl;
        S.top=S.base+S.stacksize;
        S.stacksize += STACKIN_INCREMENT;
    }
    *S.top++=e;
}

template <class T2,class T1>
void Pop(T1 &S,T2 &e)
{
    if(S.top==S.base)
        cout << "Stack is empty!!" << endl;
    e=*--S.top;
}

template <class T2,class T1>
T2 GetTop(T1 S)
{
    if(S.top==S.base)
        cout << "Stack is empty!!" << endl;
    return  *--S.top;
}

bool IsOperand(char c)
{
    if(('0'<=c&&c<='9')||c=='.')
        return true;
    else
        return false;
}

int main()
{
    string str;
    int T;
    cin>>T;
    while(T--)
    {
        cin>>str;
        str[str.length()-1]='#';
        // str.push_back('#');// 最后是#(结束标志)
        double a,b;
        char x;
        char theta;
        stack_char OPTR;
        InitStack<char>(OPTR);
        Push(OPTR,'#');
        stack_double OPND;
        InitStack<double> (OPND);
        int i=0;
        char c=str[i++];//

        double operand=0;

        while(!(c=='#'&&GetTop<char>(OPTR)=='#'))
        {
            if(IsOperand(c))
            {
                operand=atof(&str[i-1]); //把从c开头的数转化成double
                Push(OPND,operand);
                while(IsOperand(str[i]))
                    i++;
                c=str[i++];

            }
            else
            {
                switch(Precede (GetTop<char> (OPTR), c))
                {

                case '<':
                    Push(OPTR,c);
                    c=str[i++];
                    break;

                case '=':
                    Pop(OPTR,x);
                    c=str[i++];
                    break;
                case '>':
                    Pop(OPTR,theta);
                    Pop(OPND,b);
                    Pop(OPND,a);
                    Push(OPND,Operate(a, theta, b));
                    break;
                default:
                    cout<<"operator Error!"<<endl;
                    break;
                }
            }
        }
        printf("%0.2lf\n",GetTop<double>(OPND));
        //cout<<GetTop<double>(OPND)<<endl;

        free(OPTR.base);
        free(OPND.base);
    }
    return 0;
}