模拟初级计算器 单调栈实现

题意:求解一串不出现数学公式只含‘+‘,‘-‘,‘*‘,‘/‘, ‘(‘ , ‘)‘的计算表达式,输出结果;

其中‘/‘是带小数的除法。并且输入的数值位double型,若是输入的运算符有误,或者出现除0错误,则直接输出intput error.

输入时除数值之间不能出现空格外,其他地方均能有空格。并且3(...)看成为3*(); 0.5也可以输入为.5;

注意:代码中目前没有加入识别是减号还是符号的处理;所以只能处理非负整数之间的运算;

实现细节:以运算符的优先级来设置一个优先级(数学意义)递减的单调栈。但是给予‘(‘ ,‘)‘不一样的优先级;即栈中实际上只是存储的是‘+‘,‘-‘运算,‘*‘,‘/‘运算会计算出数值;没遇到一个‘)‘。表示计算与前一个‘(‘之间的所有值;最后加发‘)‘为了全部计算完。

ps:由于只是随便写的,要是发现bug直接指出即可;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<cmath>
#define esp 1e-7
using namespace std;
char s[3000],op[1000];
double v[1000];
map<char,int> mp;
bool solve()
{
    mp[‘*‘] = 1,mp[‘/‘] = 1,mp[‘+‘] = 2,mp[‘-‘] = 2,mp[‘(‘] = 3, mp[‘)‘] = 4;//维护一个单调递增的栈;
    int len = strlen(s),stk = 0,top = 0;
    s[len++] = ‘)‘;
    op[++stk] = ‘(‘;
    for(int i = 0;i < len;i++)if(s[i] != ‘ ‘){//容许输入有空格;
        if(s[i] != ‘.‘ && s[i] < ‘0‘ || s[i] > ‘9‘){//可能输入的小数位 .5 即0.5
            if(mp.find(s[i]) == mp.end()) return false;
            while(stk >= 1 && mp[op[stk]] < mp[s[i]] && s[i] != ‘(‘){
                if(stk == 1 && i != len - 1) return false;
                if(s[i] == ‘)‘ && op[stk] == ‘(‘){stk--; break;}
                if(op[stk] == ‘+‘) v[top-1] += v[top];
                else if(op[stk] == ‘-‘) v[top-1] -= v[top];
                else if(op[stk] == ‘*‘) v[top-1] *= v[top];
                else if(op[stk] == ‘/‘)
                    if(fabs(v[top]) < esp) return false;//除0;
                    else v[top-1] /= v[top];
                top--;stk--;
            }
            if(s[i] != ‘)‘)
                op[++stk] = s[i];
        }
        else{
            double val = 0.0,f = 1;
            if(s[i] == ‘.‘) f /= 10,i++;
            for(;s[i] >= ‘0‘ && s[i] <= ‘9‘;i++){//小数不能写成 .1这样的形式;
                if(f == 1){
                    val = val*10 + (s[i]-‘0‘);
                }
                else{
                    val += f*(s[i] - ‘0‘);
                    f /= 10;
                }
                if(s[i+1] == ‘.‘) f = 0.1,i++;
                if(f < 1 && s[i+1] == ‘.‘)    return false;//出现多个小数点
            }
            if(s[i--] == ‘(‘) op[++stk] = ‘*‘;// 3(2 - 4) = 3*(2 - 4)
            v[++top] = val;
        }
    }
    return stk?false:true;//最终符号栈中没有一个符号
}
int main()
{
    while(gets(s), strlen(s)){
        if(solve()) printf("%f\n",v[1]);
        else puts("input error");
    }
}
时间: 2024-12-28 20:02:41

模拟初级计算器 单调栈实现的相关文章

【11.2晚校内测试】【装桶模拟】【单调栈】

真的是fo了,晚上还来一次测试...... mister[问题描述] 不久前 Mister 从太空中探测到一个奇怪的信号,他开始研究这个信号. 经过一些变换后,这个信号变成了长度为 n 的排列或者它的循环移位.对于进一步的研究 Mister 需要一些数据分析,这就是为什么他决定选择这个排列的循环移位,它有最小的可 能偏差.我们把排列的偏差定义为 求一个可能偏差最小的排列 p 的循环移位. 让我们表示 k(0≤k < n)的循环移位排列 p 的变化需要达到这种转变,例如: k = 0: 变成 p1

【BZOJ】3016: [Usaco2012 Nov]Clumsy Cows 贪心 单调栈

Description Bessie the cow is trying to type a balanced string of parentheses into her new laptop, but she is sufficiently clumsy (due to her large hooves) that she keeps mis-typing characters. Please help her by computing the minimum number of chara

1821 最优集合(单调栈+模拟)

1821 最优集合 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 一个集合S的优美值定义为:最大的x,满足对于任意i∈[1,x],都存在一个S的子集S',使得S'中元素之和为i. 给定n个集合,对于每一次询问,指定一个集合S1和一个集合S2,以及一个数k,要求选择一个S2的子集S3(|S3|<=k),使得S1∪S3的优美值最大. (集合元素可以重复) Input 第一行一个数n,(n<=1000) 接下来n行,每行描述一个集合: 第一个数m,表示集合大小,

【单调栈维护连续区间】2019.1.18模拟赛T2 浇花

这道题是一道单调栈的题 1 题目描述 2 JDFZ在餐厅门前种了一排nn棵花,每棵花都有一个高度.浇花大爷会枚举所有的区间,然后从区间中找出一个高度最矮的花进行浇水.由于浇花大爷浇完水之后就精疲力竭了,所以请你帮助他计算每棵花都被浇了几次水. 3 4 输入格式 5 第一行一个整数nn. 第二行nn个整数,分别表示每棵花的高度. 6 7 输出格式 8 一行nn个整数用空格隔开,分别表示每棵花被浇了几次水. 9 10 样例一 11 input 12 3 13 1 3 5 14 output 15 3

csp-s模拟测试50(9.22)「施工(单调栈优化DP)」&#183;「蔬菜(二维莫队???)」&#183;「联盟(树上直径)」

改了两天,终于将T1,T3毒瘤题改完了... T1 施工(单调栈优化DP) 考场上只想到了n*hmaxn*hmaxn的DP,用线段树优化一下变成n*hmaxn*log但显然不是正解 正解是很**的单调栈 可以想象到最优情况一定是将两端高于中间的一段平原填成一段平的坑,不然如果坑内存在高度差那么我们即使只将一部分抬升也肯定没有用处,并且如果中间的坑已经高于了两端,再向上升也肯定不优,然后就中间的坑可以很很小,也可以很长,对于这个模型我们首先想到n^2*h的DP 设当前表示的f[i]表示当前到了i节

[CSP-S模拟测试]:array(单调栈)

题目描述 在放完棋子之后,$dirty$又开始了新的游戏. 现在他拥有一个长为$n$的数组$A$,他定义第$i$个位置的分值为$i−k+1$,其中$k$需要满足: 对于任意满足$k\leqslant j\leqslant i$的$j$,有$A[k]\leqslant A[j]\leqslant A[i]$.当对于第$i$个数,有多个$k$满足条件时,取能获得较大分值的$k$. 现在,$dirty$想要知道$A$数组中分值最大的位置对应的分值为多少. 输入格式 第一行一个整数$n$,表示$A$数组

【NOIP数据结构专项】单调队列单调栈

[洛谷P1901 ]发射站 http://www.luogu.org/problem/show?pid=1901 题目描述 某地有 N 个能量发射站排成一行,每个发射站 i 都有不相同的高度 Hi,并能向两边(当 然两端的只能向一边)同时发射能量值为 Vi 的能量,并且发出的能量只被两边最近的且比 它高的发射站接收. 显然,每个发射站发来的能量有可能被 0 或 1 或 2 个其他发射站所接受,特别是为了安 全,每个发射站接收到的能量总和是我们很关心的问题.由于数据很多,现只需要你帮忙计 算出接收

Educational Codeforces Round 23 D. Imbalanced Array(单调栈)

题目链接:Educational Codeforces Round 23 D. Imbalanced Array 题意: 给你n个数,定义一个区间的不平衡因子为该区间最大值-最小值. 然后问你这n个数所有的区间的不平衡因子和 题解: 对每一个数算贡献,a[i]的贡献为 当a[i]为最大值时的 a[i]*(i-l+1)*(r-i+1) - 当a[i]为最小值时的a[i]*(i-l+1)*(r-i+1). 计算a[i]的l和r时,用单调栈维护.具体看代码,模拟一下就知道了. 然后把所有的贡献加起来.

51nod 1102 面积最大的矩形(单调栈)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1102 题意: 思路: 做法就是求出每个长方形向左向右所能延伸的最大距离. 我这里用单调栈来做,维护一个单调递增的栈(自底向上递增),如果当前值大于栈顶,那么直接进栈,如果小于的话,那就说明前面比它大的那些数最多只能延伸到它这里.自己手动模拟一下就可以了. 1 #include<iostream> 2 #include<algorithm> 3 #inclu