PTA7-4 suffix evaluation (25 points) (question + code + detailed comment + pit analysis)

We humans are accustomed to writing "infix", for example  3 + 5 * 2 , its value 13. (ps Why are humans accustomed to infix style? Is it because infix style is
easier to use than suffix style?) And computers are more accustomed to "suffix style" (also called "reverse Polish notation"). The suffix formula corresponding to the above infix formula is:  3 5 2 * +
Now, please evaluate the entered suffix formula.

Input format:

On a single line a postfix, 运算数and 运算符separated by a space, the length of the operands does not exceed 6bits, only the operator + - * / of four.

Output format:

Output the suffix value in one line, with one decimal place.

Input sample:

3 5.4 2.2 * +

Sample output:

14.9

 

Question: Given a string, calculate the result of its suffix expression

Method: A typical stack operation , when a number is read, it is pushed into the stack; when an operator is read, the two numbers on the top of the stack are popped to perform operations, and then the result is added to the stack (using STL string and stack is easy to achieve )

Note analysis:

  • Judge negative numbers and decimals
  • When doing subtraction and division operations, the second pop-up number is the subtracted or dividend
  • According to the question, the divisor will not be 0, because the calculation will be wrong, and the question will not give an error prompt

The AC code is as follows:

#include<bits/stdc++.h> 
using namespace std;

stack<double>num;                 //声明一个栈,储存操作数

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;
}

//I often read my blog and know that my blog is as detailed as enoki mushroom , and the comments are very detailed. Do not spray!

After // look like this is a good habit Oh ~

Guess you like

Origin blog.csdn.net/qq_45472866/article/details/106697758