Исполнение условия, введённого пользователем

Пользователь вводит условие, предположим 3 > 2. Надо разбить его на части (первая, условие, вторая) и вывести true/false. Условие также может быть с подвохом: содержать знаки сравнения в строках "ab>=?c" != "ce"

Я пробовал использовать regex - split'ить строку по знакам сравнения, а дальше использовать switch, но тогда не будет работать второй приведенный пример и получится слишком громоздко.

String input = "3 > 2";

String first = input.split("[><=]")[0];
String second = input.split("[><=]")[1];

String operator = "";
Matcher operatorMatcher = Pattern.compile(".+\\s?(.*)\\s?.+").matcher(input);
if (operatorMatcher.find()) operator = operatorMatcher.group(1).trim();

boolean result;

switch (operator) {
    case ">" -> {
        if (Integer.parseInt(first) > Integer.parseInt(second) result = true;
        else result = false;
    }

    case "<" -> {
        //...
    }
    //и дальше
}

Есть ли какой-то оптимальный вариант?


Ответы (2 шт):

Автор решения: Qwer

Второй пример не будет работать, потому что он не числовой. Дело в том, что знаки сравнения (больше, меньше и тд.) применимы только к числам, к буквам нет. Буквенные значения можно только сравнить на тождественность, равны они между собой или нет. Тогда получается мы имеем две группы примеров – числовые и не числовые, и работать с разными группами должны по-разному.

// Для примера возьмем одно отрицательное число 
     String input = "-3 > 2";

        //обратите внимание, что в каждом примере математический знак отделен пробелами в двух сторон
        //значит мы можем выбрать в качестве "разделителя" пробел
        String [] arr = input.split(" ");

        //NumberUtils.isCreatable проверяет является ли строка числом
        if (NumberUtils.isCreatable(arr[0]) && NumberUtils.isCreatable(arr[2])) {
            int first = Integer.parseInt(arr[0]);
            int sec = Integer.parseInt(arr[2]);

            //switch можно дополнить любыми вариантами для arr[1] (математического знака), приведу тут наиболее очевидные
            switch (arr[1]) {
                case ">":
                    System.out.println(first > sec);
                    break;
                case "<":
                    System.out.println(first < sec);
                    break;
                case "=":
                    System.out.println(first == sec);
                    break;
                case "!=":
                    System.out.println(first != sec);
                    break;
            }
       //если пример не числовой, то он попадет в этот блок
        } else {
            switch (arr[1]) {
                case "=":
                    System.out.println(arr[0].equals(arr[2]));
                    break;
                case "!=":
                    System.out.println(!arr[0].equals(arr[2]));
                    break;
        }
    } 
}
}

Мой пример можно дополнить разного рода проверками. Например, переходить к блоку if/else только если размер arr = 3. Можно проверить arr[0] и arr[2], не являются ли они также математическими примерами и выполнить их в первую очередь. Тут все зависит от вашей задачи.

Так же обратите внимание на избыточность двойной проверки if/else в выражении if (Integer.parseInt(first) > Integer.parseInt(second) result = true; else result = false; , т.к. Вы сравниваете два интовых числа, то результат будет всегда иметь тип boolen. Переменная типа boolen имеет значение либо true, либо false. Посмотрите, насколько изящнее будет приравнять result к результату сравнения result =Integer.parseInt(first) > Integer.parseInt(second)

→ Ссылка
Автор решения: Stanislav Volodarskiy

Немного неожиданное решение - использование встроенного интерпретатора JavaScript:

import java.util.*;
import javax.script.*;

public class Temp {
    public static void main(String[] args) throws ScriptException {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        String expression = new Scanner(System.in).nextLine(); 
        System.out.println(engine.eval(expression));
    } 
}
$ javac Temp.java

$ echo "3 > 2" | java Temp
true

$ echo '"ab>=?c" != "ce"' | java Temp
true
→ Ссылка