字符串计算器的设计

最近遇到一个问题,设计一个简易计算器,输入一个字符串,有加减乘除括号运算,求计算结果。比如输入一个很长的字符串

3+(((5+9*(4+3)+5)*6+(4*5*4))),我们在计算的时候先括号,再乘除,最后加减。计算机会从左到右依次扫描字符串,遇到低优先级的先不计算,直到遇到更低优先级的,比如先前有个4*6没有计算,再次扫描下一个字符串遇到了+号,我们就不必继续保存不计算了而是先把4*6计算完,得到24+再继续扫描,

设计思想,利用两个栈一个是符号栈,一个是数字栈,遇到低优先级的就弹栈计算再入栈,当然还要分情况,比如栈顶是左括号,再来一个加号也不能弹栈计算,如果符号栈顶是*,再来一个+那就可以弹栈计算了,自己动手划两个栈就明白了,我就不划了,源代码如下。代码没有做差错处理,默认输出正确的表达式,差错处理请读者自行在相应位置加入代码。另外只能计算整数算式,没考虑小数

注意如果代码注释没理解自行画两个栈,一个符号栈,一个操作数栈,然后观察下进出栈情况就很清楚了。我之前划过,但是不知道放哪了,懒得再画了。

#include<iostream>
#include<stdio.h>
#include<stack>
using namespace std;
using std::stack;
int priority(char c);
bool have_higher_priority(char a, char b);
int cal(int left, char op, int right);

int main()
{
    char expr[100]="3+(((5+9*(4+3)+5)*6+(4*5*4)))";//存放输入的字符串
    stack<int> operand_stack;//操作数栈
    stack<char>operator_stack;//运算符号栈
    int i;
    int j;
    int num, left_operand, right_operand;
    char op='\0';//上一个运算符
    num =0;
    //cin >> expr;
    for (i = 0; expr[i] != '\0'; i++)
    {
        if (expr[i] == '+' || expr[i] == '-' || expr[i] == '*' || expr[i] == '/' || expr[i] == '(' || expr[i] == ')')//如果是符号
        {
            if (expr[i] == '(')//如果接下来的符号是左括号,直接入栈
            {
                operator_stack.push(expr[i]);
            }
            else if (expr[i] == ')')//如果接下来的符号是右括号,一直弹栈操作,直到碰到左括号
            {
                while (operator_stack.top() != '(')
                {
                    right_operand = operand_stack.top();
                    operand_stack.pop();
                    left_operand = operand_stack.top();
                    operand_stack.pop();
                    op=operator_stack.top();
                    operator_stack.pop();
                    operand_stack.push(cal(left_operand, op, right_operand));

                }
                operator_stack.pop();
            }
            else//如果是其他操作符,判断优先级
            {
                if (operator_stack.empty())//符号栈为空直接进栈
                {
                    operator_stack.push(expr[i]);
                }
                else//操作符栈不为空
                {
                    while (!operator_stack.empty()&&have_higher_priority(operator_stack.top(), expr[i])&&operator_stack.top()!='(')//栈顶元素优先级比当前运算符优先级高,且栈顶符号不是左括号
                    {                                                                                     //弹栈计算
                        right_operand = operand_stack.top();
                        operand_stack.pop();
                        left_operand = operand_stack.top();
                        operand_stack.pop();
                        op = operator_stack.top();
                        operator_stack.pop();
                        operand_stack.push(cal(left_operand, op, right_operand));
                    }
                    operator_stack.push(expr[i]);
                }

            }
            
        }
        if ((expr[i] - '0') >= 0 && (expr[i] - '0') <= 9)//如果是数字
        {
            while((expr[i] - '0') >= 0 && (expr[i] - '0') <= 9)
            {
                num=10*num+(expr[i] - '0');
                i++;
            }
            operand_stack.push(num);
            i--;
            num=0;
        }

    }
    while (!operator_stack.empty())
    {
        right_operand = operand_stack.top();
        operand_stack.pop();
        left_operand = operand_stack.top();
        operand_stack.pop();
        op = operator_stack.top();
        operator_stack.pop();
        operand_stack.push(cal(left_operand, op, right_operand));
    }
    printf("%d", operand_stack.top());
    getchar();
    getchar();

}

int priority(char c)
{
    switch (c)
    {
    case'+':
    case'-':
        return 1;
    case'*':
    case'/':
        return 2;
    case'(':
    case')':
        return 3;
    }
}
bool have_higher_priority(char a, char b)
{
    if (priority(a) >= priority(b))
    {
        return true;
    }
    else
    {
        return false;
    }
}
int cal(int left, char op, int right)
{
    switch (op)
    {
    case '+':
        return left + right;
    case '-':
        return left - right;
    case '*':
        return left * right;
    case '/':
        return left / right;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值