How to get Java scanner to acknowledge blank input?

前端 未结 1 1128
星月不相逢
星月不相逢 2021-01-05 17:00

I am having trouble getting my program to respond to empty inputs. For example, say I wanted to prompt the user to enter a value for money with type BigDecimal

1条回答
  •  生来不讨喜
    2021-01-05 18:05

    Scanner offers two basic - and sometimes conflicting - use cases:

    1. Read input by tokens, disregarding any whitespace inbetween (this is what your initial code does)
    2. Read input by line, without treating any contents of those lines specially

    Generally speaking mixing the two is a poor idea (it works, but probably not how you intend). The token-reading methods like next() and nextBigDecimal() ignore newlines.

    If you want to handle Enter you need to read a user's input line-by-line with Scanner.nextLine() and parse each line individually (i.e. line.split("\\s+")), rather than use Scanner's token-reading methods.

    Some people like to use nested Scanners and read input line by line with one Scanner then pass the line into a new Scanner to tokenize just that line.

    For example:

    try (Scanner in = new Scanner(System.in)) {
      while (in.hasNextLine()) {
        try {
          String line = in.nextLine();
          Scanner lineScan = new Scanner(line);
          BigDecimal moneyInput = lineScan.nextBigDecimal();
          String currency = lineScan.next();
          // do something
        } catch (NoSuchElementException | IllegalStateException e) {
          System.err.print("Please enter the VALUE followed by the CURRENCY");
        }
      }
    }
    

    If you don't want to use a nested Scanner there are a number of other roughly-equivalent mechanisms. Here's the gist, but you'll likely want to add additional error-handling code (e.g. if new BigDecimal() throws an exception:

    Using String.split():

    String[] parts = line.split("\\s+");
    if (parts.length == 2) {
      BigDecimal moneyInput = new BigDecimal(parts[0]);
      String currency = parts[1];
      // do something
    } else {
      System.err.println("Please enter the VALUE followed by the CURRENCY");
    }
    

    Using Pattern:

    /**
     * Matches one or more digits, optionally followed by a . and more digits,
     * followed by whitespace then one or more uppercase letters.
     */
    private static final Pattern MONEY_PATTERN =
        Pattern.compile("(\\d+(?:\\.\\d+))\\s+([A-Z]+)");
    

    Then:

    Matcher m = MONEY_PATTERN.matcher(line);
    if (m.matches()) {
      BigDecimal moneyInput = new BigDecimal(m.group(1));
      String currency = m.group(2);
    // do something
    } else {
      System.err.println("Please enter the VALUE followed by the CURRENCY");
    }
    

    0 讨论(0)
提交回复
热议问题