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

Posted hxer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟初级计算器 单调栈实现相关的知识,希望对你有一定的参考价值。

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

其中‘/‘是带小数的除法。并且输入的数值位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");
    }
}

 

以上是关于模拟初级计算器 单调栈实现的主要内容,如果未能解决你的问题,请参考以下文章

用数组模拟栈 队列 以及单调栈 单调队列应用

用数组模拟栈 队列 以及单调栈 单调队列应用

golang 代码实现单调栈

2/9 康托展开+单调队列+单调栈(模拟栈)

单调队列与单调栈作用

[BZOJ1595] [Usaco2008 Jan]人工湖(单调栈)