Подтвердить что ты не робот

Почему Java просит меня снова нажать Enter?

Я немного устал от своего мозга, пытаясь понять, как работает Сканер. Итак, вот код:

Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
String p = sc.nextLine();
System.out.println(s);
System.out.println(p);
System.out.println(sc.hasNextLine());

Что я ожидаю:

Love is good  <- press ENTER
Love is blind <- press ENTER
Love is good  <- output
Love is blind <- output
false

Что у меня есть:

Love is good   <- I press ENTER
Love is blind  <- I press ENTER
Love is good   <- output
Love is blind  <- output
<- press ENTER
true <- output

Что я не понимаю:

  • Вместо немедленной печати этой строки - System.out.println(sc.hasNextLine()); - он заставляет меня снова нажать ENTER.
  • Он печатает true вместо false, в то время как больше нет строк или символов

Что я прочитал: я прочитал дюжину ответов stackoverflow об использовании hasNextLine() после nextInt() и о том, как nextInt() не потребляет окончательный символ в строке, но я не Не понимаю, почему, хотя я не использую nextInt() здесь, мне еще нужно нажать ENTER еще раз и почему hasNextLine() является истинным.

4b9b3361

Ответ 1

Вместо Scanner используйте BufferedReader следующим образом:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

class Test {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        String s = reader.readLine();
        String p = reader.readLine();
        System.out.println(s);
        System.out.println(p);      
        System.out.println(reader.ready());
    }
}

Чтобы узнать больше об этом, посмотрите здесь и здесь. Как правило, когда вам нужно разбирать вещи (например, nextInt), используйте Scanner, иначе придерживайтесь BufferedReader. BufferedReader намного быстрее, чем Scanner.

Что касается того, почему вы получили это неприятное поведение, см. javadoc для Scanner.

Часть, которая применяется в вашем конкретном случае:

Операция сканирования может блокировать ожидание ввода.

В этом случае это означает: после того, как первые две строки считываются с помощью Scanner, Scanner ожидает ввода, вызванного вызовом метода sc.hasNextLine(). Затем, когда Enter был поражен, он получил вход (следовательно, он печатает true, в соответствии с docs он возвращает true когда есть вход). Так как после вызова метода sc.hasNextLine() в вашей программе больше исполняемых строк, программа заканчивается, создавая иллюзию, что для этого требуется два ввода.

Ответ 2

Из Документация сканера (выделение мной):

public boolean hasNextLine()

Возвращает true, если на входе этого сканера есть еще одна строка. Этот метод может блокироваться при ожидании ввода. Сканер не продвигается мимо какого-либо ввода.

Вероятно, происходит то, что hasNextLine блокируется, потому что он ждет ввода, который вы даете, нажимая enter.

Ответ 3

Прежде всего, вы используете Scanner, объявленный в System.in, так что это означает, что вы спрашиваете .in проверить, является ли их значение больше, поэтому он ждет, чтобы пользователь что-то вводил, и после того, как вы нажмете enter, очевидно, что это возвращает true.

Итак, если вы хотите проверить s или p, скажите Сканер следующим образом:

Scanner sc = new Scanner(s);

или

Scanner sc = new Scanner(p);

тогда проверьте sc.hasNextLine();, это должно вернуть false, насколько я знаю, но для ввода пользователем я бы рекомендовал создать другую переменную Scanner, а затем взять значения от пользователя и использовать sc для вашей вещи hasNextline().

Надеюсь, первая логика поможет вам.

Ответ 4

Вы запрашиваете три строки ввода!

У стандартного ввода всегда есть еще одна строка, пока вы не закроете терминал. В системе Unix вы можете нажать Ctrl + D в конце, и он вернет flase (= вход закрыт).

Программа будет вести себя так, как ожидалось, если бы у вас был конечный ввод. Но интерактивный ввод: как программа знает, что пользователь не намерен вводить Шекспира дальше?

Функция hasNextLine() будет ждать появления нового входа (или для сигнала, что не может быть нового ввода). Эта функция не предназначена для "того, что пользователь уже вводил другую строку", а вместо этого означает "ждать следующей строки". Таким образом, для практических целей hasNextLine() эквивалентно "является ли пользовательский ввод все еще подключенным и может ли он в конечном итоге содержать другую строку".

Зачем вам нужна последняя строка? Просто удалите его!

Ответ 5

У вас есть проблема, что Scanner читается из заданного InputStream, который может быть чем-то вроде файла или в вашем случае System.in.

Как описано в этом ответе, файл имеет конец, а sc.hasNextLine() возвращает false. Пользуясь потоком, вы ожидаете, что он не будет иметь возможности предоставить входные данные и, следовательно, заблокирует и ждет ваш следующий вход.

Может быть, вы можете подумать о "выходе из char" (здесь это "#" ):

Scanner sc = new Scanner(System.in);
StringBuilder builder = new StringBuilder();
while (sc.hasNextLine()) {
    String line = sc.nextLine();
    if (line.equals("#")) {
        break;
    }
    builder.append(line + "\n");
}
System.out.println(builder.toString());
sc.close();

Ответ 6

В вашем случае я отладил ваш пример и увидел, что

System.out.println(sc.hasNextLine());
Строка

ожидает нового ввода. Это не правда и не ложно. Этого не существует. Именно поэтому он блокирует приложение. Неважно, что вы ввели (введите или любую другую кнопку на клавиатуре), это даст вам правду, потому что вы предоставили новый ввод.