首页 > 代码库 > 求前缀表达式的值

求前缀表达式的值

/* 求前缀表达式的值(25)

时间限制
400 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard

算术表达式有前缀表示法、中缀表示法和后缀表示法等形式
前缀表达式指二元运算符位于两个运算数之前,
例如2+3*(7-4)+8/4的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4
请设计程序计算前缀表达式的结果值。

输入格式说明:
输入在一行内给出不超过30个字符的前缀表达式,只包含+、-、*、\以及运算数,
不同对象(运算数、运算符号)之间以空格分隔

输出格式说明:
输出前缀表达式的运算结果,精确到小数点后1位,或错误信息“ERROR”

样例输入与输出:
序号   输入	                        输出
1	   + + 2 * 3 - 7 4 / 8 4        13.0
2	   / -25 + * - 2 3 4 / 8 4      12.5
3	   / 5 + * - 2 3 4 / 8 2        ERROR
4	   +10.23                       10.2

分析:
1)将所有元素顺序放入队列,如发现其后跟两个数的符号,
   丢弃符号和两数,并将将结果放入符号位置
2)往返进行,直到最后只剩一个元素,输出
3)计算如出现错误,输出ERROR并返回,如结果无误输出时结果保留一位小数
*/
#include<iostream>
#include<string>
#include<sstream>
#include<cstdlib> // gcvt 或 sprintf
#include<iomanip>
using namespace std;


double Calcult(string op, double a, double b)
{
    switch(op[0])
    {
    case '+':return a + b; break;
    case '-':return a - b; break;
    case '*':return a * b; break;
    case '/':return a / b; break;
    }
}


void Input(string q[], int& i)
{
    string line,str;
    getline(cin, line, '\n');
    istringstream stream(line);
    i = 0;
   
    // 此步已去除正数前的正号
    while(stream >> str)
    {     
        q[i++] = str;
    }
}

bool IsOper(string& item)
{
   return (item == "+" || item == "-" || item == "*" || item == "/") ? true : false;
}

void GetVal(string q[], int len)
{
    double a, b;
    string op;
    char val[20];

    while(len > 1)
    {
        for(int i = 0; i < len; ++i)
        {
            if( IsOper(q[i]) )
            {
                if(i + 2 < len && !IsOper(q[i + 1]) && !IsOper(q[i + 2]))
                {
                    op = q[i];
                    a = strtod(q[i + 1].c_str(), NULL);
                    b = strtod(q[i + 2].c_str(), NULL);
                    if(op == "/" && b == 0)
                    {
                        cout << "ERROR" << endl;
                        return;
                    }
                    for(int j = i+1; j < len-2; ++j)
                        q[j] = q[j + 2];
                    len -= 2;

                    // Linux 下不能用 sprintf_s, 也不能用 _gcvt_s, 
                    // 而用 gcvt(浮点值, 15, val); 其中 15 是有效位数

                    // 缓冲区、缓冲区大小(减1位,保存结束符?)、浮点数、有效位数(最大为17) 
                    _gcvt_s(val, 19, Calcult(op, a, b), 17); 
                    q[i] = val;
                }
            }           
        }
    }
    cout << setiosflags(ios::fixed) << setprecision(1) << strtod(q[0].c_str(),NULL) << endl;  
}

void Run()
{
    string q[30]; 
    int len;
    Input(q,len);
    GetVal(q,len);
}

int main(void)
{
    Run();
    return 0;
}

求前缀表达式的值