PTA7-4 后缀式求值 (25分) (题目 + 代码 + 详细注释 + 坑点分析)

我们人类习惯于书写“中缀式”,如 3 + 5 * 2 ,其值为13。 (p.s. 为什么人类习惯中缀式呢?是因为中缀式比后缀式好用么?)
而计算机更加习惯“后缀式”(也叫“逆波兰式”,Reverse Polish Notation)。上述中缀式对应的后缀式是: 3 5 2 * +
现在,请对输入的后缀式进行求值。

输入格式:

在一行中输入一个后缀式,运算数运算符之间用空格分隔,运算数长度不超过6位,运算符仅有+ - * / 四种。

输出格式:

在一行中输出后缀式的值,保留一位小数。

输入样例:

3 5.4 2.2 * +

输出样例:

14.9

 

题意:给定字符串,算出其后缀表达式的结果

方法:典型的栈的操作,当读入数字时,入栈;当读到运算符时,弹出栈顶的两个数进行运算,再把结果加入栈中(用STL的string和stack很容易实现)

注意点分析:

  • 判断负数和小数
  • 当做减法和除法运算时,第二个弹出的数才是被减数或被除数
  • 由题意知,除数不会是0,因为会运算错误,题目没有让给出错误提示

AC代码如下:

#include 
using namespace std;

stacknum;                 //声明一个栈,储存操作数

double cal(double x1, double x2, char c){          //给定两个数(x1先弹出)和操作符,得到计算结果
    if (c == '+')  return x1 + x2;
    if (c == '-')  return x2 - x1;               //注意是x2 - x1和 x2 / x1
    if (c == '*')  return x1 * x2;
    if (c == '/')  return x2 / x1;           
}

double change(string s) {                     //把字符串转成相应的数值
    double ans = 0, sign = 1;                //sign为符号,初始为1
    if (s[0] == '-') {                       //先判断负数
        sign = -1;                           //标记符号为负
        s.erase(s.begin());                 //把首位的负号抹去
    }
    int cnt = 0, flag = 0;                   //cnt是小数位的位数(即最后小数点要往左移多少位),flag表示是否发现了小数点,二者初始都是0
    for (int i = 0; s[i]; i++) {             //遍历字符串
        char c = s[i];                              
        if (c != '.') ans = ans * 10 + c - '0';          //如果是数字,则转换成对应的值(高位乘10加本位)
        else  flag = 1;                //发现了小数点,flag改为1
        if(c != '.') cnt += flag;      //小技巧:当发现了小数点之后,cnt每次都要+1,在此之前不变,即加0;而刚好和flag同步了,则可以直接加flag;这里的判断是因为,刚发现小数点时,cnt不加
    }
    if(cnt)  ans /= pow(10, cnt);                 //小数点移位操作,即除以10^cnt
    return sign * ans;                       //最后连带符号返回字符串对应的数值
}

int main() {
    string s;
    double ans;
    getline(cin, s);                     //对于中间有空格的字符串,要用getline
    for (int i = 0; s[i];) {             //遍历字符串
        string temp = "";                
        while (s[i] != ' ' && s[i])       //得到每两个空格之间的部分
            temp += s[i++];                  //string类可以把字符直接加到末尾
        if (s[i] == ' ')                  //跳过空格
            i++;
        if (temp == "+" || temp == "-" || temp == "*" || temp == "/") {       //如果是操作符
            double x1 = num.top();             //弹出两个数
            num.pop();
            double x2 = num.top();
            num.pop();
            ans = cal(x1, x2, temp[0]);         //进行运算
            num.push(ans);              //再把结果压入栈中
        }
        else                           //是操作数,就把string转换成double,并入栈
            num.push(change(temp));

    }

    printf("%.1f\n", ans);                          //输出最终结果
    return 0;
}

//常看我的博客都知道,我的博客讲解就像金针菇那么细,注释都很详细的。大神勿喷!

//先看后好习惯哦~

PTA7-4 后缀式求值 (25分) (题目 + 代码 + 详细注释 + 坑点分析)_第1张图片

你可能感兴趣的:(题解)