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

时间:2016-07-20 02:12:02

标签: java input java.util.scanner bigdecimal

我无法让我的程序响应空输入。例如,假设我想提示用户输入类型为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
$100.00 USD ≈ ¥670.17 CNY

ASDF USD之类的输入会恰当地导致错误消息。

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

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

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





1000.00 USD
$1000.00 USD ≈ ¥6701.70 CNY

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

我不知道如何解释的另一个结果是,如果用户仅输入货币值,则在最终输入货币之前按[返回]一堆。

示例:

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



USD
$100.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
$100.00 USD ≈ ¥670.17 CNY

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

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

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

感谢您的阅读,并为长篇文章感到抱歉。

1 个答案:

答案 0 :(得分:10)

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

  1. 通过令牌读取输入,忽略其间的任何空格(这是您的初始代码所做的)
  2. 通过读取输入,而不处理这些行的任何内容
  3. 一般来说,将两者混合是一个糟糕的想法(它有效,但可能不是你想要的)。像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");
    }