Regex захвата чисел до и после символа

1

Я хочу иметь возможность отправить математическое выражение/уравнение в мою программу и дать мне ответ. Я использую регулярные выражения, чтобы декодировать числа для работы. Это мой текущий код регулярного выражения для добавления:

Matcher m = Pattern.compile(".*\\D*(\\d{1,})\\s*\\+\\s*(\\d+).*").matcher(e);
if(!m.matches()) return e;
e = ((int) Addition.add(Double.parseDouble(m.group(1)), Double.parseDouble(m.group(2)))) + "";

Это хорошо работает для второго номера в m.group(2) но m.group(1) возвращает только последнее число перед символом оператора, и я пробовал несколько разных способов, это один из моих последних неудач. Что я делаю не так?

EDIT: Это 3 метода решения, и у него есть некоторые тестовые результаты, с которыми я тестировал.

public double solve(String e) {
    if (!validExpression(e))
        return 0;
    e = e.replace(" ", "");
    boolean doPar = false;
    if (e.contains("(") || e.contains(")")) {
        doPar = true;
        int par = 0;
        for (char c : e.toCharArray()) {
            if (c == '(')
                par++;
            else if (c == ')')
                par--;
        }
        if (par != 0)
            return 0;
    }
    if (doPar)
        e = solveParentheses(e);
    e = solveSmallExpression(e);
    return Double.parseDouble(e.replace("(", "").replace(")", ""));
}

private static String solveSmallExpression(String e) {
    System.out.println(e);
    while(e.contains("^")){
        final Matcher m = Pattern.compile(".*\\D*(\\d{1,})\\s*\\^\\s*(\\d+).*").matcher(e);
        if(!m.matches()) return e;
        System.out.println(m.group(1) + "\t" + m.group(2));
        e = ((int) Exponentiation.raise(Double.parseDouble(m.group(1)), Double.parseDouble(m.group(2)))) + "";
    }
    while(e.contains("/") || e.contains("*")) {
        if(e.contains("/")){
            final Matcher m = Pattern.compile(".*\\D*(\\d{1,})\\s*/\\s*(\\d+).*").matcher(e);
            if(!m.matches()) return e;
            System.out.println(m.group(1) + "\t" + m.group(2));
            e = ((int) Division.divide(Double.parseDouble(m.group(1)), Double.parseDouble(m.group(2)))) + "";
        }
        if(e.contains("*")){
            final Matcher m = Pattern.compile(".*\\D*(\\d{1,}+)\\s*\\*\\s*(\\d+).*").matcher(e);
            if(!m.matches()) return e;
            System.out.println(m.group(1) + "\t" + m.group(2));
            e = ((int) Multiplication.multiply(Double.parseDouble(m.group(1)), Double.parseDouble(m.group(2)))) + "";
        }
    }
    while(e.contains("-") || e.contains("+")) {
        if(e.contains("-")){
            final Matcher m = Pattern.compile(".*\\D*(\\d{1,})\\s*\\-\\s*(\\d+).*").matcher(e);
            if(!m.matches()) return e;
            System.out.println(m.group(1) + "\t" + m.group(2));
            e = ((int) Subtraction.subtract(Double.parseDouble(m.group(1)), Double.parseDouble(m.group(2)))) + "";
        }
        if(e.contains("+")){
            final Matcher m = Pattern.compile(".*\\D*(\\d{1,})\\s*\\+\\s*(\\d+).*").matcher(e);
            if(!m.matches()) return e;
            System.out.println(m.group(1) + "\t" + m.group(2));
            e = ((int) Addition.add(Double.parseDouble(m.group(1)), Double.parseDouble(m.group(2)))) + "";
        }
    }
    System.out.println(e);
    System.out.println();
    return e;
}

private static String solveParentheses(String e) {
    while (e.contains("(") && e.contains(")")) {
        int start = -1;
        int end = -1;
        for(int i = 0; i < e.length(); i++) {
            char c = e.charAt(i);
            if(c == '(')
                start = i + 1;
            else if(c == ')')
                end = i;
        }

        String sub = e.substring(start, end);
        if(sub.contains("(") && sub.contains(")"))
            sub = solveParentheses(sub);
        sub = solveSmallExpression(sub);
        e = e.replace(e.subSequence(start - 1, end + 1), sub);
    }
    return e;
}

private static boolean validExpression(String e) {
    for (char c : e.toCharArray()) {
        if (!Character.isDigit(c) && c != '(' && c != ')' && c != '^' && c != '+' && c != '-' && c != '/' && c != '*' && c != ' ')
            return false;
    }
    return true;
}

Когда я печатаю это:
System.out.println((new ExpressionSolver()).solve("(24 * 100) - (24/12)"));
Это результат:

24/12
4   12
0

24*100
4   100
400

400-0
0   0
0

0.0
  • 2
    Пожалуйста, предоставьте образец ввода и ожидаемый результат.
  • 0
    «математическое выражение» слишком общее. Вы хотите поддержать скобки? Modulus? логарифмы? Или просто +-*/ ?
Показать ещё 1 комментарий
Теги:
numbers
capturing-group

2 ответа

1
Лучший ответ

. * жадный, и будет есть всю строку, а затем откат, пока не ударит что-то, что соответствует. Поскольку вы можете иметь 0 вхождений нецифровой (\ D *) и нуждаться хотя бы в одной цифре и знаке плюса, регулярное выражение будет совпадать, как только оно вернется достаточно далеко, чтобы его ударить.

Вы можете исправить это, используя ". *?" вместо этого, неохотный оператор, который захватывает как можно меньше символов.

  • 0
    Это сработало! Я не знал, что ты можешь использовать ? сдерживать жадных операторов. Я знал, что это существует, но я не совсем знал, что это было до сих пор. Спасибо!
0

Почему вы не используете одно и то же групповое объявление в обеих группах?

Использует средства (\ d+)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню