2016-12-12 1 views
0

Я использую Scanner для управления входом (который поставляется по 1 строке за раз) в мою программу. Во-первых, я проверяю строку, чтобы увидеть, какая команда она соответствует. Затем я использую Scanner next, чтобы пройти через линию и захватить или пропустить части ввода, которые я хочу (я мог бы использовать группы захвата регулярных выражений, но я предпочитаю делать это вручную.) Я использую next вместо skip даже для групп I меня не волнует, потому что я хочу быть уверен, что раздел ввода все равно соответствует, даже если мне все равно, что это такое, и skip просто молча игнорирует его, если он не совпадает.InputMismatchException после проверки с hasNext

Проблема в том, что даже после проверки определенного шаблона я получаю исключение InputMismatchException, когда я пытаюсь пройти мимо next.

String phone = "(1\\W?)?(\\d{3}|\\(\\d{3}\\))?\\W?\\d{3}\\W?\\d{4}"; 
String strline = "add 1112223333 matt"; 
Scanner line = new Scanner(strline).useDelimiter("\n"); 
String addPat = "(?i)add\\s+" + phone + "\\s+.+"; 
if (line.hasNext(addPat)) { 
    line.next("(?i)add\\s+");       //InputMismatchException thrown here 
    String number = line.next(phone); 
}    

Даже упрощенный случай терпит неудачу:

if (line.hasNext("(?i)add\\s+.+")) { 
    line.next("(?i)add\\s+"); 
    ... 
}   

ответ

1

Короткий ответ:

Использование:

line.findInLine("^" + "(?i)add\\s+"); 

вместо:

line.next("(?i)add\\s+"); 

Длинный ответ:
Если порыться в документации оду Scanner вы найдете такое определение:

Сканер разбивает свой вклад в лексем с использованием шаблона разделителя, который по умолчанию соответствует пустому пространству. Затем полученные токены могут быть преобразованы в значения разных типов с использованием различных методов.


Другими словами:

  • Каждый nextXXXXX метод анализирует ровно один маркер.
  • Маркер представляет собой фрагмент текста, который окружен двумя разделителями

Поскольку вы используете «\ п» в качестве разделителя, то есть только один маркер в строке ввода: «добавить 1112223333 матовый» - всю строку.

Этот маркер соответствует шаблону: addPat = "(?i)add\\s+" + phone + "\\s+.+";
Но этот маркер не соответствует шаблону: "(?i)add\\s+" и исключение.

Используйте методы Scanner#findInLine или Scanner#findWithinHorizon - эти методы игнорируют разделители и могут анализировать только часть токена.

+0

Документ для сканера говорит 'findWithinHorizon (Pattern.compile (pattern, horizon))', это опечатка? findWithinHorizon также имеет перегрузку (Pattern, int). У Pattern.compile есть перегрузка для String и int, но предполагается, что int - это или варианты шаблонов, а не расстояние.Кроме того, если я не знаю, как долго будет матч, как я могу вычислить горизонт для использования без риска «клипа», как описано в документе. Я хочу использовать findWithinHorizon вместо findInLine, чтобы он не соответствовал «BADTERM add [...]». –