如何解析输入字符串,如" 4> 1",解析表达式并返回布尔值

时间:2017-08-17 07:18:26

标签: java string parsing boolean-expression

我现在正在学习Java,并且不知道如何转换输入字符串(例如"4>1")以获得布尔返回。

我想实现的目标是,让Java根据boolean中的用户输入返回String(true / false)?

例如,我试图获得" true"的返回值输入" !(4>=10)"。

2 个答案:

答案 0 :(得分:3)

没有简单的答案

对于初学者来说,没有简单的解决方案。我注意到有人提到Boolean.valueOf(...);

Boolean.valueOf(String)方法的目标不是评估条件或方程。这只是将String"true""false"转换为Boolean对象的简单方法。

无论如何,如果你想要这种功能,你必须设置一些明确的限制。 (注意:有些方程没有答案:“0/0 = 0/0”)

正则表达式解析

如果您只是将整数与整数进行比较,那么您可以假设方程将始终采用以下格式:

<integer1>[whitespace]<operator>[whitespace]<integer2>

然后,您可以做的是使用正则表达式将您的字符串拆分为3个部分。

public static boolean evaluate(String input)
{
  Pattern compile = Pattern.compile("(\\d+)\\s*([<>=]+)\\s*(\\d+)");
  Matcher matcher = compile.matcher(input);
  if (matcher.matches())
  {
    String leftPart = matcher.group(1);
    String operatorPart = matcher.group(2);
    String rightPart = matcher.group(3);

    int i1 = Integer.parseInt(leftPart);
    int i2 = Integer.parseInt(rightPart);

    if (operatorPart.equals("<")) return i1 < i2;
    if (operatorPart.equals(">")) return i1 > i2;
    if (operatorPart.equals("=")) return i1 == i2;
    if (operatorPart.equals("<=")) return i1 <= i2;
    if (operatorPart.equals(">=")) return i1 >= i2;

    throw new IllegalArgumentException("invalid operator '" + operatorPart + "'");
  }

  throw new IllegalArgumentException("invalid format");
}

脚本引擎

Java还支持脚本引擎(例如Nashorn and others)。这些引擎可以调用javascript方法,例如eval(...) javascript方法,这正是您所需要的。所以,这可能是一个更好的解决方案。

public static boolean evaluate(String input)
{
  try
  {
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
    Object result = engine.eval("eval('" + input + "');");
    return Boolean.TRUE.equals(result);
  }
  catch (ScriptException e)
  {
    throw new IllegalArgumentException("invalid format");
  }
}

此解决方案可以处理更复杂的输入,例如"!(4>=10)"

注意:出于安全考虑,您可能希望从用户输入中删除特定字符。 (例如'字符)

答案 1 :(得分:0)

Suye Shen,在Java字符串中不是表达式 - 它们只是一系列字符,如果你问它们的布尔值,它们总是假的(比如说,任何字符串都没有布尔值)。

您可以将字符串转换为可以具有布尔值的表达式 - 您只需要创建解析器来读取字符串的内容 - 以及解析器 ,将解析后的符号评估为布尔值。

制作解析器和解析器并不是很难,但值得注意的是,如果您在问题中添加更多数学运算,它可能会发生巨大变化。您编写问题的方式,您只想评估表达式:

4>10

4<=100

!10>=3

!28<5

所以基本上,你只想支持符号{!,&lt; =,&gt; =,&lt;,&gt;}。甚至不是&#34; +&#34;,&#34; - &#34;或&#34; =&#34;是必要的。而你只想使用整数(整数)作为参数。这简单易行。我甚至删除了&#34;(&#34;和&#34;)&#34;使它成为最简单的例子。

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import org.apache.axis.utils.StringUtils;


class CheckUrlsSafeFromFile {

  private Scanner s;

  public static void main(String args[]) throws Exception {
    Scanner scanner = new Scanner(System.in);
    String token = scanner.next();

    //read the user input and resolve it to true/false, until user type 'exit'
    while (!token.equals("exit")) {
      System.out.println(resolveString(parseString(token)));
      token = scanner.next();
    }
    scanner.close();

  } 

  //this is the most basic parser. It takes in a string, and returns a 
  //list of numbers and symbols. 
  public static List<String> parseString (String input) {

    List<String> tokens = new ArrayList<String>();
    if (StringUtils.isEmpty(input)) return tokens;
    if (input.indexOf("!")==0) {
      tokens.add("not");
      input = input.substring(1);
      tokens.addAll(parseString(input));
    }
    else if (input.indexOf("<=")>0 && input.indexOf("<=")<input.length()-2) {
      String firstArgument = input.substring(0,input.indexOf("<="));
      String secondArgument = input.substring(input.indexOf("<=")+2);
      tokens.addAll(parseString(firstArgument));
      tokens.add("smaller-equals");
      tokens.addAll(parseString(secondArgument));
    }
    else if (input.indexOf(">=")>0 && input.indexOf(">=")<input.length()-2) {
      String firstArgument = input.substring(0,input.indexOf(">="));
      String secondArgument = input.substring(input.indexOf(">=")+2);
      tokens.addAll(parseString(firstArgument));
      tokens.add("greater-equals");
      tokens.addAll(parseString(secondArgument));
    }
    else if (input.indexOf("<")>0 && input.indexOf("<")<input.length()-1) {
      String firstArgument = input.substring(0,input.indexOf("<"));
      String secondArgument = input.substring(input.indexOf("<")+1);
      tokens.addAll(parseString(firstArgument));
      tokens.add("smaller");
      tokens.addAll(parseString(secondArgument));
    }
    else if (input.indexOf(">")>0 && input.indexOf(">")<input.length()-1) {
      String firstArgument = input.substring(0,input.indexOf(">"));
      String secondArgument = input.substring(input.indexOf(">")+1);
      tokens.addAll(parseString(firstArgument));
      tokens.add("greater");
      tokens.addAll(parseString(secondArgument));
    }
    else {
      tokens.add(input);
    }

    return tokens;
  }

  //And this is the resolver.
  public static boolean resolveString (List<String> parsedTokens) {
    if (parsedTokens==null || parsedTokens.size()==0) return false;
    if (parsedTokens.size()==1) return false;
    if (parsedTokens.get(0).equals("not")) {
      parsedTokens.remove(0);
      return !resolveString(parsedTokens);
    }
    if (parsedTokens.size()>2 && parsedTokens.get(1).equals("greater")) {
      String firstArgument = parsedTokens.get(0);
      String secondArgument = parsedTokens.get(2);
      int firstArgumentInt = Integer.parseInt(firstArgument);
      int secondArgumentInt = Integer.parseInt(secondArgument);
      return firstArgumentInt>secondArgumentInt;
    }
    if (parsedTokens.size()>2 && parsedTokens.get(1).equals("greater-equals")) {
      String firstArgument = parsedTokens.get(0);
      String secondArgument = parsedTokens.get(2);
      int firstArgumentInt = Integer.parseInt(firstArgument);
      int secondArgumentInt = Integer.parseInt(secondArgument);
      return firstArgumentInt>=secondArgumentInt;
    }
    if (parsedTokens.size()>2 && parsedTokens.get(1).equals("smaller")) {
      String firstArgument = parsedTokens.get(0);
      String secondArgument = parsedTokens.get(2);
      int firstArgumentInt = Integer.parseInt(firstArgument);
      int secondArgumentInt = Integer.parseInt(secondArgument);
      return firstArgumentInt<secondArgumentInt;
    }
    if (parsedTokens.size()>2 && parsedTokens.get(1).equals("smaller-equals")) {
      String firstArgument = parsedTokens.get(0);
      String secondArgument = parsedTokens.get(2);
      int firstArgumentInt = Integer.parseInt(firstArgument);
      int secondArgumentInt = Integer.parseInt(secondArgument);
      return firstArgumentInt<=secondArgumentInt;
    }
    return false;
  }
}

运行此结果可能如下:

4>10
false
4<=100
true
!10>=3
false
!28<5
true
exit

我希望您可以采用这个基本示例并对其进行扩展,以包含更多数学,如{+, - ,=,/,*,(,)}和更多符号,以及非整数。有可用于解析和解析的库,但是你自己解决这个问题可能是一个很好的Java课程。