【JAVA】数组模拟栈实现综合计算器

使用数组模拟栈完成表达式计算思路:

  • 1)通过index值(索引),来遍历我们的表达式
  • 2)如果我们发现是一个数字,就存入数字栈
  • 3)如果发现扫描到一个符号,就分如下情况
  • (3.1)如果发现符号栈为空,就直接入栈
  • (3.2)如果符号栈有操作符,就进行比较,如果当前操作符的优先级小于或者等于栈中的操作符,就需要先操作字符栈中的pop一个符号,然后数字栈pop两个数字,进行运算。将得到的结果,入数字栈,然后将比较时候小的操作符入符号栈。如果当前操作符的优先级大于栈中的操作符,就直接入符号栈。
  • 4)当表达式扫描完毕,就顺序的从数字栈和符号栈中分别pop出相应的数和符号并且运行。
  • 5)最后数字栈剩下的一个数字就是表达式的结果

修复计算bug:

  1. 无法计算多位数 个人解决方法
    1)添加一个count=0的计数器,遍历表达式,如果if判断句判断为数字则count++,如果判断为字符那么count–;
    2)然后特殊情况是表达式是以负数开头的(例如‘-11-2*2’),这个先看数字栈是否为空,若为空那么就说明这个符号的作用是开头标正负用的。那么判断完就给一个count++,这样count就不会变成负数
  2. 无法连减的解决方法
    一开始我想着栈中存放的数都为正数,但是一从栈中拿出来两个数和符号进行计算就会出bug。 例如表达式
    ‘3-2-1’ ,最后结果是2,显然出错了,本来结果是0啊?!
    这个错误过程是这样的:
    遍历完表达式数字栈有 {3、2、1},字符栈有{‘-’、‘-’}
    ①首先开始计算时候数字栈取出2、1,字符栈取出 ‘-’
    ② 然后计算2-1=1又存入了栈中
    ③此时数字栈中{3、1},字符栈中{‘-’}
    ④然后数字栈又取出3、1,字符栈取出 ‘-’ 计算得到3-1=2
    栈都是先存后取的,如果连减就会出问题。
    个人解决方法:
    创建int isNegative=0;其作用是判断一个数字为正负,0为非负数,1为负数。
    每次遇到负号就将其变为正号存入字符栈,并且让isNegative+1。如果表达式遍历到数字之后那么根据isNegative是否为1,就知道存入前是否乘(-1)
    这样数字栈里就有正负了,最后让isNegative=0等待下一次循环。

import org.junit.Test;
public class Calculator {
    @Test
    public void test1() {
        String ex = "-12+20*3-2*2-1";
        NumStack num = new NumStack(100);//创建数字栈,大小为100
        CharStack cc = new CharStack(50);//创建字符栈,大小为50
        char[] arr = ex.toCharArray();//将表达式转换成字符串一个一个处理
        int index = 0;//索引,用来扫描
        int num1 = 0;//接收数字栈的出栈值
        int num2 = 0;//接收数字栈的出栈值
        char oper;//接收字符栈的出栈值
        int res = 0;//接收结果
        int isNegative=0;//判断一个数字为正负,0为非负数,1为负数
        int count=0;//计数器,1代表一位,0代表零位,以此类推
        while (true) {
            if (index == arr.length) {
                System.out.println("表达式遍历完毕!");
                break;
            }
            char ch = arr[index++];
            if (cc.isOper(ch)) {//如果是字符//
                count--;
                if (!cc.isEmpty()) {//如果字符栈不为空
                    if (cc.priority(ch) < cc.priority(cc.peek())) {//如果要添加到栈的字符优先度小于栈中要出的字符
                        num1 = num.pop();
                        num2 = num.pop();
                        oper = cc.pop();
                        res = cc.cal(num1, num2, oper);
                        num.push(res);
                        if(ch=='-'){
                            isNegative++;
                            ch='+';
                        }
                        cc.push(ch);
                    } else {
                        if(ch=='-'){
                            isNegative++;
                            ch='+';
                        }
                        cc.push(ch);
                    }
                } else {//如果字符栈为空
                    if(num.isEmpty()&&ch=='-'){//如果数字栈也为空,说明是开头加的字符表示正负
                        isNegative++;
                        count++;//这里不++,例如‘-12-2*2’就会出错count先来这个if判断count就等于-1了
                    }else if (ch=='-'){//如果字符栈为空并且遍历的字符为负数
                        ch='+';
                        isNegative++;
                        cc.push(ch);
                    }else{//如果字符栈为空并且遍历的字符不是负数
                        cc.push(ch);
                    }

                }
            } else {//如果是数字//
                count++;
                if(count>=2){//如果大于两位
                    String n = String.valueOf(ch);
                    Integer i = new Integer(n);
                    int a=num.pop();
                    if(a>=0){//大于两位数,并且数字栈前一个数大于零
                        a=(a*10)+i;
                        num.push(a);
                        count--;
                    }else{//大于两位数,并且数字栈前一个数小于零
                        a=(a*10)-i;
                        num.push(a);
                        count--;
                    }

                }else{//如果是一位数
                    //char-->String-->Integer-->int
                    String n = String.valueOf(ch);
                    Integer i = new Integer(n);
                    if(isNegative==1){//如果这个一位数字前面一位是负号
//                        System.out.println("如果是数字,并且前面是负号,此时存到数字栈的数为:"+(-i));
                        num.push(-i);
                        isNegative--;
                    }else{//如果这个一位数字前面一位是除了负号的符号
//                        System.out.println("如果是数字,此时存到数字栈的数为:"+i);
                        num.push(i);
                    }

                }

            }
        }
//        num.showStack();
//        cc.showStack();
        while (true) {//处理栈中剩下的数
            if (cc.isEmpty()) {//如果字符栈为空说明栈处理完毕
                break;
            }
            num1 = num.pop();
            num2 = num.pop();
            oper = cc.pop();
            res = cc.cal(num1, num2, oper);
            num.push(res);
        }
        System.out.println("表达式'" + ex + "'的最终结果是:" + num.peek() + ",res=" + res);
    }
}

class NumStack {//模拟数字栈
    private int maxSize;
    private int[] Stack;
    private int top = -1;

    public NumStack(int maxSize) {
        this.maxSize = maxSize;
        Stack = new int[maxSize];
    }

    public boolean isFull() {
        return top == maxSize - 1;
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public void push(int num) {
        if (isFull()) {
            System.out.println("数字栈满!存入失败");
            return;
        }
        top++;
        Stack[top] = num;
    }

    public int pop() {
        if (isEmpty()) {
//            throw new RuntimeException("数字栈空!!!");
            return -1;
        }
        int val = Stack[top];
        top--;
        return val;
    }

    //返回当前栈顶的值,但没有从栈中取出
    public int peek() {
        return Stack[top];
    }
    public void showStack(){
        for(int i=top;i>=0;i--){
            System.out.println("Stack["+i+"]"+Stack[i]);
        }
    }

}

class CharStack {//模拟字符栈
    private int maxSize;
    private char[] Stack;
    private int top = -1;

    public CharStack(int maxSize) {
        this.maxSize = maxSize;
        Stack = new char[maxSize];
    }

    public boolean isFull() {
        return top == maxSize - 1;
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public void push(char num) {
        if (isFull()) {
            System.out.println("字符栈栈满!!!");
            return;
        }
        top++;
        Stack[top] = num;
    }

    public char pop() {
        if (isEmpty()) {
            throw new RuntimeException("字符栈栈空!!!");
        }
        char val = Stack[top];
        top--;
        return val;
    }

    //返回运算符的优先级
    // 优先级用数字表示,数字越大优先级越高
    public int priority(char oper) {
        String oper2 = String.valueOf(oper);
        if (oper2.equals("*") || oper2.equals("/")) {
            return 1;
        } else if (oper2.equals("+") || oper2.equals("-")) {
            return 0;
        } else {
            System.out.println("无法识别优先度!");
            return -1;//目前只能识别+、-、*、/
        }
    }

    //判断是不是一个运算符
    public boolean isOper(char a) {
        String oper = String.valueOf(a);
        return oper.equals("+") || oper.equals("-") || oper.equals("*") || oper.equals("/");
    }

    //计算方法
    public int cal(int num1, int num2, char oper) {
        int sum = 0;
        switch (oper) {
            case '+':
                sum = num1 + num2;
                break;
            case '-':
                sum = num2 - num1;//注意顺序
                break;
            case '*':
                sum = num1 * num2;
                break;
            case '/':
                sum = num2 / num1;
        }
        return sum;
    }

    //返回当前栈顶的值,但没有从栈中取出
    public char peek() {
        return Stack[top];
    }
    public void showStack(){
        for(int i=top;i>=0;i--){
            System.out.println("Stack["+i+"]"+Stack[i]);
        }
    }
}

待完成:
目前无法计算加括号的表达式
2022.1.26改进:
【JAVA】逆波兰综合计算器

初学数据结构,如果有更好的修改意见请在评论区留言

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值