JAVA 用栈实现计算器 (中缀表达式)

思路分析:

扩展:实现多位数计算 

        // 扫描的是数字,直接入栈  !!! 当处理的是多位数时,我们不能一看到是数字,就直接入栈。可能是个多位数
                 // 思路分析: 我们需要判断当前数字的下一位是不是符号,如果是直接入栈,不是的话进行数字拼接
                keepNum += ch;
                if(index == expression.length() - 1){ //
                    numStack.push(Integer.parseInt(keepNum));
                }else{
                    if(operStack.isOper(expression.substring(index + 1, index + 2).charAt(0))){
                        numStack.push(Integer.parseInt(keepNum));
                        // 清空 keepNum
                        keepNum = "";
                    }
                }

整体代码:

/*
 *    项目名称:ANA
 *    文件名称:Calculator.java
 *    Date:2023/9/26 上午10:45
 *    Author:yan_Bingo
 */

package Learning;

/**
 * @author Yan_Bingo
 * @version 1.0
 * Create by 2023/9/26 10:45
 */

public class Calculator {
    public static void main(String[] args) {
        // 数字栈
        ArrayStack2 numStack = new ArrayStack2(100);
        // 符号栈
        ArrayStack2 operStack = new ArrayStack2(100);

        String expression = "3^2+30*3/3-3%3";
        int num1 = 0; // 数字1
        int num2 = 0; // 数字2
        int result = 0; // 运算的的结果
        int index = 0; // 表达式的索引
        int oper = 0; // 符号
        char ch = ' '; // 每次扫描到的字符
        String keepNum = ""; // 用于拼接多位数

        while(true){
            if(index >= expression.length()){
                break;
            }
            ch = expression.substring(index, index + 1).charAt(0);

            // 如果扫描的字符是符号
            if(operStack.isOper(ch)){
                if(operStack.isEmpty()){ // 如果符号栈为空,直接入栈
                    operStack.push(ch);
                }else {

                    // 如果扫描的字符优先级小于或等于符号栈栈顶的优先级,就从数字栈 pop 两个数,再从符号栈 pop 出一个符号,进行运算
                    if (operStack.priority(ch) <= operStack.priority(operStack.queryTop())) {
                        num1 = numStack.pop();
                        num2 = numStack.pop();
                        oper = operStack.pop();
                        result = operStack.cal(num1, num2, oper);
                        numStack.push(result);
                        operStack.push(ch);
                    } else { // 如果扫描的字符优先级大于符号栈栈顶的优先级,就直接入符号栈
                        operStack.push(ch);
                    }
                }
            }else{ // 扫描的是数字,直接入栈  !!! 当处理的是多位数时,我们不能一看到是数字,就直接入栈。可能是个多位数
                 // 思路分析: 我们需要判断当前数字的下一位是不是符号,如果是直接入栈,不是的话进行数字拼接
                keepNum += ch;
                if(index == expression.length() - 1){ //
                    numStack.push(Integer.parseInt(keepNum));
                }else{
                    if(operStack.isOper(expression.substring(index + 1, index + 2).charAt(0))){
                        numStack.push(Integer.parseInt(keepNum));
                        // 清空 keepNum
                        keepNum = "";
                    }
                }
            }
            index++;
        }

        while (!operStack.isEmpty()){
            num1 = numStack.pop();
            num2 = numStack.pop();
            oper = operStack.pop();
            result = operStack.cal(num1, num2, oper);
            numStack.push(result);
        }

        System.out.printf("表达式 %s = %d", expression, numStack.queryTop());





    }
}

class ArrayStack2{
    private int maxSize;
    private int top = -1;
    private int [] stack;

    // 构造器
    public ArrayStack2(int maxSize){
        this.maxSize = maxSize;
        stack = new int[this.maxSize];
    }

    // 获取栈顶的元素,但不出栈
    public int queryTop(){
        return stack[top];
    }

    // 判断栈是否为空
    public boolean isEmpty(){
        return top == -1;
    }

    // 判断栈是否已满
    public boolean isFull(){
        return top == maxSize - 1;
    }

    //  入栈
    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 showStack(){
        if(isEmpty()){
            System.out.println("当前栈为空~~");
            return;
        }
        for (int i = top; i >= 0 ; i--) {
            System.out.printf("stack[%d] = %d\n", i, stack[i]);
        }
    }

    // 返回运算符的优先级,优先级由数字表示,数字越大,优先级越高
    public int priority(int oper){
        // if(oper == '(' || oper == ')'){
        //     return 4;
        // }
        if(oper == '^'){
            return 3;
        }else if(oper == '*' || oper == '/' || oper == '%'){
            return 2;
        }else if(oper == '+' || oper == '-'){
            return 1;
        }else{
            return 0;
        }
    }

    // 判断接收的字符是否是运算符
    public boolean isOper(int ch){
        if(ch == '*' || ch == '/' || ch == '+' || ch == '-' || ch == '%' || ch == '^'){
            return true;
        }else{
            return false;
        }
    }

  // 计算运算的结果
    public int cal(int num1, int num2, int ch){
        int res = 0;
        if(ch == '*'){
            res =  num2 * num1;
        }else if(ch == '/'){
            if(num1 == 0){
                throw new RuntimeException("表达式的格式有误,0不能作为除数");
            }
            res = num2 / num1;
        }else if(ch == '+'){
            res = num2 + num1;
        }else if(ch == '-'){
            res = num2 - num1;
        }else if(ch == '^'){
            res = (int)Math.pow(num2, num1);
        }else if(ch == '%'){
            res = num2 % num1;
        }
        return res;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值