算法训练 表达式计算

逻辑最重要

  */要优先于+-  所以要想好如何才能实现先*/后加减

如何协调运算符运算次序

首先我定义一个优先级递增串 ( +- */ )
右括号优先级最高左括号优先级最低 
栈顶的运算符为A新产生的运算符为B,如果B的优先级高则直接放在上面 
如果B的优先级低那么就要先运算栈顶运算符,然后将B放入栈顶,这样使得栈中的运算符优先级正确 
进而直到所有运算符进栈,这个栈都是符合运算逻辑的  
最后把剩下的统一出栈,取出数值栈中的数字(肯定只剩一个) 即为答案 
这里我使用的方法是用一个栈来存储运算符,一个栈来放操作数

代码

这个代码反复设计了多次,最后感觉没什么可改的了,。。。
#include<cstdio>
#include<stack>
#include<cctype>
using std::stack;
#include<cstring>
stack<int> numsk;
stack<char> opsk;
char s[120];
int readNum(int &pos)//从字符串中读取一个数字
{
    int num=0;
    for(;isdigit(s[pos]);pos++)
    {
        num = num*10+int(s[pos]-'0');
    }
    return num;
}
int checkPriority(char op)//查询某个运算符的优先级数
{
    if(op=='(')
        return 0;
    else if(op=='+'||op=='-')
        return 1;
    else if(op=='*'||op=='/')
        return 2;
    else
        return 3;
}
bool iscalc(char op)//判断新来的运算符和栈顶的运算符是否符合运算逻辑
{
    if(opsk.empty())
        return false;
    char opk = opsk.top();
    if(checkPriority(opk)>=checkPriority(op))
        return true;
    else 
        return false;
}
void calc()//取出一个运算符,两个运算数,进行运算,运算结果入栈
{
    char op;
    int n1,n2;
    op = opsk.top();
    opsk.pop();
    n1 = numsk.top();
    numsk.pop();
    n2 = numsk.top();
    numsk.pop();
    switch(op)
    {
        case '+':
            numsk.push(n2+n1) ;
            return;
        case '-':
            numsk.push(n2-n1);
            return;
        case '*':
            numsk.push(n2*n1);
            return;
        case '/': 
            numsk.push(n2/n1);
            return;
    }
}
int main()
{

    scanf("%s",s);
    //这里我把( 和 )单独拿出来判断
    //(直接入栈 )直接运算到(为止
    for(int i=0;i<strlen(s);i++)
    {
        if(isdigit(s[i]))
        {
            numsk.push(readNum(i));
            i--;
        }
        else
        {
            char op = s[i];
            if(op=='(')
            {
                opsk.push(op);
                continue;
            } 
            if(op==')')
            {
                char op1;
                while(1)
                {
                    op1 = opsk.top();
                    if(op1=='(')
                    {
                        opsk.pop();
                        break;
                    }
                    calc();

                }
            }
            else
            {
                if(iscalc(op))
                {
                    calc();
                }
                opsk.push(op);
            }
        }
    }
    //最后将剩下的没有运算的进行运算
    char op1;
    while(!opsk.empty())
    {
        calc();
    }
    printf("%d\n",numsk.top());
    return 0;
}

AC时间2017.11.11

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值