PTA7-4 后缀式求值 (25分) (题目 + 代码 + 详细注释 + 坑点分析)
我们人类习惯于书写“中缀式”,如3 + 5 * 2,其值为13。 (p.s. 为什么人类习惯中缀式呢?是因为中缀式比后缀式好用么?)而计算机更加习惯“后缀式”(也叫“逆波兰式”,Reverse Polish Notation)。上述中缀式对应的后缀式是:3 5 2 * +现在,请对输入的后缀式进行求值。输入格式:在一行中输入一个后缀式,运算数和运算符之间用空格分隔,运算数长度不超过6位,运算符仅有
·
我们人类习惯于书写“中缀式”,如 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<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;
}
//常看我的博客都知道,我的博客讲解就像金针菇那么细,注释都很详细的。大神勿喷!
//先看后赞是好习惯哦~
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献3条内容
所有评论(0)