Исполнение условия, введённого пользователем
Пользователь вводит условие, предположим 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 шт):
Второй пример не будет работать, потому что он не числовой. Дело в том, что знаки сравнения (больше, меньше и тд.) применимы только к числам, к буквам нет. Буквенные значения можно только сравнить на тождественность, равны они между собой или нет. Тогда получается мы имеем две группы примеров – числовые и не числовые, и работать с разными группами должны по-разному.
// Для примера возьмем одно отрицательное число
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)
Немного неожиданное решение - использование встроенного интерпретатора 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