Der Scanner überspringt nextLine (), nachdem next () oder nextFoo () verwendet wurden.
Ich benutze die Scanner
Methoden 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
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.nextLine
after Scanner.next()oder eine andere Scanner.nextFoo
Methode (außer sich nextLine
selbst) verwenden.
Problemumgehung:
Setzen entweder einen
Scanner.nextLine
Anruf nach jedemScanner.nextInt
oderScanner.nextFoo
zu konsumieren Rest der Zeile einschließlich Newlineint option = input.nextInt(); input.nextLine(); // Consume newline left-over String str1 = input.nextLine();
Oder, noch besser, lesen Sie die Eingabe durch
Scanner.nextLine
und 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();
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();
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()
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
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.
TL; DR Verwendung scanner.skip("\\R")
vor jedem scanner.newLine()
Aufruf, der ausgeführt wird nach:
scanner.next()
scanner.next*TYPE*()
Methode, wiescanner.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.in
die 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 age
und 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#nextType
System.in
age
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 nextLine
auch 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
nextInt
von Scanner-Cache von - anrufen
nextLine
, - oder IMO besser lesbar wäre, wenn Sie anrufen
skip("\\R")
oderskip("\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
(nochnext
oder keinenextTYPE
Methoden) überhaupt nicht. Lesen Sie stattdessen die gesamten Daten Zeile für Zeile mitnextLine
und analysieren Sie die Nummern aus jeder Zeile (vorausgesetzt, eine Zeile enthält nur eine Nummer), um den richtigen Typ wieint
via zu erhaltenInteger.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
.
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();
}
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();
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 :
- Kopieren Sie den angegebenen Code unter Ihren Java-Code.
- 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....
Um das Problem zu vermeiden, verwenden Sie es nextLine();
sofort danach, nextInt();
da es beim Löschen des Puffers hilft. Wenn Sie drücken ENTER
die nextInt();
nicht die neue Linie erfassen und daher überspringt die Scanner
später Code.
Scanner scanner = new Scanner(System.in);
int option = scanner.nextInt();
scanner.nextLine(); //clearing the buffer
sc.nextLine()
ist besser als das Parsen der Eingabe. Weil es in Bezug auf die Leistung gut sein wird.
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 firstNumber
und secondNumber
variable 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!
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);
}
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();
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
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.
Da nextXXX()
Methoden nicht lesen newline
, außer nextLine()
. Wir können das newline
nach dem Lesen eines beliebigen non-string
Wertes ( int
in 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);
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)
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();
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();