OCAC暑期比赛第二场 L题 简单计算器 题解

简单计算器
【题目描述】
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
【输入格式】
输入包含一行字符串,不超过1000个字符,整数和运算符之间用一个空格分隔。没有非法表达式。
【输出格式】
输出该字符串对应的表达式的值,精确到小数点后2位。
【样例 1 输入】
1 + 2
【样例 1 输出】
3.00
【样例 2 输入】
4 + 2 * 5 - 7 / 11
【样例 2 输出】
13.36
【样例解释】
1 + 2 = 3
4 + 2 * 5 - 7 / 11 ≈ 13.36
【题目分析】
我们可以利用栈来解决这道问题。
首先,对于我们来说,这道题目比较简单,没有用到小括号。
对于遇到小括号的情况,我们可能会用递归来实现“有小括号先求小括号里面的”的效果。
但是因为这里没有,所以我们只需要处理“加减乘除”就可以了,
可以发现,“加减”是一类的;“乘除”是一类的。
所以我们可以这么做:
我们开两个栈:stack1和stack2,stack1用于存放数字,stack2用于存放符号(+或-),
首先,我们把公式中的第一个数字放入stack1中,
接下来我们每次处理一个符号c和一个数字a,
如果c是乘号或者除号,那么我们只需要取出stack1中的栈顶元素b,然后将 a*b 或者 a/b 的结果在放入stack中即可。
如果c是加号或者减号,那么我们要判断一下此时stack1中的元素个数,
如果stack1中只有一个元素,那么我们将a放入stack1中,将c放入stack2中,因为对于a来说,他的下一步运算很有可能是乘除运算,
所以还是需要将此时的a留在栈顶以北接下来的运算的。
如果stack1中有两个元素,而此时的符号是加号或者减号,那就是说,我新加进来的以a开头的部分,最终是要和他前面的这两个stack1中的元素做加减运算的。
那么我们就可以先将stack1中的两个元素先合并了,那么我们假设:
先从stack1中出来的是num1(这个num1是表达式中靠后的元素,因为栈是“后进先出”),
后从stack1中出来的是num2(这个num2是表达式中靠前的元素),
而stack2中取出的元素是c的话,
如果c是+,则我们将num2+num1重新放入stack1中;
如果c是-,则我们将num2-num1重新放入stack1中。
我们按照这样的方式一直进行到遍历完整个表达式。
此时stack1中可能存在一个元素,也可能还存在两个元素,
那么在存在两个元素的情况下,我们可以知道,这两个元素肯定是加减运算的,因为我们不将乘除号放入stack2中,只将加减号放入stack2中。所以我们只需要进行一下上述的过程就可以将stack1中的元素变成一个了。
那么最终的结果就是stack1中剩余的这唯一一个元素。
注意:这道题目有一个要注意的地方就是他是以0为单独一行结尾就算输入结束了。
实现代码如下:

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

stack<double> stk1, stk2;
// stk1用于存放数字,stk2用于存放符号,
// 因为stk2里面的符号只可能是+或-,所以用1表示+,用-1表示-

double a;
char c;
string line, s;

int main() {

    while (!stk1.empty()) stk1.pop();
    while (!stk2.empty()) stk2.pop();
    getline(cin, line);
    stringstream ss(line);
    ss >> a;
    stk1.push(a);
    while (ss >> s >> a) {
        c = s[0];
        double b;
        switch (c) {
            case '*':
                b = stk1.top();
                stk1.pop();
                stk1.push(b * a);
                break;
            case '/':
                b = stk1.top();
                stk1.pop();
                stk1.push(b / a);
                break;
            default:
                if (stk1.size() == 2) { // 其实是==2就行
                    double num1 = stk1.top();
                    stk1.pop();
                    double num2 = stk1.top();
                    stk1.pop();
                    double flag = stk2.top();
                    stk2.pop();
                    stk1.push(num2 + flag * num1);
                }
                stk1.push(a);
                stk2.push( c == '+' ? 1 : -1 );
                break;
        }
    }
    if (stk1.size() == 2) {
        double num1 = stk1.top();
        stk1.pop();
        double num2 = stk1.top();
        stk1.pop();
        double flag = stk2.top();
        stk2.pop();
        stk1.push( num2 + flag * num1 );
    }
    double res = stk1.top();
    printf("%.2lf\n", res);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ocac/p/11131682.html
今日推荐