1

Всем привет! Учусь работать с ArrayList-ом. Задача такая: добавляем элементы в список, и после того как ввели последний нужный элемент нужно закончить добавление. Решил этот вопрос через цикл while. Но столкнулся с проблемой: Для выхода из цикла нужно нажать какую-то клавишу. В идеале хотел выходом с цикла сделать нажатие пробела(Spacebar), но если я правильно понял по тому, что начитался на просторах интернета - это очень сложно. Так как программа учебная, решил сделать выход через символ(букву). И при выводе на консоль столкнулся с InputMismatchException. Начал пересматривать инфу которую уже знаю и гуглить, но еще больше себя запутал. Может кто подскажет, как обойти это исключение? сделать правильно? или даже прописать выход с цикла с помощью пробела? Спасибо всем, кто подскажет и научит!

    while (true) {
        int number = scan.nextInt();
        list.add(number);
        String out = scan.nextLine().toLowerCase();
        if("i".equals(out)){
            break;
        }
    }
    System.out.println(list);

Это кусок кода. Принцип работы такой: int number принимает наши числа, а когда нам "надоело" их вводить - мы нажимаем клавишу "i", цикл прерывается и в консоль выводит наш list.

insolor
  • 49,104
  • 3
  • 1
    Вы столкнулись с одной из самых популярных проблем у новичков. Чтобы прочитать символ после чтения числа с помощью nextInt, следовало использовать next, а не nextLine – Nowhere Man Nov 14 '23 at 12:29
  • 1
    Если же хотите использовать именно nextLine для ввода каждого числа с отдельной строки, НЕ нужно использовать nextInt, а читаете ввод построчно -- тогда вы сможете проверить и пробел/пустую строку как условие выхода. – Nowhere Man Nov 14 '23 at 12:37
  • Чтобы прочитать символ после чтения числа с помощью nextInt, следовало использовать next, а не nextLine - я так делал, но в таком случае массив выводится в консоль через один, или же опять исключение. Например при вводе 1,2,3 - вывод в консоль: 1,3; а при вводе 1.2.3.4 - исключение. – PavelPavlik Nov 14 '23 at 17:33
  • В обоих последних примерах данные не будут читаться для сканера, который по умолчанию использует пробельные символы как разделители. – Nowhere Man Nov 14 '23 at 17:47
  • Придумал такое решение: boolean bool = true; while (bool) { String input = scan.nextLine().toLowerCase(); if (Character.isDigit(input.charAt(0))) { list.add(Integer.valueOf(input)); } if(input.equals("q")) { bool = false; } } System.out.println(list); Приветствуется такое решение или очень большой код? Оцените пожалуйста. И, если это возможно, подскажите могу ли я вместо символа выбрать другую клавишу( например -пробел). Если да, то как это сделать? – PavelPavlik Nov 14 '23 at 18:43
  • Разумеется в таком решении вы можете выбрать и пробел вместо буквы 'q', но дело в том, что после пробела всё равно придётся нажимать Enter, чтобы была введена строка. Также в этом коде нет "защиты" от кривого ввода (может быть исключение при парсинге числа). – Nowhere Man Nov 14 '23 at 19:04
  • Можете посмотреть ответ – Nowhere Man Nov 14 '23 at 19:10

1 Answers1

0

Если стоит задача просто ввести целые числа в список, достаточно придерживаться однородного подхода:

  1. Использовать Scanner::nextInt (+ дополнительно проверять поток ввода Scanner::hasNextInt)
  2. Использовать построчный ввод Scanner::nextLine + Integer.parseInt / Integer.valueOf(String str)

Важно помнить, что по умолчанию разделителями в сканере являются только пробельные символы типа ' ', '\t', '\n'. Если ввод содержит другие разделительные символы, например, знаки пунктуации ',', '.', ';', сканер придётся дополнительно сконфигурировать при помощи метода Scanner::useDelimiter.

Примеры.

  1. Ввод размера списка/массива и последующее заполнение.
    Достаточно использовать только метод Scanner::nextInt:
public static List<Integer> readIntList(Scanner scan) {
    List<Integer> list = new ArrayList<>();
    System.out.println("Введите количество целых чисел: ");
    int n = scan.nextInt();
    System.out.println("Введите " + n + " чисел через пробел");
    while (n-- > 0) {
        list.add(scan.nextInt());
    }
    return list;
}
  1. Ввод списка произвольной длины, пока не будет обнаружено некоторое число -- признак конца ввода (0 для ввода натуральных чисел, -1 -- для ввода неотрицательных чисел и т.п.)
public static List<Integer> readIntList(Scanner scan, int limit) {
    List<Integer> list = new ArrayList<>();
    System.out.println("Вводите целые числа, пока не будет введено число " + limit + " -- признак конца ввода");
    int n;
    while ((n = scan.nextInt()) != limit) {
        list.add(n);
    }
    return list;
}

Как видно, оба метода достаточно просты благодаря тому, что используются одинаковые методы как для ввода основного содержимого списка, так и для ввода "ограничителей".

  1. Ввод списка чисел произвольной длины, пока не будет введена команда выхода (слово или буква)
    Фактически, это исправленный вариант начального кода.
    Для организации выхода будет использоваться особое множество слов Set<String> stopWords.
    Если же пользователь введёт "непонятное" слово или число, они будут проигнорированы.
public static List<Integer> readIntList(Scanner scan, Set<String> stopWords) {
    List<Integer> list = new ArrayList<>();
    System.out.println("Вводите целые числа, пока не будет введено одно из слов: " + stopWords);
    while (true) {
        if (scan.hasNextInt()) {
            list.add(scan.nextInt());
        } else if (scan.hasNext()) {
            if (stopWords.contains(scan.next().toLowerCase())) {
                break;
            }
        }
    }
    return list;
}
  1. Обработка построчного ввода, пока не будет введена пустая строка или же строка, содержащая только пробелы.
    Здесь будет использоваться Scanner::nextLine, для простоты примем, что каждое число вводится в своей строке:
public static List<Integer> readIntListByLine(Scanner scan) {
    List<Integer> list = new ArrayList<>();
    System.out.println("Введите список целых чисел, каждое в своей строке, конец ввода -- пустая строка");
    String line;
    while (!(line = scan.nextLine().trim()).isEmpty()) { // trim() уберёт пробелы
        try {
            list.add(Integer.valueOf(line));
        } catch (NumberFormatException numfex) {
            // numfex.printStackTrace();
        }
    }
    return list;
}

Аналогично можно реализовать проверку на ввод команды для прекращения ввода.

Nowhere Man
  • 15,995
  • 33
  • 19
  • 29