如何让 Java 扫描仪确认空白输入?

How to get Java scanner to acknowledge blank input?

我无法让我的程序响应空输入。例如,假设我想提示用户输入类型为 BigDecimal 的货币价值以及货币类型。这是有问题的程序的样子。

public static void main(String[] args) {
    Scanner input = new Scanner(System.in);

    System.out.print("Enter the amount of money " 
                             + "and specify currency (USD or CNY): ");

    // initialize variable moneyInput
    BigDecimal moneyInput;

    // check if moneyInput is numeric
    try {
         moneyInput = input.nextBigDecimal();
    } catch (InputMismatchException e){
        System.err.println("InputMismatchException: non-numeric value");
        return;
    }

    // specify currency of moneyInput
    String currencyType = input.next();

    ...
}

所以在这里,像 100.00 USD 这样的输入可以正常工作。

Enter the amount of money and specify currency (USD or CNY): 100.00 USD
0.00 USD ≈ ¥670.17 CNY

ASDF USD 这样的输入会相应地导致错误消息。

Enter the amount of money and specify currency (USD or CNY): ASDF USD
InputMismatchException: non-numeric value

但是,如何强制程序响应空白输入,立即按下 return 键或在第一行输入一堆空格?例如:

Enter the amount of money and specify currency (USD or CNY): 





1000.00 USD
00.00 USD ≈ ¥6701.70 CNY

在上面的示例中,用户可以无限期地按下 return 键,直到输入可读的内容(有效或无效)。 我想实现一些方法来检查用户是否按下了 return 键而没有输入任何有意义的东西

另一个我不知道如何解释的结果是,如果用户只输入了货币价值,然后在最终输入货币之前多次按 [return]。

示例:

Enter the amount of money and specify currency (USD or CNY): 100.00



USD
0.00 USD ≈ ¥670.17 CNY

如何让程序在输入数值并用户按下 [return] 后提示用户 Please specify the currency:?像

Enter the amount of money and specify currency (USD or CNY): 100.00
Please specify the currency: USD
0.00 USD ≈ ¥670.17 CNY

通过将 try-catch 块之后的部分更改为:

,我能够实现上述功能
input.nextLine();
System.out.print("Please specify the currency: ");
String currencyType = input.nextLine();

但是使用这种方法,程序失去了允许用户在一行中输入 moneyInputcurrencyType 的能力,就像第一个例子中那样。 (同样,仍然存在能够为每个提示无限期地按下 [return] 直到最终输入可读内容的问题)。

感谢阅读,抱歉冗长 post。

Scanner 提供了两个基本的——有时是相互冲突的——用例:

  1. 通过 tokens 读取输入,忽略中间的任何空格(这就是您的初始代码所做的)
  2. 读取的输入,不特别处理这些行的任何内容

一般来说,将两者混合是一个糟糕的主意(它有效,但可能不是你想要的)。 next()nextBigDecimal() 等令牌读取方法会忽略换行符。

如果你想处理 Enter 你需要使用 Scanner.nextLine() 逐行读取用户的输入并单独解析每一行(即 line.split("\s+")),而不是使用 Scanner 的令牌读取方法。

有些人喜欢使用嵌套的 Scanner 并用一个 Scanner 逐行读取输入,然后将该行传递到新的 Scanner 以仅标记该行。

例如:

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");
    }
  }
}

如果您不想使用嵌套 Scanner,还有许多其他大致等效的机制。这是要点,但您可能希望添加额外的错误处理代码(例如,如果 new BigDecimal() 抛出异常:

使用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");
}

使用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]+)");

然后:

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");
}