Сканер пропускает nextLine () после использования next () или nextFoo ()?


я использую Scanner методы nextInt() и nextLine() для чтения входных данных.

это выглядит так:

System.out.println("Enter numerical value");    
int option;
option = input.nextInt(); // Read numerical value from input
System.out.println("Enter 1st string"); 
String string1 = input.nextLine(); // Read 1st string (this is skipped)
System.out.println("Enter 2nd string");
String string2 = input.nextLine(); // Read 2nd string (this appears right after reading numerical value)

проблема в том, что после ввода числового значения, первый input.nextLine() пропускается, а второй input.nextLine() выполняется, так что мой вывод выглядит следующим образом:

Enter numerical value
3   // This is my input
Enter 1st string    // The program is supposed to stop here and wait for my input, but is skipped
Enter 2nd string    // ...and this line is executed and waits for my input

я протестировал свое приложение, и похоже, что проблема заключается в использовании input.nextInt(). Если я удалю его, то оба string1 = input.nextLine() и string2 = input.nextLine() выполняются так, как я хочу, чтобы они быть.

15 501

15 ответов:

вот так Scanner.nextInt метод не потребляет последние строки характер вашего ввода, и при этом что новая строка потребляется при следующем вызове Scanner.nextLine.

вы столкнетесь с подобным поведением при использовании Scanner.nextLine после Scanner.next() и Scanner.nextFoo способ (кроме nextLine сам.)

решение:

  • либо стрелять холостым Scanner.nextLine звонить после Scanner.nextInt или Scanner.nextFoo потреблять остальную часть этой строки, включая новая строка

    int option = input.nextInt();
    input.nextLine();  // Consume newline left-over
    String str1 = input.nextLine();
    
  • или, было бы еще лучше, если бы вы прочитали ввод через Scanner.nextLine и конвертировать входные данные в нужный вам формат. Например, к целому числу с помощью Integer.parseInt(String) метод.

    int option = 0;
    try {
        option = Integer.parseInt(input.nextLine());
    } catch (NumberFormatException e) {
        e.printStackTrace();
    }
    String str1 = input.nextLine();
    

проблема с вход.nextInt() метод-он только считывает значение int. Поэтому, когда вы продолжаете читать с вводом.nextLine () вы получаете ключ ввода "\n". Так, чтобы пропустить это, вы должны добавить вход.nextLine (). Надеюсь, теперь это должно быть ясно.

попробуйте вот так:

System.out.print("Insert a number: ");
int number = input.nextInt();
input.nextLine(); // This line you have to add (It consumes the \n character)
System.out.print("Text1: ");
String text1 = input.nextLine();
System.out.print("Text2: ");
String text2 = input.nextLine();

это потому, что когда вы вводите номер, затем нажмите введите,input.nextInt() потребляет только число, а не "конец строки". Когда input.nextLine() выполняется, он потребляет "конец строки" все еще в буфере от первого входа.

вместо этого используйте input.nextLine() сразу после input.nextInt()

там, кажется, много вопросов об этой проблеме с java.util.Scanner. Я думаю, что более читаемым / идиоматическим решением было бы позвонить scanner.skip("[\r\n]+") чтобы удалить любые символы новой строки после вызова nextInt().

EDIT: как @PatrickParker отметил ниже, это вызовет бесконечный цикл, если пользователь вводит любые пробелы после числа. Смотрите их ответ для лучшего шаблона для использования с skip:https://stackoverflow.com/a/42471816/143585

Он делает это, потому что input.nextInt(); не захватывает новую строку. вы могли бы сделать, как и другие предложенные, добавив input.nextLine(); внизу.
В качестве альтернативы вы можете сделать это в стиле C# и разобрать следующую строку на целое число, например:

int number = Integer.parseInt(input.nextLine()); 

это работает так же хорошо, и это экономит вам строку кода.

вещей, которые вы должны знать:

  • текст, который представляет несколько строк, также содержит непечатаемые символы между строками (мы называем их разделителями строк), например

    • возврат каретки (CR-в строковых литералах, представленных как "\r")
    • подача строки (LF-в строковых литералах, представленных как "\n")
  • когда вы читаете данные с консоли, это позволяет пользователю ввести его ответ и когда он закончит он должен как-то подтвердить этот факт. Для этого пользователю необходимо нажать клавишу "enter"/"return" на клавиатуре.

    важно то, что этот ключ помимо обеспечения размещения пользовательских данных стандартный ввод (в лице System.in, который считывается Scanner) также отправляет зависимые от ОС разделители строк (например, для Windows \r\n) после него.

    поэтому, когда вы просите пользователя для значения, как age, и пользователь вводит 42 и нажимает enter, стандартный ввод будет содержать "42\r\n".

вместо input.nextLine() использовать input.next(), это должно решить проблему.

измененный код:

public static Scanner input = new Scanner(System.in);

public static void main(String[] args)
{
    System.out.print("Insert a number: ");
    int number = input.nextInt();
    System.out.print("Text1: ");
    String text1 = input.next();
    System.out.print("Text2: ");
    String text2 = input.next();
}

чтобы избежать этой проблемы, используйте nextLine(); сразу после nextInt(); как это помогает в очистке буфера. При нажатии кнопки ENTER the nextInt(); не захватывает новую строку и, следовательно, пропускает Scanner код позже.

Scanner scanner =  new Scanner(System.in);
int option = scanner.nextInt();
scanner.nextLine(); //clearing the buffer

если вы хотите быстро сканировать ввод, не путаясь в методе класса сканера nextLine (), используйте для этого пользовательский сканер ввода .

код :

class ScanReader {
/**
* @author Nikunj Khokhar
*/
    private byte[] buf = new byte[4 * 1024];
    private int index;
    private BufferedInputStream in;
    private int total;

    public ScanReader(InputStream inputStream) {
        in = new BufferedInputStream(inputStream);
    }

    private int scan() throws IOException {
        if (index >= total) {
            index = 0;
            total = in.read(buf);
            if (total <= 0) return -1;
        }
        return buf[index++];
    }
    public char scanChar(){
        int c=scan();
        while (isWhiteSpace(c))c=scan();
        return (char)c;
    }


    public int scanInt() throws IOException {
        int integer = 0;
        int n = scan();
        while (isWhiteSpace(n)) n = scan();
        int neg = 1;
        if (n == '-') {
            neg = -1;
            n = scan();
        }
        while (!isWhiteSpace(n)) {
            if (n >= '0' && n <= '9') {
                integer *= 10;
                integer += n - '0';
                n = scan();
            }
        }
        return neg * integer;
    }

    public String scanString() throws IOException {
        int c = scan();
        while (isWhiteSpace(c)) c = scan();
        StringBuilder res = new StringBuilder();
        do {
            res.appendCodePoint(c);
            c = scan();
        } while (!isWhiteSpace(c));
        return res.toString();
    }

    private boolean isWhiteSpace(int n) {
        if (n == ' ' || n == '\n' || n == '\r' || n == '\t' || n == -1) return true;
        else return false;
    }

    public long scanLong() throws IOException {
        long integer = 0;
        int n = scan();
        while (isWhiteSpace(n)) n = scan();
        int neg = 1;
        if (n == '-') {
            neg = -1;
            n = scan();
        }
        while (!isWhiteSpace(n)) {
            if (n >= '0' && n <= '9') {
                integer *= 10;
                integer += n - '0';
                n = scan();
            }
        }
        return neg * integer;
    }

    public void scanLong(long[] A) throws IOException {
        for (int i = 0; i < A.length; i++) A[i] = scanLong();
    }

    public void scanInt(int[] A) throws IOException {
        for (int i = 0; i < A.length; i++) A[i] = scanInt();
    }

    public double scanDouble() throws IOException {
        int c = scan();
        while (isWhiteSpace(c)) c = scan();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = scan();
        }
        double res = 0;
        while (!isWhiteSpace(c) && c != '.') {
            if (c == 'e' || c == 'E') {
                return res * Math.pow(10, scanInt());
            }
            res *= 10;
            res += c - '0';
            c = scan();
        }
        if (c == '.') {
            c = scan();
            double m = 1;
            while (!isWhiteSpace(c)) {
                if (c == 'e' || c == 'E') {
                    return res * Math.pow(10, scanInt());
                }
                m /= 10;
                res += (c - '0') * m;
                c = scan();
            }
        }
        return res * sgn;
    }

}

плюсы :

  • сканирование ввода быстрее, чем BufferReader
  • Уменьшает Сложность Времени
  • сбрасывает буфер для каждого следующего входа

методы :

  • scanChar () - сканирование одного символа
  • scanInt() - сканировать целочисленное значение
  • scanLong () - сканировать длинное значение
  • scanString () - сканировать строковое значение
  • scanDouble () - сканировать двойное значение
  • scanInt (int [] array) - сканирует полный массив(целое число)
  • scanLong (long[] array) - сканирование всего массива (Long)

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

  1. скопируйте данный код ниже вашего кода java.
  2. инициализировать объект для данного Класс

ScanReader sc = new ScanReader(System.in); 3. Импорт необходимых классов:

import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; 4. Бросьте IOException из вашего основного метода для обработки исключения 5. Используйте Предоставленные Методы. 6. Наслаждайтесь

пример :

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
class Main{
    public static void main(String... as) throws IOException{
        ScanReader sc = new ScanReader(System.in);
        int a=sc.scanInt();
        System.out.println(a);
    }
}
class ScanReader....

Если вы хотите читать обе строки и ints, решение заключается в использовании двух сканеров:

Scanner stringScanner = new Scanner(System.in);
Scanner intScanner = new Scanner(System.in);

intScanner.nextInt();
String s = stringScanner.nextLine(); // unaffected by previous nextInt()
System.out.println(s);

intScanner.close();
stringScanner.close();

sc.nextLine() лучше по сравнению с разбора входных данных. Потому что производительность мудрый это будет хорошо.

public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int i = scan.nextInt();
        scan.nextLine();
        double d = scan.nextDouble();
        scan.nextLine();
        String s = scan.nextLine();

        System.out.println("String: " + s);
        System.out.println("Double: " + d);
        System.out.println("Int: " + i);
    }

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

используя BufferedReader#nextLine(), Если бы Scanner#readLine(), избегает этой ошибки. Вы даже можете написать свою собственную оболочку сканера, чтобы переопределить функцию чтения строки сканера с помощью функции BufferedReader nextLine.

Я думаю, что я довольно поздно на вечеринку..

как уже было сказано, звоните input.nextLine() после получения вашего значения int решит вашу проблему. Причина, по которой ваш код не работал, заключалась в том, что больше нечего было хранить из вашего ввода (где вы ввели int) в string1. Я просто пролить немного света на всю эту тему.

считают nextLine () как нечетный среди nextFoo() методы в классе сканера. Давайте возьмем небольшой пример.. Допустим, у нас есть две строки кода, как показано ниже:

int firstNumber = input.nextInt();
int secondNumber = input.nextInt();

если мы вводим значение ниже (в виде одной строки ввода)

54 234

ценности firstNumber и secondNumber переменная становится 54 и 234 соответственно. Причина, по которой это работает таким образом, заключается в том, что новая подача строки (т. е. \n)ЭТО НЕ автоматически генерируется при использовании метода nextInt принимает значения. Он просто берет "next int" и движется дальше. Это то же самое для остальных методов nextFoo() за исключением nextLine().

nextLine () генерирует новый поток строк сразу после получения значения; это то, что @RohitJain означает, что новый поток строк "потребляется".

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

Я надеюсь, что это помогает.. Веселого кодирования!

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

int i = new Scanner(System.in).nextInt();