检查表达式是否合法

public class Main {

    /**
     * 检查表达式是否合法,合法返回true
     * @param expression 表达式支持 +、-、*、/、(、)、整数、小数、负数
     * @return
     */
    private boolean checkExpression(String expression) {
        //去除空格
        expression = expression.replaceAll(" ","");
        // 支持的运算符
        Set<Character> operate_set = new HashSet<>();
        operate_set.add('-');
        operate_set.add('+');
        operate_set.add('*');
        operate_set.add('/');

        //拆分字符串
        char[] arr = expression.toCharArray();
        int len = arr.length;

        //前后括号计数,用来判断括号是否合法
        int checkNum = 0;

        //数字集合
        List<Character> digit_list = new ArrayList<>();
        //循环判断
        for (int i = 0; i < len; i++) {
            if(Character.isDigit(arr[i]) || arr[i] == '.'){ //数字和小数点判断
                //把数字和小数点加入到集合中,为了下一步判断数字是否合法
                digit_list.add(arr[i]);
            }else { //非数字和小数点
                //如果集合中有值,取出来判断这个数字整体是否合法
                if(digit_list.size() > 0) {
                    //判断字符串是否合法
                    boolean result = isNumberStringFromList(digit_list);
                    if(result){
                        //如果合法,清空集合,为了判断下一个
                        digit_list.clear();
                    }else{
                        //不合法,返回false
                        return false;
                    }
                }

                if (arr[i] == '+' || arr[i] == '*' || arr[i] == '/') {
                    //判断规则(1.不能位于首位 2.不能位于末尾 3.后面不能有其他运算符 4.后面不能有后括号)
                    if (i == 0 || i == (len - 1) || operate_set.contains(arr[i + 1]) || arr[i + 1] == ')') {
                        return false;
                    }
                } else if (arr[i] == '-') {
                    //减号判断规则(1.不能位于末尾 2.后面不能有其他运算符 3.后面不能有后括号)
                    if (i == (len - 1) || operate_set.contains(arr[i + 1]) || arr[i + 1] == ')') {
                        return false;
                    }

                } else if (arr[i] == '(') {
                    checkNum++;
                    //判断规则(1.不能位于末尾 2.后面不能有+,*,/运算符和后括号 3.前面不能为数字)
                    if (i == (len - 1) || arr[i + 1] == '+' || arr[i + 1] == '*' || arr[i + 1] == '/' || arr[i + 1] == ')'||(i != 0 && Character.isDigit(arr[i-1]))) {
                        return false;
                    }
                } else if (arr[i] == ')') {
                    checkNum--;
                    //判定规则(1.不能位于首位 2.后面不能是前括号 3.括号计数不能小于0,小于0说明前面少了前括号)
                    if (i == 0 || (i < (len - 1) && arr[i + 1] == '(') || checkNum < 0) {
                        return false;
                    }
                }else{
                    //非数字和运算符
                    return false;
                }
            }
        }

        // 表达式最后是数字,走这里,如果集合中有值,取出来判断这个数字整体是否合法
        if(digit_list.size() > 0) {
            //判断字符串是否合法
            boolean result = isNumberStringFromList(digit_list);
            if(result){
                //如果合法,清空集合,为了判断下一个
                digit_list.clear();
            }else{
                //不合法,返回false
                return false;
            }
        }

        //不为0,说明括号不对等,可能多前括号
        if(checkNum != 0){
            return false;
        }
        return true;
    }

    /**
     * 校验字符串是否是数值
     * @param list 由数字字符组成的字符列表
     * @return
     */
    private boolean isNumberStringFromList(List<Character> list){
        if(CollectionUtils.isEmpty(list)){
            return false;
        }
        //正则判断数字是否合法
        boolean result = isNumber(list.stream().map(Object::toString).collect(Collectors.joining()));

        if(!result){
            // numStr不是一个合法的数字,记录日志
        }
        return result;
    }

    /**
     * 判断字符串是否为整数,浮点数类型,是返回true
     * @param str
     * @return
     */
    public static boolean isNumber(String str){
        // ? 匹配前面的子表达式零次或一次
        // \d 匹配一个数字字符
        // * 匹配前面的子表达式零次或多次
        // + 匹配前面的子表达式一次或多次
        Pattern pattern = Pattern.
            compile("^-?([1-9]\\d*\\.\\d+|0\\.\\d*[1-9]\\d*|[1-9]\\d*|0)$");
        Matcher isNum = pattern.matcher(str);
        return isNum.matches();
    }

    public static void main(String[] args) {
        Main main = new Main();
        String[] arr = new String[]{
                "2+2.",
                "2+000.3",
                "2+0023",
                "2+a",
                "2)+1",
                "+2-3",
                "2+(3",
                "2+4)",
                "2+6/",
                "2+6+",
                "2+6*",
                "2+()+3",
                "2+(3+3)+8)+9",
                "100",
                "1+2",
                "(1+2)",
                "1.2",
                "1+1.2",
                "(1+1.2)",
                "1+(1+2)",
                "1+(1+2)*2",
                "1+(1+1.2)",
                "1+(1+1.2)*2",
                "(1+(1+1.2)*2)/2",
                "(1+(1+1.2)*2)*2",
                "(1+(1+1.2)*2)*(2+2)",
                "(1+(1+1.2)*2)*(2+2*3+20)",
                "(0.333)",
                "2+(-0.3)",
        };
        for (String s : arr) {
            System.out.println(s + " "  + main.checkExpression(s));
        }


//        String exp = "(L1+T10)/2+1.20+M3";
//        List<String> params = Lists.newArrayList("L1", "T10", "M3");
//        for (String param : params) {
//            exp = exp.replaceAll(param, "1");
//        }
//        System.out.println(exp);
//
//        System.out.println(exp + " " + main.checkExpression(exp));
    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值