Java实现中缀表达式计算

中缀表达式计算,注释完整易懂。无健壮性,要求正确输入。

import java.util.Scanner;
import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String expression = input.nextLine();
        try {
            System.out.println(expression + " = " + calculateInfixExpression(expression));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
    //计算中缀表达式
    public static int calculateInfixExpression(String expression) {
        //定义两个栈(操作数栈、运算符栈)
        Stack<String> s1 = new Stack<String>();
        Stack<String> s2 = new Stack<String>();
        //遍历表达式
        int flag = 0;//上一个是空或者符号则为0
        int isNegative = 0;//是一就把数字变负数
        int i = 0;
        int len = expression.length();
        char ch;     //当前字符
        String op;   //运算符
        int num1;     //操作数1
        int num2;    //操作数2
        int res;     //运算结果
        while (i < len) {
            ch = expression.charAt(i);
            //判断当前字符是操作数还是运算符
            //System.out.println(ch);
            if (ch >= 48 && ch <= 57) {
                //当前字符是操作数,则直接入栈
                String str = "" + ch;
                while (i + 1 < len) {
                    ch = expression.charAt(i + 1);
                    if (ch < 48 || ch > 57) {
                        break;
                    } else {
                        i++;
                        str += ch;
                    }
                }
                if (isNegative == 1) {
                    str = "-" + str;
                    isNegative = 0;
                }
                s1.push(str);
                flag = 1;
            } else {
                //当前字符是运算符,则判断是 左括号 或 右括号 或 + - * /
                if (ch == '(') {
                    //直接入栈
                    s2.push("" + ch);
                    flag = 0;
                } else if (ch == ')') {
                    //出栈并运算,直到遇到左括号,最后丢弃这对括号
                    while (!s2.peek().equals("(")) {
                        op = s2.pop();
                        num1 = Integer.parseInt(s1.pop());
                        num2 = Integer.parseInt(s1.pop());
                        //计算 num2 op num1 并将结果压入栈, 注意传参的顺序
                        res = calculate(num2, op, num1);
                        s1.push("" + res);
                    }
                    //丢弃这对括号
                    s2.pop();
                } else if (ch == '-') {
                    if (flag == 0) {
                        isNegative = 1;
                    } else {
                        if (s2.empty()) {
                            s2.push("" + ch);
                        } else {
                            //判断优先级
                            String currentOp = "" + ch;
                            String stackTopOp = s2.peek();
                            //当前运算符 > 栈顶运算符,直接入栈
                            if (priority(currentOp) > priority(stackTopOp)) {
                                s2.push(currentOp);
                            } else {
                                //当前运算符 <= 栈顶运算符,不断弹出栈顶运算符并计算,直到当前 运算符 >栈顶运算符 或 栈为空
                                while (!s2.empty() && priority(currentOp) <= priority(s2.peek())) {
                                    op = s2.pop();
                                    num1 = Integer.parseInt(s1.pop());
                                    num2 = Integer.parseInt(s1.pop());
                                    res = calculate(num2, op, num1);
                                    s1.push("" + res);
                                }
                                //将当前运算符压入栈
                                s2.push(currentOp);
                            }
                        }
                        flag = 0;
                    }

                } else if (isOper(ch)) {
                    //如果是 + - * /, 则需要跟栈顶运算符判断优先级(先判断栈是否为空,为空就直接入栈)
                    if (s2.empty()) {
                        s2.push("" + ch);
                    } else {
                        //判断优先级
                        String currentOp = "" + ch;
                        String stackTopOp = s2.peek();
                        //当前运算符 > 栈顶运算符,直接入栈
                        if (priority(currentOp) > priority(stackTopOp)) {
                            s2.push(currentOp);
                        } else {
                            //当前运算符 <= 栈顶运算符,不断弹出栈顶运算符并计算,直到当前 运算符 >栈顶运算符 或 栈为空
                            while (!s2.empty() && priority(currentOp) <= priority(s2.peek())) {
                                op = s2.pop();
                                num1 = Integer.parseInt(s1.pop());
                                num2 = Integer.parseInt(s1.pop());
                                res = calculate(num2, op, num1);
                                s1.push("" + res);
                            }
                            //将当前运算符压入栈
                            s2.push(currentOp);
                        }
                    }
                    flag = 0;
                } else {
                    //遇到无法识别字符则抛出异常
                    throw new RuntimeException("无法识别" + ch);
                }
            }
            i++;
        }
        //将剩下的操作符逐一弹出栈并计算
        while (!s2.empty()) {
            op = s2.pop();
            num1 = Integer.parseInt(s1.pop());
            num2 = Integer.parseInt(s1.pop());
            res = calculate(num2, op, num1);
            s1.push("" + res);
        }
        res = Integer.parseInt(s1.pop());
        return res;
    }

    //判断是不是运算符
    public static boolean isOper(char op) {//这里不对减号进行判断,因为减号可能是负号,计算时单独判断
        return op == '+' || op == '%' || op == '*' || op == '/';
    }

    //计算 num1 op num2
    public static int calculate(int num1, String op, int num2) {
        int res = 0;
        switch (op) {
            case "+":
                res = num1 + num2;
                break;
            case "-":
                res = num1 - num2;
                break;
            case "*":
                res = num1 * num2;
                break;
            case "/":
                res = num1 / num2;
                break;
            case "%":
                res = num1 % num2;
                break;
            default:
                break;
        }
        return res;
    }

    //返回运算符的优先级
    public static int priority(String op) {
        switch (op) {
            case "+":
            case "-":
                return 1;
            case "*":
            case "/":
            case "%":
                return 2;
            case "(":
                return 0;
            default:
                return -1;
        }
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值