用数组模拟栈实现综合计算器

栈实现综合计算器

使用栈完成表达式的计算思路
建立两个栈,一个数字栈(numStack)一个符号栈(operStack)
1.通过一个index值(索引),来遍历我们的表达式
2.如果我们扫描到的是一个数字,就直接入栈
3如果我们扫描到的是一个符号,就分如下情况
3.1如果发现当前的符号栈为空,就直接入栈
3.2如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符,就需要从数栈中pop出两个数字,在从符号栈中pop出一个符号,进行运算,将得到的结果入数栈,然后将当前的操作符入符号栈。如果当前的操作符的优先级大于栈中的操作符,就直接入符号栈。
4.当表达式扫描完毕,就顺序的从数栈和符号栈中pop出相应的数和符号。
5.最后数栈只有一个数字,就是表达式的结果。
在这里插入图片描述我也根据这个思路,画了个简单的图,如上图
对于以上思路
我们需要在数组模拟栈的基本方法上添加一些别的判断方法
1.priority() *和/的优先级是高于+和-的
2.isOper() 判断是否是运算符,需要将数和运算符存放在两个栈中
3.计算的方式 cal() 对于过程中和结尾 数字栈弹出的两个数和符号栈弹出的符号要进行计算,*和+没有区分,栈先进后出的特性,注意-和/计算时,数字的先后顺序。

重点问题

我认为的
1.在进行四则运算的时候,肯定不可能是都是10以内的运算,我们在将数字入栈的时候是不能直接入栈的,需要判断它的下一位是否是运算符,如果是运算符的话直接入栈,不是的话接着扫描直到符合上述条件。
2.就如我上图所画图的例子 ,但同样的你去分析9+2*3+4,还是有所不同的,在进行数字栈的二次弹栈,和字符栈的弹栈后,不能将优先级小于栈顶的那个运算符直接入栈,是还要进行判断的。

废话不多说代码如下:

package com.zrx.markdown;

import java.util.Scanner;

public class Calculator {
    public static void main(String[] args) {
        // 完成表达式的运算
//        String exp = "70+20*6-4";
//        String exp= "9-2*3+4";
        System.out.println("请输入表达式");
        Scanner scanner = new Scanner(System.in);
        String exp="";
        exp=scanner.next();

        // 创建两个栈,一个数栈一个符号栈
        ArrayStack numStack = new ArrayStack(10);
        ArrayStack operStack = new ArrayStack(10);
        // 定义需要的相关变量
        int index = 0; // 用于扫描
        int num1 = 0;
        int num2 = 0;
        int oper = 0;
        int res = 0;
        char ch = ' '; // 将每次扫描得到的char保存到ch
        String keepNum = ""; // 用于拼接多位数
        // 开始while循环的扫描exp
        while(true) {
            // 依次得到exp的每一个字符
            ch = exp.charAt(index);
            // 判断ch是什么,然后做相应的处理
            if(operStack.isOper(ch)) { // 如果是运算符
                if(!operStack.isEmpty()) {
                    if(operStack.priority(ch) <= operStack.priority(operStack.retTop())) {
//                        num1 = numStack.pop();
//                        num2 = numStack.pop();
//                        oper = operStack.pop();
//                        res = numStack.cal(num1, num2, oper);
//                        // 把运算的结果入数栈
//                        numStack.push(res);
//                        // 把当前的操作符入符号栈
//                        operStack.push(ch);
                        while(true){
                            num1 = numStack.pop();
                            num2 = numStack.pop();
                            oper = operStack.pop();
                            res = numStack.cal(num1, num2, oper);
                            // 把运算的结果入数栈
                            numStack.push(res);
                            if(operStack.isEmpty()){
                                break;
                            }
                            if(operStack.priority(ch)> operStack.priority(operStack.retTop())){
                                break;
                            }

                        }
                        // 把当前的操作符入符号栈
                        operStack.push(ch);
                    } else {
                        // 如果当前的操作符的优先级大于栈中的操作符,直接入符号栈
                        operStack.push(ch);
                    }
                } else {
                    // 如果为空直接入符号栈
                    operStack.push(ch);
                }
            } else { // 如果是数字,则直接入数栈
                keepNum += ch;
                if (index == exp.length() - 1) {
                    numStack.push(Integer.parseInt(keepNum));
                } else {
                    if (operStack.isOper(exp.charAt(index+1))) {
                        numStack.push(Integer.parseInt(keepNum));
                        keepNum = "";
                    }
                }
            }
            // index + 1,并判断是否扫描到最后
            index++;
            if (index >= exp.length()) {
                break;
            }
        }

        // 当表达式扫描完毕时,就顺序的从数栈和符号栈中pop出相应的数和符号并运行
        while(true) {
            // 如果符号栈为空,则计算到最后的结果,数栈中只有一个数字
            if (operStack.isEmpty()) {
                break;
            } else {
                num1 = numStack.pop();
                num2 = numStack.pop();
                oper = operStack.pop();
                res = numStack.cal(num1, num2, oper);
                numStack.push(res); // 入栈
            }
        }
        // 将数栈的最后一个数字pop出就是结果
        int result1 = numStack.pop();
        System.out.println("result:"+result1);
    }
}
class ArrayStack{
    private int maxSize;
    private int[] stack;
    private int top=-1;

    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        stack=new int[this.maxSize];//初始化数组
    }
    //判断栈满
    public boolean isFull(){
        return top==maxSize-1;
    }
    //判断栈空
    public boolean isEmpty(){
        return top==-1;
    }
    //入栈操作
    public  void push(int value){
        //先对栈进行状态判断
        if(isFull()){
            return;
        }
        //在进行添加
        top++;
        stack[top]=value;
    }
    /**
     * 出栈
     * 其实就是将栈顶的数据返回
     */
    public int pop(){
        if (isEmpty()) {
            //抛出异常
            throw new RuntimeException("stack is empty");
        }
        int value=stack[top];
        top--;
        return value;

    }
    //返回当前栈顶的值
    public int retTop(){
        return  stack[top];
    }
    //遍历栈,要从栈顶开始遍历
    public void list(){
        if (isEmpty()) {
            throw new RuntimeException("stack is empty");
        }
        for(int i=top;i>=0;i--){
            System.out.println(stack[i]);
        }
    }
    //返回预算符的优先级,直接用数字表示,数字越大优先级越高;
    public int priority(int oper){
           if(oper=='*' || oper=='/'){
               return 1;
           }
           if(oper=='+' || oper=='-'){
               return 0;
           }else{
               return -1;
           }
    }
    //判断是否是一个运算符
    public boolean isOper(char val){
        return val=='+' || val=='-' || val=='/' ||val=='*';
    }
    //计算方法
    public int  cal(int num1,int num2,int val){
        int res=0;//存放计算的结果;
        switch (val){
            case '+':
                res=num1+num2;
                break;
            case '-':
                res=num2-num1;
                break;
            case '*':
                res=num1*num2;
                break;
            case '/':
                res=num2/num1;
                break;
            default:
                break;
                
        }
        return res;

    }
}

是谁写代码不加注释,嗷,是我那没事儿了
哈哈哈哈嗝 溜了 溜了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Quare_feifei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值