逆波兰式 HDU1237 简单计算器

题目链接:

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19367

题意:

给定一个计算式,计算式合法。每个运算符和数字之间差一个空格,输出其值。

思路:

逆波兰式模板题。

逆波兰式主要是这样一个操作。两个栈(最初和队列弄混。队列为先进先出),一个栈s1存储逆波兰式,一个栈s2作临时存储,存储操作数。读入数字时,直接存入s1.如果题目说明数字的长度会大于一,则在遇到遍历字符串遇到非数字字符后,向s1里压入一个” ”(空串)代表分割。

关键来了,操作的优先级p1,栈顶的优先级p2。若p1小于等于p2,则把p2的栈顶元素弹出并压入s1,知道p1大于p2,然后把p1压入s2。注意是“小于等于”。

输出计算的时候,遇到操作M,栈顶第一个操作数X1,第二个X2,则根据栈的结构特点,结果应为X2 (M)X1

扩展式的想一想,如果存在左括号(、右括号)等蛋疼的符号。遇到右括号则弹栈直到遇到左括号,同时改变里面的操作数。

源码:

#include <cstdio>

#include <cstring>

#include <string>

#include <cmath>

#include <queue>

#include <stack>

#include <algorithm>

#include <iostream>

using namespace std;

int const MAXN = 2000;

char s0[MAXN],porlan[MAXN];

int priority(char c)

{

    switch(c){

        case '#':return 0;

        case '+':return 1;

        case '-':return 2;

        case '*':return 3;

        case '/':return 4;

    }

}

void trans(char a[],char b[])

{

    int len = strlen(a);

    stack<char>ss;

    while(!ss.empty())

        ss.pop();

    int tot = 0;

    for(int i=0; i<len; i++){

        if(isdigit(a[i]) || a[i]==' ')

            b[tot++] = a[i];

        else{

            if(priority(a[i])<=2 ){

                    while(!ss.empty()){

                    b[tot++] = ss.top();

                    ss.pop();

                }

            }

            else{

                while(!ss.empty() && priority(ss.top())>2 ){

                    b[tot++] = ss.top();

                    ss.pop();

                }

            }

            ss.push(a[i]);

        }

    }

    while(!ss.empty()){

        if(ss.top() == '#')

            break;

        b[tot++] = ' ';

        b[tot++] = ss.top();

        ss.pop();

    }

    b[tot] = '\0';

}

double cal(char a[])

{

    stack<double>ss;

    while(!ss.empty())

        ss.pop();

    double temp = 0;

    int tot = 0;

    double t1,t2;

    for(int i=0; i<strlen(a); i++){

        if(a[i]>='0' && a[i]<='9'){

            temp = temp*10 + a[i] - '0';

        }

        else if(a[i] == ' '){

            if(isdigit(a[i-1]) || temp){

                ss.push(temp);

                temp = 0;

            }

        }

        else{

            t2 = ss.top();ss.pop();

            t1 = ss.top();ss.pop();

            switch(a[i]){

            case '+':

                t1 = t1 + t2;break;

            case '-':

                t1 = t1 - t2;break;

            case '*':

                t1 = t1 * t2;break;

            case '/':

                t1 = t1 / t2;break;

            }

//            printf("t1 = %.2f\n",t1);

            ss.push(t1);

        }

    }

    return ss.top();

}

int main()

{

    while(gets(s0)){

        if(!strcmp(s0,"0"))

            break;

        trans(s0,porlan);

        double ans = cal(porlan);

        printf("%.2f\n",ans);

    }

    return 0;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值