java校验四则运算规则是否正确

  


前言

背景:在一些情况下需要用户通过四则运算的方式自定义程序的运行规则,这时就需要对用户的输入表达式进行校验,具体实现是通过入栈,出栈解析表达式,来校验元素子表达式时候符合运算规则。

一、具体代码实现

代码示例如下:


import java.util.Arrays;
import java.util.List;
import java.util.Stack;

/**
 * 校验四则运算语法
 * 目前只支持小括号级别的优先级运算"()"
 * 在这个例子中 支持 “且 或” 运算符 ,如需要添加其他运算符 可以通过setLogicList(List<String> logicList)进行赋值
 * node:这个类并没有经过完全的测试,请不要完全信任这个类
 * 该类的核心算法参考网上教程:https://zhuanlan.zhihu.com/p/273245625
 */
public class FourArithmeticOperationsValidate {

    /**
     * 代表临时运算结果,没有特殊含义
     */
    private String tempResult = "TR";

    private List<String> logicList = Arrays.asList("且", "或");

    private List<String> operatorList = Arrays.asList("且", "或", "(", ")");

    /**
     * 校验表达式
     *
     * @param exp
     * @return
     */
    public boolean doValidate(String exp) {

        // 定义一个栈,用来存储运算过程
        Stack<String> stack = new Stack<>();
        // 第一步去除括号,即先计算括号里面的
        for (int i = 0; i < exp.length(); i++) {
            String character = String.valueOf(exp.charAt(i));
            if (character.equals(" ")) {
                continue;
            }
            if (character.equals(")")) {
                // 如果遇到右括号,把栈中的数据一个一个取出来放入另外一个栈中,直到遇见左括号
                Stack<String> sb = new Stack<>();
                while (!stack.isEmpty() && !stack.peek().equals("(")) {
                    sb.push(stack.pop());
                }
                //如果不存在 “(” 说明 括号没有闭合
                if (stack.size() ==0 || !"(".equals(stack.peek())) return false;

                stack.pop();// 删除栈中的左括号
                if (!validationExpression(sb)) {
                    return false; //如果校验结果为false,无需进行继续校验
                }
                stack.push(tempResult);// 将括号里面的内容计算之后重新放入栈中

            } else {
                // 没有遇到右括号
                if (stack.isEmpty()) {
                    stack.push(character);
                    continue;
                }
                if (operatorList.contains(character)) {
                    stack.push(character); // 如果是运算符或者左括号,直接入栈
                } else {
                    // 如果不是操作符,需要和之前入栈的数字拼接
                    if (operatorList.contains(stack.peek()) || tempResult.equals(stack.peek())) {
                        stack.push(character); // 如果上一个入栈的是操作符,直接入栈
                    } else {
                        // 如果上一个入栈的不是操作符,先出栈,再拼接,最后入栈
                        stack.push(stack.pop() + character);
                    }
                }
            }
        }
        // 计算最后的结果
        if (stack.size() == 1) {// 计算完括号里面的,如果栈中只剩下一个元素
            return validationExpression(stack);
        } else {// 计算完括号里面的,栈中还有多个元素,继续计算
            // 但是此时栈中的元素是正序排列的,需要变成倒序再计算
            Stack<String> last = new Stack<>();
            while (!stack.isEmpty()) {
                last.push(stack.pop());
            }
            return validationExpression(last);
        }
    }

    /**
     * 校验单个表达式是否合法
     *
     * @param exp 表达式 此时的表达式中不应该还有(,)
     * @return true 校验通过 false 校验不通过
     */
    private boolean validationExpression(Stack<String> exp) {
        int size = exp.size();
        if (size == 0 || size == 2 || (size == 1 && logicList.contains(exp.peek()))) return false;
        if (exp.contains("(") || exp.contains(")")) return false;
        boolean dataFlag = false; //当前字符串为数值
        boolean optFlag = false;//当前字符串为操作符
        for (int i = 0; i < exp.size(); i++) {
            String s = exp.get(i);
            if (!logicList.contains(s)) {
                if (dataFlag) return false;
                dataFlag = true;
                optFlag = false;
            } else {
                if (optFlag) return false;
                optFlag = true;
                dataFlag = false;
            }
        }
        return dataFlag;
    }

    public List<String> getLogicList() {
        return logicList;
    }

    public void setLogicList(List<String> logicList) {
        this.logicList = logicList;
    }

    public List<String> getOperatorList() {
        return operatorList;
    }

    public void setOperatorList(List<String> operatorList) {
        this.operatorList = operatorList;
    }


}

以上代码的  validationExpression(Stack<String> exp) 方法主要用来验证子表达式是够符合运算规则。上面代码中的运算符是“且” “或” ,用户可以根据自已的需要通过setLogicList(List<String> logicList)方法来自定义运算符。

二、测试用例

示例代码如下:

public class FourArithmeticValidateTest {
    public static void main(String[] args) {
        
        FourArithmeticOperationsValidate expressTest = new FourArithmeticOperationsValidate();

        System.out.println("1且(" +expressTest.doValidate("1且("));
        System.out.println("1且()" +expressTest.doValidate("1且()"));
        System.out.println(")" +expressTest.doValidate(")"));


    }

    
}


总结

以上代码没有经过完全的测试,请不要直接cv,另外以上代码核心算法参考网上大佬教程,原文链接https://zhuanlan.zhihu.com/p/273245625

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值