13.java栈实现计算器

更新了代码,能跑通了,昨天果然是太晚了脑子混了,今天一看其实就差一句,在最后while循环的时候忘记把拿到的oper从栈里pop出去了,导致oper栈一直不空就要一直从数据栈中取数据进行计算所以一直在越界。

老师提供的计算器的特点:计算数据要为一位数,先减后加会导致出错。我在修改了将判断oper的函数改为循环后,即一直对比直到栈空或优先级高于栈顶符号才入栈,而非老师的版本只判断一次。保证了其可以先做减法也没有问题。但多位数的bug还未 改,有思路但就要大改了。以后有机会再说吧qwq

——————————————————————————————————————————————————————————————————

今天是大困难的一天,学习了中缀表达式、后缀表达式、前缀表达式的定义以及计算方式,不得不说发明这种方法的人脑子真的太好使。

老师讲了两种计算器,一种是通过数组栈写中缀表达式的计算器,没写出来- -,小分支真的太多太多了,想改善老师的代码的bug最后改到头昏脑胀也没改出来,参考了视频弹幕中的方法,但还是不太可行,明天接着改吧(或者不改了。中缀表达式真的好复杂- -

说起来大二的数据结构课就是从中缀表达式这里开始彻底脱节的,这次倒是确实地明白了几种表达式的计算方式及定义了。

凑合看吧,明天起来继续调试看看能不能调通。

package linkedlist;

public class jisuanqi {
    public static void main(String[] args){
        String expression="3-2-2";
        ArrayStack1 numstack=new ArrayStack1(10);
        ArrayStack1 operstack=new ArrayStack1(10);
        int index=0;
        int num1=0;
        int num2=0;
        int oper=0;
        int res=0;
        char ch=' ';
        while (true){
            ch=expression.charAt(index);
            if(operstack.isoper(ch)){
                if(operstack.isEmpty()){
                    operstack.push(ch);
                }else {
                    while (true){
                        if (operstack.isEmpty()){
                            operstack.push(ch);
                            break;
                        }
                        if(operstack.priority(ch)<=operstack.priority(operstack.peek())){
                            num2=numstack.pop();
                            num1=numstack.pop();
                            oper=operstack.pop(); //就是这句话。。
                            res=numstack.cal(num1,num2,oper);
                            numstack.push(res);
                        }else {
                            operstack.push(ch);
                            break;
                        }
                    }
                }

            }else {
                numstack.push(ch-48);
            }
            index++;
            if (index>=expression.length()) break;
        }
        while(true){
            if (operstack.isEmpty()) break;
            num2=numstack.pop();
            num1=numstack.pop();
            oper=operstack.pop();
            res=numstack.cal(num1,num2,oper);
            numstack.push(res);
        }
        int res2=numstack.pop();
        System.out.println(res2);
    }

}
class ArrayStack1{
    public int top=-1;
    public int[] stack;
    public int maxSize;

    public ArrayStack1(int maxSize) {
        this.maxSize = maxSize;
        stack=new int[maxSize];
    }
    public int peek(){
        return stack[top];
    }
    public int priority(int oper){
        if(oper=='*'||oper=='/'){
            return 1;
        }else if (oper=='+'||oper=='-'){
            return 0;
        }else {
            return -1;
        }
    }
    public boolean isoper(int oper){
        return oper=='+'||oper=='-'||oper=='*'||oper=='/';
    }
    public int cal(int num1,int num2,int oper){
        int res=0;
        switch (oper){
            case '+':
                res=num1+num2;
                break;
            case '-':
                res=num1-num2;
                break;
            case '*':
                res=num1*num2;
                break;
            case '/':
                res=num1/num2;
                break;
        }
        return res;
    }
    public boolean isFull(){
        if(top==maxSize-1) return true;
        return false;
    }
    public boolean isEmpty(){
        if(top==-1) return true;
        return false;
    }
    public void push(int value){
        if(isFull()){
            System.out.println("栈满,无法加入");
            return;
        }
        top++;//先加栈顶再赋值
        stack[top]=value;
    }
    public int pop(){
        if(isEmpty()){
            throw new RuntimeException("栈空,没有数据");
        }
        int value=stack[top];
        top--;
        return value;
    }
    public void list(){
        if(isEmpty()){
            System.out.println("栈空,没有数据");
        }
        for(int i=top;i>=0;i--){
            System.out.printf("stack[%d]=%d",i,stack[i]);
        }
    }
}

 

第二种计算器明显人性化太多了,是后缀表达式的计算器,虽然人类很难看懂是真的,但算起来真的太方便了,很容易就可以复现;

package linkedlist;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class caculator {
    public static void main(String[] args){
        //String suffixExpression="30 4 + 5 * 6 -";
        String suffixExpression="4 5 * 8 - 60 + 8 2 / +";
        List<String> list=getListString(suffixExpression);
        int res=cal(list);
        System.out.print(res);
    }
    public static List<String> getListString(String s){
        String[] sp=s.split(" ");
        List<String> list=new ArrayList<String>();
        for (String c:sp){
            list.add(c);
        }
        return list;
    }
    public static int cal(List<String> list){
        Stack<String> stack=new Stack<String>();
        for (String item:list){
            if(item.matches("\\d+")){
                stack.push(item);
            }else {
                int num2=Integer.parseInt(stack.pop());
                int num1=Integer.parseInt(stack.pop());
                int res=0;
                if (item.equals("+")){
                    res=num1+num2;
                }else if (item.equals("-")){
                    res=num1-num2;
                }else if(item.equals("/")){
                    res=num1/num2;
                }else if (item.equals("*")){
                    res=num1*num2;
                }else {
                    throw new RuntimeException("运算符有误");
                }
                stack.push(""+res);
            }
        }
        return Integer.parseInt(stack.pop());
    }
}

 

posted @ 2022-03-28 01:28  水煮小白菜  阅读(82)  评论(0编辑  收藏  举报