NYOJ35 表达式求值(双栈法)

描述

ACM队的mdd想做一个计算器,但是,他要做的不仅仅是一计算一个A+B的计算器,他想实现随便输入一个表达式都能求出它的值的计算器,现在请你帮助他来实现这个计算器吧。
比如输入:“1+2/4=”,程序就输出1.50(结果保留两位小数)

输入

第一行输入一个整数n,共有n组测试数据(n<10)。
每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。
数据保证除数不会为0

输出

每组都输出该组运算式的运算结果,输出结果保留两位小数。

样例输入

2
1.000+2/4=
((1+2)*5+1)/4=

样例输出

1.50
4.00

思路

双栈法是一种比较简单的表达式求值方法:

首先需要两个栈,一个来存储数字,另一个来存储符号
具体做法是:

  1. 先把左括号压入符号栈,从左到右扫描字符串
  2. 如果碰见的是数字1~9或者.就利用一个字符串存起来
  3. 当遇见的不是数字时代表当前遇到了符号,把存储的字符串变成数字,然后压入数字栈中。然后判断当前遇到了什么符号,如果是加减,那么就直接从符号栈中取出两个数字进行计算,然后把结果压入栈中,如果遇到乘除符号,那么就直接先计算栈中的所有的乘除法,再把当前的符号压入栈中
  4. 如果遇见右括号,或者等号,就直接计算栈中剩余的符号。
  5. 最后输出数字栈中的栈顶就是答案

代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#include <list>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define inf 0x3f3f3f3f
typedef long long ll;
const int N = 1000 + 20;
stack<char> st_ch;
stack<double> st_num;
void calc1()
{
    char ch = st_ch.top();
    while (ch != '(')
    {
        double num1 = st_num.top();
        st_num.pop();
        double num2 = st_num.top();
        st_num.pop();
        switch (ch)
        {
        case '+':
            num2 += num1;
            break;
        case '-':
            num2 -= num1;
            break;
        case '*':
            num2 *= num1;
            break;
        case '/':
            num2 /= num1;
            break;
        }
        st_num.push(num2);
        st_ch.pop();
        ch = st_ch.top();
    }
}
void calc2()
{
    char ch = st_ch.top();
    while (ch == '*' || ch == '/')
    {
        double num1 = st_num.top();
        st_num.pop();
        double num2 = st_num.top();
        st_num.pop();
        switch (ch)
        {
        case '*':
            num2 *= num1;
            break;
        case '/':
            num2 /= num1;
            break;
        }
        st_num.push(num2);
        st_ch.pop();
        ch = st_ch.top();
    }
}
int main()
{
    //freopen("in.txt", "r", stdin);
    string str;
    int t;
    cin >> t;
    while (t--)
    {
        cin >> str;
        int len = str.size();
        st_ch.push('(');
        string str_num = "";
        for (int i = 0; i < len; i++)
        {
            if (isdigit(str[i]) || str[i] == '.')
            {
                str_num += str[i];
                continue;
            }
            if (str_num != "")
            {
                double num = atof(str_num.c_str());
                st_num.push(num);
                str_num = "";
            }
            switch (str[i])
            {
            case '+':
            case '-':
                calc1();
                st_ch.push(str[i]);
                break;
            case '*':
            case '/':
                calc2();
                st_ch.push(str[i]);
                break;
            case '(':
                st_ch.push('(');
                break;
            case ')':
            case '=':
                calc1();
                st_ch.pop();
                break;
            }
        }
        printf("%.2lf\n", st_num.top());
        st_num.pop();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/riba2534/article/details/80227638