2016-07-20 7 views
5

У меня возникли проблемы с получением моей программы ответа на пустые входы. Например, скажем, я хотел бы попросить пользователя ввести значение для денег с типом BigDecimal, а также тип валюты. Вот как выглядит данная программа.Как получить сканер Java для подтверждения пустого ввода?

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 

Как получить программу, чтобы подсказать пользователю что-то вроде 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 

Я был в состоянии достигнуть выше функциональность, изменив часть после блока примерки поймать в:

input.nextLine(); 
System.out.print("Please specify the currency: "); 
String currencyType = input.nextLine(); 

Но с помощью этого метода, программа теряет возможность разрешить пользователю для ввода как moneyInput, так и currencyType в одну строку, как в первом примере. (И опять же, по-прежнему существует проблема, позволяющая бесконечно нажимать [return] для каждого из этих запросов до тех пор, пока не будет прочитан какой-нибудь читаемый).

Спасибо за чтение и извините за длинный пост.

ответ

10

Scanner предлагает два основных - и иногда противоречащие друг другу - Прецеденты:

  1. Читать вход на лексем, игнорируя любые пробелы между ними (это то, что ваш исходный код делает)
  2. Читать вход по линии, без обработки какого-либо содержимого этих линий, особенно

Вообще говоря, смешивание двух является плохой идеей (это работает, но, вероятно, не так, как вы предполагаете). Методы чтения маркера, такие как next() и nextBigDecimal(), игнорируют новые строки.

Если вы хотите обрабатывать Enter вам необходимо прочитать строку ввода-построчного пользователя с Scanner.nextLine() и разобрать каждую строку по отдельности (т.е. line.split("\\s+")), а не использовать Scanner «s методов маркеров чтения.

Некоторые люди любят использовать вложенные 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"); 
} 
+0

Привет, не могли бы вы показать, как использовать метод parse с 'line.split (" \\ s + ")' для достижения того же результата? Я не знаком с этим методом, поэтому мне сложно синтаксис. Спасибо –

+1

Добавлены дополнительные примеры. – dimo414

+0

Хорошо, как я могу отдельно проверить, действительно ли 'currency'? Я хочу, чтобы он действовал так же, как и с 'moneyInput', т. Е. Если было введено что-то вроде' 100.00 abc' или '100.00', пользователь повторно запрашивает только« валюту », и как только они вводят действительную валюту, USD', программа возобновляется нормально. Я попытался использовать другой цикл do-while внутри, чтобы проверить валюту, и это сработало, за исключением того, когда был введен пустой ввод, что в основном та же проблема, что и в начале этого сообщения (вот мой код: http: // pastebin .com/raw/CT0qjBPk и скриншоты программы: http://imgur.com/a/mjfaL). –