Java Scanner.hasNextInt() в цикле с условием. Что не так с кодом?

171
06 октября 2021, 08:40

Начал учить Java. Появился вопрос как реализовать проверку вводимых данных в консоль.

Подскажите, пожалуйста, почему данный код зацикливается:

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

    boolean number = false;
    int ab;
    while (number == false)
    {
        System.out.println("Введите число");
        if (in.hasNextInt()) 
        {
            ab = Integer.parseInt(in.nextLine());
            System.out.println("Вы ввели: " + ab);
            number = true;
        }
        else
        {
            System.out.println("Вы ввели не число");
        }
    }
}

а данный нет:

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

    boolean number = false;
    int ab;
    while (number == false)
    {
        System.out.println("Введите число");
        if (in.hasNextInt()) 
        {
            ab = Integer.parseInt(in.nextLine());
            System.out.println("Вы ввели: " + ab);
            number = true;
        }
        else
        {
            System.out.println("Вы ввели не число");
            in.nextLine();
        }
    }
}

Или как лучше написать нечто подобное?

Answer 1

Имеется в виду случай, если пользователь вводит что-нибудь не целочисленное. Правильно?

Зацикливание в первом случае происходит потому что выполняется только лишь проверка введенных пользователем данных. Данные проверились. Целого числа там нет. Соответственно, выполняется инструкция блока else. Выводится сообщение "Вы ввели не число", затем происходит возврат в начало цикла. Снова "Введите число". И, затем, снова проверяются данные введенные пользователем. Те же самые данные. Они же никуда не делись. Чтобы их убрать, они должны быть прочтены. Это чтение как раз и происходит в блоке else второго варианта (in.nextLine();). Просто чтение, без записи куда-либо. После этого сканер снова встанет в режим ожидания ввода и никакого зацикливания не произойдет.

Answer 2

Условие if (in.hasNextInt()) проверяет можно ли введенные пользователем символы интерпретировать как целое число. Если сделать присваивание перед условием, то в случае некорректного ввода (например: "4g5") будет сгенерирована ошибка. Чтобы этого избежать, как раз таки и прописывается данное условие.

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

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    System.out.println("Введите число:");
    int ab = Integer.parseInt(in.nextLine());
    System.out.println("Вы ввели: " + ab);
}

Можно даже сделать так, чтобы из пользовательского ввода автоматически удалялись все символы, не являющиеся цифрами:

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    System.out.println("Введите число:");
    int ab = Integer.parseInt(in.nextLine().replaceAll("\\D", ""));
    System.out.println("Вы ввели: " + ab);
}

Результат:

Введите число:
54x5cxbxbgfb516xvbv
Вы ввели: 545516

Правда, в последнем случае, если пользователь введет символы среди которых вообще не будет цифр, то сгенерируется исключение. Решается опять же добавлением условия))

Answer 3

Пасыбо больсое, давно голову ломал почему так происходит, решил проблему зацикливанием на метод return, но этот способ проще. Немного упростил код без boolean:

 Scanner in = new Scanner(System.in);
  int ab;
        while (true)
        {
            System.out.println("Введите число");
            if (in.hasNextInt())
            {
                ab = Integer.parseInt(in.nextLine());
                System.out.println("Вы ввели: " + ab);
            break;
            }
            else
            {
                System.out.println("Вы ввели не число");
                in.nextLine();
            }}}

READ ALSO
JavaFx как получить Stage из Controller?

JavaFx как получить Stage из Controller?

Структура проект такой

323
Как вернуть фокус в начало текста в JTextPane?

Как вернуть фокус в начало текста в JTextPane?

После вывода текста в JTextPane, необходимо вернуть фокус в начало текста, а потом переместить фокус на кнопкуЧтобы долго не объяснять, вот две...

198
Вызов хранимой процедуры при помощи hibernate

Вызов хранимой процедуры при помощи hibernate

В базе данных есть хранимая процедура

238