Der Scanner überspringt nextLine (), nachdem next () oder nextFoo () verwendet wurden.

Oct 27 2012

Ich benutze die ScannerMethoden nextInt()und nextLine()zum Lesen von Eingaben.

Es sieht aus wie das:

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)

Das Problem ist, dass nach Eingabe des numerischen Werts der erste input.nextLine()übersprungen und der zweite input.nextLine()ausgeführt wird, so dass meine Ausgabe folgendermaßen aussieht:

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

Ich habe meine Anwendung getestet und es sieht so aus, als ob das Problem in der Verwendung liegt input.nextInt(). Wenn ich es lösche, werden beide string1 = input.nextLine()und string2 = input.nextLine()so ausgeführt, wie ich es möchte.

Antworten

898 RohitJain Oct 27 2012 at 23:39

Dies liegt daran, dass die Scanner.nextIntMethode das Zeilenumbruchzeichen in Ihrer Eingabe nicht liest, das durch Drücken der Eingabetaste erstellt wurde, und der Aufruf von Scanner.nextLinenach dem Lesen dieser Zeilenumbruch zurückkehrt .

Sie werden auf ein ähnliches Verhalten stoßen, wenn Sie Scanner.nextLineafter Scanner.next()oder eine andere Scanner.nextFooMethode (außer sich nextLineselbst) verwenden.

Problemumgehung:

  • Setzen entweder einen Scanner.nextLineAnruf nach jedem Scanner.nextIntoder Scanner.nextFoozu konsumieren Rest der Zeile einschließlich Newline

    int option = input.nextInt();
    input.nextLine();  // Consume newline left-over
    String str1 = input.nextLine();
    
  • Oder, noch besser, lesen Sie die Eingabe durch Scanner.nextLineund konvertieren Sie Ihre Eingabe in das richtige Format, das Sie benötigen. Beispielsweise können Sie mithilfe der Integer.parseInt(String)Methode in eine Ganzzahl konvertieren .

    int option = 0;
    try {
        option = Integer.parseInt(input.nextLine());
    } catch (NumberFormatException e) {
        e.printStackTrace();
    }
    String str1 = input.nextLine();
    
222 Prine Aug 14 2011 at 19:24

Das Problem liegt bei der Methode input.nextInt () , die nur den Wert int liest. Wenn Sie also mit input.nextLine () weiterlesen, erhalten Sie die Eingabetaste "\ n". Um dies zu überspringen, müssen Sie die input.nextLine () hinzufügen . Hoffe das sollte jetzt klar sein.

Versuchen Sie es so:

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();
85 Bohemian Aug 14 2011 at 19:25

Wenn Sie eine Nummer eingeben und dann drücken Enter, wird input.nextInt()nur die Nummer verbraucht, nicht das "Zeilenende". Bei der input.nextLine()Ausführung wird das noch im Puffer befindliche "Zeilenende" von der ersten Eingabe verbraucht.

Verwenden Sie stattdessen input.nextLine()sofort danachinput.nextInt()

51 DenisTulskiy Mar 23 2014 at 23:35

Es scheint viele Fragen zu diesem Thema zu geben java.util.Scanner. Ich denke, eine lesbarere / idiomatischere Lösung wäre, aufzurufen scanner.skip("[\r\n]+"), um nach dem Aufruf alle Zeilenumbrüche zu löschen nextInt().

BEARBEITEN: Wie unten bei @PatrickParker angegeben, führt dies zu einer Endlosschleife, wenn der Benutzer nach der Nummer ein Leerzeichen eingibt. In der Antwort finden Sie ein besseres Muster für das Überspringen:https://stackoverflow.com/a/42471816/143585

37 ElectricCoffee Feb 24 2013 at 05:01

input.nextInt();Dies geschieht, weil der Zeilenumbruch nicht erfasst wird. Sie könnten wie die anderen vorgeschlagenen tun, indem Sie eine input.nextLine();darunter hinzufügen .
Alternativ können Sie es im C # -Stil ausführen und eine nextLine in eine Ganzzahl wie folgt analysieren:

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

Dies funktioniert genauso gut und spart Ihnen eine Codezeile.

28 Pshemo Oct 10 2016 at 05:51

TL; DR Verwendung scanner.skip("\\R")vor jedem scanner.newLine()Aufruf, der ausgeführt wird nach:

  • scanner.next()
  • scanner.next*TYPE*()Methode, wie scanner.nextInt().

Dinge, die Sie wissen müssen:

  • Text, der nur wenige Zeilen darstellt, enthält auch nicht druckbare Zeichen zwischen Zeilen (wir nennen sie Zeilentrennzeichen) wie

  • Wagenrücklauf (CR - in String-Literalen dargestellt als "\r")

  • Zeilenvorschub (LF - in String-Literalen dargestellt als "\n")

  • Wenn Sie Daten von der Konsole lesen, kann der Benutzer seine Antwort eingeben, und wenn er fertig ist, muss er diese Tatsache irgendwie bestätigen. Dazu muss der Benutzer die Eingabetaste / Eingabetaste auf der Tastatur drücken.

Wichtig ist, dass dieser Schlüssel neben der Sicherstellung, dass Benutzerdaten in die Standardeingabe (dargestellt durch System.indie gelesen wird Scanner) gestellt werden, auch betriebssystemabhängige Zeilentrennzeichen (wie bei Windows \r\n) nachträglich sendet .

Wenn Sie also den Benutzer nach einem Wert wie fragen ageund Benutzertypen 42 eingeben und die Eingabetaste drücken, enthält die Standardeingabe "42\r\n".

Problem

Scanner#nextInt(und andere Methoden) erlaubt es nicht , Scanner zu verbrauchen diese Zeilenseparatoren. Es wird sich von lesen (wie sonst Scanner würde wissen , dass es nicht mehr Ziffern von dem Benutzer , die repräsentieren Wert als Leerzeichen gegenüber ?) , Die sie von der Standardeingabe entfernen, aber es wird auch cachen diese Zeilenseparatoren intern . Wir müssen uns daran erinnern, dass alle Scannermethoden immer ausgehend vom zwischengespeicherten Text scannen.Scanner#nextTypeSystem.inage

Sammelt jetzt Scanner#nextLine()einfach alle Zeichen und gibt sie zurück, bis Zeilentrennzeichen (oder das Ende des Streams) gefunden werden. Da Zeilentrennzeichen nach dem Lesen der Nummer von der Konsole sofort im Cache des Scanners gefunden werden, wird eine leere Zeichenfolge zurückgegeben, was bedeutet, dass Scanner vor diesen Zeilentrennzeichen (oder dem Ende des Streams) kein Zeichen finden konnte.
BTW nextLineauch verbraucht diese Zeilenseparatoren.

Lösung

Also , wenn Sie wollen Nummer fragen und dann für ganze Zeile während der leeren Zeichenfolge als Ergebnis zu vermeiden nextLine, entweder

  • verbrauchen Zeilentrennzeichen nextIntvon Scanner-Cache von
  • anrufen nextLine,
  • oder IMO besser lesbar wäre, wenn Sie anrufen skip("\\R")oder skip("\r\n|\r|\n")den Scanner einen Teil überspringen lassen, der durch ein Zeilentrennzeichen übereinstimmt (weitere Informationen zu \R:https://stackoverflow.com/a/31060125)
  • Verwenden Sie nextInt(noch nextoder keine nextTYPEMethoden) überhaupt nicht. Lesen Sie stattdessen die gesamten Daten Zeile für Zeile mit nextLineund analysieren Sie die Nummern aus jeder Zeile (vorausgesetzt, eine Zeile enthält nur eine Nummer), um den richtigen Typ wie intvia zu erhalten Integer.parseInt.

Übrigens : Methoden können Trennzeichen (standardmäßig alle Leerzeichen wie Tabulatoren, Zeilentrennzeichen) einschließlich der vom Scanner zwischengespeicherten Trennzeichen überspringen , bis sie den nächsten Nicht-Trennzeichenwert (Token) finden. Vielen Dank für die Eingabe wie CodeScanner#nextType"42\r\n\r\n321\r\n\r\n\r\nfoobar"

int num1 = sc.nextInt();
int num2 = sc.nextInt();
String name = sc.next();

wird in der Lage sein, richtig zuzuweisen num1=42 num2=321 name=foobar.

17 Castaldi Jul 23 2014 at 17:20

Anstelle der input.nextLine()Verwendung input.next()sollte dies das Problem lösen.

Geänderter Code:

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();
}
16 AndréWillikValenti Jun 21 2017 at 01:52

Wenn Sie sowohl Zeichenfolgen als auch Ints lesen möchten, können Sie zwei Scanner verwenden:

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();
13 NIKUNJKHOKHAR Jun 16 2017 at 15:12

Wenn Sie Eingaben schnell scannen möchten, ohne in die nextLine () -Methode der Scannerklasse verwirrt zu werden, verwenden Sie dafür den benutzerdefinierten Eingabescanner.

Code:

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;
    }

}

Vorteile:

  • Scannt die Eingabe schneller als BufferReader
  • Reduziert die Zeitkomplexität
  • Leert den Puffer für jede nächste Eingabe

Methoden:

  • scanChar () - Einzelzeichen scannen
  • scanInt () - Ganzzahligen Wert scannen
  • scanLong () - Langwert scannen
  • scanString () - String-Wert scannen
  • scanDouble () - Scan Doppelter Wert
  • scanInt (int [] array) - scannt das gesamte Array (Integer)
  • scanLong (long [] array) - scannt das gesamte Array (Long)

Verwendung :

  1. Kopieren Sie den angegebenen Code unter Ihren Java-Code.
  2. Objekt für bestimmte Klasse initialisieren

ScanReader sc = new ScanReader(System.in); 3. Importieren Sie die erforderlichen Klassen:

import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; 4. Lösen Sie IOException von Ihrer Hauptmethode aus, um Exception zu behandeln. 5. Verwenden Sie die bereitgestellten Methoden. 6. Genießen Sie

Beispiel:

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....
12 UrvashiGupta Nov 17 2016 at 07:51

Um das Problem zu vermeiden, verwenden Sie es nextLine();sofort danach, nextInt();da es beim Löschen des Puffers hilft. Wenn Sie drücken ENTERdie nextInt();nicht die neue Linie erfassen und daher überspringt die Scannerspäter Code.

Scanner scanner =  new Scanner(System.in);
int option = scanner.nextInt();
scanner.nextLine(); //clearing the buffer
10 shankarupadhyay Sep 14 2017 at 17:16

sc.nextLine()ist besser als das Parsen der Eingabe. Weil es in Bezug auf die Leistung gut sein wird.

6 TaslimOseni Jan 07 2018 at 17:33

Ich denke, ich bin ziemlich spät zur Party.

Wie bereits erwähnt, input.nextLine()löst ein Anruf nach dem Abrufen Ihres int-Werts Ihr Problem. Der Grund, warum Ihr Code nicht funktionierte, war, dass Sie nichts anderes von Ihrer Eingabe (in die Sie das int eingegeben haben) speichern konnten string1. Ich werde nur ein bisschen mehr Licht auf das gesamte Thema werfen.

Betrachten Sie nextLine () als die ungerade unter den nextFoo () -Methoden in der Scanner-Klasse. Nehmen wir ein kurzes Beispiel. Nehmen wir an, wir haben zwei Codezeilen wie die folgenden:

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

Wenn wir den folgenden Wert eingeben (als einzelne Eingabezeile)

54 234

Der Wert von our firstNumberund secondNumbervariable wird zu 54 bzw. 234. Der Grund, warum dies so funktioniert, ist, dass ein neuer Zeilenvorschub ( dh \ n ) NICHT automatisch generiert wird, wenn die nextInt () -Methode die Werte aufnimmt. Es nimmt einfach das "nächste int" und geht weiter. Dies gilt auch für die übrigen nextFoo () -Methoden mit Ausnahme von nextLine ().

nextLine () generiert unmittelbar nach der Eingabe eines Werts einen neuen Zeilenvorschub. Dies ist, was @RohitJain bedeutet, wenn gesagt wird, dass der neue Zeilenvorschub "verbraucht" ist.

Schließlich nimmt die next () -Methode einfach den nächsten String, ohne eine neue Zeile zu generieren. Dies macht dies zur bevorzugten Methode, um separate Zeichenfolgen innerhalb derselben einzelnen Zeile zu erstellen.

Ich hoffe das hilft .. Fröhliche Codierung!

5 NeerajGahlawat Jul 30 2017 at 10:48
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);
    }
5 HarshShah Jan 17 2019 at 02:24

Verwenden Sie 2 Scannerobjekte anstelle von einem

Scanner input = new Scanner(System.in);
System.out.println("Enter numerical value");    
int option;
Scanner input2 = new Scanner(System.in);
option = input2.nextInt();
4 Kaplan Oct 02 2019 at 00:20

wenn ich eine nicht leere Eingabe erwarte

public static Function<Scanner,String> scanLine = (scan -> {
    String s = scan.nextLine();
    return( s.length() == 0 ? scan.nextLine() : s );
  });


im obigen Beispiel verwendet:

System.out.println("Enter numerical value");    
int option = input.nextInt(); // read numerical value from input

System.out.println("Enter 1st string"); 
String string1 = scanLine.apply( input ); // read 1st string
System.out.println("Enter 2nd string");
String string2 = scanLine.apply( input ); // read 2nd string
4 Giri Jan 24 2020 at 18:32

In einem meiner Anwendungsfälle hatte ich das Szenario, einen Zeichenfolgenwert zu lesen , dem einige ganzzahlige Werte vorangestellt waren . Ich musste eine " for / while-Schleife " verwenden, um die Werte zu lesen. Und keiner der oben genannten Vorschläge hat in diesem Fall funktioniert.

Verwenden input.next()statt input.nextLine()beheben das Problem. Ich hoffe, dies könnte für diejenigen hilfreich sein, die sich mit einem ähnlichen Szenario befassen.

4 SandeepKumar Dec 18 2019 at 16:08

Da nextXXX()Methoden nicht lesen newline, außer nextLine(). Wir können das newlinenach dem Lesen eines beliebigen non-stringWertes ( intin diesem Fall) überspringen, indem wir scanner.skip()Folgendes verwenden:

Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(x);
double y = sc.nextDouble();
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(y);
char z = sc.next().charAt(0);
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(z);
String hello = sc.nextLine();
System.out.println(hello);
float tt = sc.nextFloat();
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(tt);
2 JeewanthaLahiru Mar 08 2020 at 22:19

Verwenden Sie diesen Code, um Ihr Problem zu beheben.

System.out.println("Enter numerical value");    
int option;
option = input.nextInt(); // Read numerical value from input
input.nextLine();
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)
TobiasJohansson Mar 13 2015 at 18:06

Warum nicht für jede Lesung einen neuen Scanner verwenden? Wie unten. Mit diesem Ansatz werden Sie Ihr Problem nicht konfrontieren.

int i = new Scanner(System.in).nextInt();
PallavKhare Nov 22 2020 at 13:59

Das Problem liegt bei der Methode input.nextInt (), die nur den Wert int liest. Wenn Sie also mit input.nextLine () weiterlesen, erhalten Sie die Eingabetaste "\ n". Um dies zu überspringen, müssen Sie die input.nextLine () hinzufügen. Hoffe das sollte jetzt klar sein.

Versuchen Sie es so:

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();