Ich habe das Verhalten von Java Scanner und .nextLine () nicht wirklich verstanden.

Der Anfang der Sache

Schreiben Sie solchen Code in Java

Main1.java


import java.util.*;

/**
 * Created 2017/05/23.
 */

public class Main1 {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    ArrayList<String> ary = new ArrayList<String>();
    int num = sc.nextInt();
    for (int i = 0; i < num; i++) {
      String word = sc.nextLine();
      ary.add(word);
    }
    System.out.println(ary);
  }
}

Oft in Programmwettbewerben 1: Zuerst eine Zahleneingabe erhalten Erhalten Sie mehr Eingaben für die Anzahl der 2: 1 eingegebenen Male Eingabewert von 3: 2 auf verschiedene Arten Weil ich so ein Programm brauchte Geben Sie die Häufigkeit ein → Schreiben Sie den eingegebenen String in Form einer Speicherung in ArrayList Das Ergebnis dieser Ausführung ist jedoch seltsam

Eingegebener Wert
2
a
b (kann nicht eintreten)

Ausführungsergebnis
[, a]

Ein mysteriöser Rohling? Ich war in einer Situation, in der ich mich befand, also beschloss ich, die Ursache zu untersuchen ...

Zunächst einmal, um die Spezifikationen von .nextLine () zu verstehen.

Lassen Sie uns zunächst die Spezifikationen mit der Referenz erfassen https://docs.oracle.com/javase/jp/8/docs/api/java/util/Scanner.html#nextLine--

nextLine

public String nextLine() Bringt den Scanner in die aktuelle Zeile und gibt übersprungene Eingaben zurück. Diese Methode gibt den Rest der aktuellen Zeile mit Ausnahme des letzten Zeilenumbruchs zurück. Die Position wird am Anfang der nächsten Zeile festgelegt. Diese Methode sucht weiterhin nach Zeilenumbrüchen in der Eingabe. Wenn also keine Zeilenumbrüche vorhanden sind, werden möglicherweise alle Eingaben gepuffert, die nach zu überspringenden Zeilen suchen. Rückgabewert: Übersprungene Zeilen Ausnahme: NoSuchElementException - wenn keine Zeile gefunden wird IllegalStateException - wenn dieser Scanner geschlossen ist


~~ Ja, ich weiß nicht wovon du sprichst ~~ Infolge verschiedener Untersuchungen vorerst -.NextLine () liest auch Leerzeichen (Leerzeilen) Ich habe das verstanden Aber diesmal stoße ich auf die Frage, woher die Leerzeichen (Leerzeilen) kommen.

Untersuchen Sie das tatsächliche Verhalten nacheinander

Zum Überprüfen durch Schreiben des Quellcodes während des tatsächlichen Überprüfens (es ist viel schneller, die Hand zu bewegen, als sich um den Kopf zu sorgen) Die Reihenfolge der Dateinamen im Quellcode ist nicht in der richtigen Reihenfolge. Beachten Sie jedoch, dass dies das Ergebnis verschiedener Versuche ist. ~~ Ich kann das nicht nur mit der Referenz lesen ... ~~

Lassen Sie uns zunächst einen kurzen Blick auf das Verhalten von Scanner und .nextLine () werfen.

Verhalten von Scanner und .nextLine ()

Main5

Main5.java


import java.util.Scanner;

/**
 * Created 2017/05/25.
 *Das Verhalten von nextLine
 */
public class Main5 {
   public static void main(String[] args) {
      String word = "123 test";
      Scanner sc = new Scanner(word);
      String line = sc.nextLine();

      System.out.println(word);
      //Ausführungsergebnis:123 test
      System.out.println(line);
      //Ausführungsergebnis:123 test
   
   }
}
Ausführungsergebnis
123 test
123 test

Das ist sehr leicht zu verstehen

Main6 Als nächstes werde ich mehrere Scans versuchen

Main6.java


import java.util.Scanner;

/**
 * Created 2017/05/25.
 */
public class Main6 {
  public static void main(String[] args){
    String word = "123 test";
    Scanner sc = new Scanner(word);
    int num     = sc.nextInt(); 
    String line = sc.nextLine();

    System.out.println(word);
    //Ausführungsergebnis:123test

    System.out.println(num);
    //Ausführungsergebnis: 123
    
    System.out.println(line);
    //Ausführungsergebnis: test

  }
}

Ausführungsergebnis
123 test
123
 test

Was ich hier beachten möchte, ist das Ausgabeergebnis von line. Wenn Sie .nextLine () ausführen, nachdem Sie .nextInt () ausgeführt haben, wurde der Nummernteil bereits gelesen. Sie können sehen, dass nur noch Blank + Test übrig bleibt

Was ist, wenn Sie .nextLine () ausführen, nachdem Sie alles gelesen haben? Lass es uns versuchen!

Main7

Main7.java


import java.util.Scanner;

/**
 * Created 2017/05/25.
 */
public class Main7 {
  public static void main(String[] args){
    String word = "123 test";
    Scanner sc = new Scanner(word);
    int num     = sc.nextInt();
    String word2 = sc.next();
    
    //String line = sc.nextLine();
    //Ich bekomme einen Fehler richtig
    //Exception in thread "main" java.util.NoSuchElementException: No line found

    System.out.println(word);
    //Ausführungsergebnis:123test

    System.out.println(num);
    //Ausführungsergebnis: 123

    System.out.println(word2);
    //Ausführungsergebnis:test

    //System.out.println(line);
    //Ausführungsergebnis:Wird aufgrund des obigen Fehlers überhaupt nicht ausgeführt

  }
}
Ausführungsergebnis 1
123 test
123
test

Obwohl es im Kommentar geschrieben ist, tritt ein Fehler auf, wenn Sie .nextLine () auskommentieren und ausführen.

Ausführungsergebnis 2(.nextLine();Kommentar abgeben und ausführen)
Exception in thread "main" java.util.NoSuchElementException: No line found
	at java.util.Scanner.nextLine(Scanner.java:1540)
	at Java.Nexts.Main7.main(Main7.java:15)

Dies enthüllt nicht die Wahrheit ... Es wird ein Fehler wie "Es gibt keine Leitung!" Zurückgegeben. Wenn Sie jedoch ein wenig hinzufügen, verschwindet der Fehler.

Main8

Main8.java


import java.util.Scanner;

/**
 * Created 2017/05/25.
 */
public class Main8 {
  public static void main(String[] args){
    String word = "123 test\n";
    Scanner sc = new Scanner(word);
    int num     = sc.nextInt();

    String word2 = sc.next();

    String line = sc.nextLine();
  
    System.out.println(word);//
    //Ausführungsergebnis:123test
    //
    //Oben befindet sich ein Leerzeichen (Trennlinie)
    
    System.out.println(num);
    //Ausführungsergebnis: 123

    System.out.println(word2);
    //Ausführungsergebnis:test

    System.out.println(line);
    //Ausführungsergebnis: (Leer)
    //Es ist leer, aber es liest tatsächlich eine leere Zeile, was nicht bedeutet, dass die Zeile nicht existiert → es wird kein Fehler ausgegeben!
    //System hier.out.println(line);Es ist sehr leicht zu verstehen, wenn Sie es mit angehängtem Debug ausführen!

  }
}
Ausführungsergebnis
123 test

123
test

Ja das ist die Wahrheit Fügen Sie den Zeilenvorschubcode "\ n" am String-Wort hinzu. Nach dem Scannen bis zu Wort2 bleiben dann im Gegensatz zu Main7 Zeilenumbrüche bestehen. String line = sc.nextLine (); liest als Zeilenumbruch (leere Zeile) Infolgedessen enthält die Zeile leere Zeichen.

Dies kann visuell mithilfe der Debug-Funktion der IDE angezeigt werden. nextline.png Sie können sehen, dass in der Zeile ein "" steht

Also, was war los?

Jetzt können Sie endlich sehen, ob sich der Main1-Code seltsam verhalten hat 1: Wenn Sie einen numerischen Wert eingeben, wird nach dem Drücken von 2 und Drücken der Eingabetaste zunächst "2 \ n" in den sc-Inhalt eingegeben. Beim Scannen mit 2: int num = sc.nextInt (); wird num = 2 gespeichert und der Inhalt von sc ist nur "\ n". 3: Nach dem Starten der Schleife liest String word = sc.nextLine (); liest den aktuell verbleibenden sc-Inhalt "\ n" Als leeres Zeichen in ary speichern 4: Der Inhalt von sc ist leer, also lesen und speichern Sie die neue Eingabe "a" hier. 5: Zu diesem Zeitpunkt stoppt die Schleife, da der Vorgang zweimal ausgeführt wird. 6: Der Inhalt von ary wird [, a]

Abschließend -Scanner gibt den Wert des aktuellen Speicherorts zurück (der Teil, in dem der Inhalt verbleibt). -.NextLine () liest auch Leerzeilen Es war ein Problem, das in der kombinierten Technik von auftrat

Wie kommt man dann zur idealen Bewegung?

Die grundlegende Lösung besteht darin, zwei Scanner zu erstellen Auf diese Weise müssen Sie das Wrack bei der Eingabe von Zahlen nicht lesen.

Main4.java


import java.util.ArrayList;
import java.util.Scanner;

/**
 * Created 2017/05/25.
 *Das Gefühl, dass die Ursache endlich verstanden wurde
 */
public class Main4 {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    Scanner sc2 = new Scanner(System.in);
    ArrayList<String> ary = new ArrayList<String>();
    int num = sc.nextInt();
    for (int i = 0; i < num; i++) {
      String word = sc2.nextLine();
      ary.add(word);
    }
    System.out.println(ary);
  }
Eingang
2
a
b
Ausführungsergebnis
[a, b]

Es ist perfekt!

Wenn Sie wissen, dass die eingegebene Zeichenfolge nicht durch Leerzeichen getrennt ist Sie können das gleiche Ergebnis erzielen, indem Sie einfach .next () verwenden.

Main2.java


import java.util.*;

/**
 * Created 2017/05/23.
 */
public class Main2 {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    ArrayList<String> ary = new ArrayList<String>();
    int num = sc.nextInt();
    for (int i = 0; i < num; i++) {
      String word = sc.next();
      ary.add(word);
    }
    System.out.println(ary);
  }
}
Eingang
2
a
b
Ausführungsergebnis
[a, b]

Beachten Sie jedoch, dass sich der Main2-Code möglicherweise unbeabsichtigt verhält, wenn Sie einen durch Leerzeichen getrennten Satz eingeben.

2
a b c
Ausführungsergebnis
[a, b]

Nachtrag vom 25.05.2017 Ich habe eine intelligentere Lösung in den Kommentaren

Main9.java


import java.util.ArrayList;
import java.util.Scanner;

/**
 * Created 2017/05/25.
 *Bitten Sie Qiita, Ihnen einen intelligenteren Weg beizubringen
 */
public class Main9 {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    ArrayList<String> ary = new ArrayList<String>();
    int num = Integer.parseInt(sc.nextLine());    //Integer.Einmal mit parseInt in eine vollständige Zahl konvertiert, kann sie von nextLine gelesen werden!
    for (int i = 0; i < num; i++) {
      String word = sc.nextLine();
      ary.add(word);
    }
    System.out.println(ary);
  }
}
Eingang
2
a
b
Ausführungsergebnis
[a, b]

Zunächst behandelt .nextLine () das Leseergebnis als String-Typ. aus diesem Grund int num = sc.nextLine(); Wenn du so schreibst wie es ist Fehler: (13, 26) java: Inkompatibler Typ: java.lang.String kann nicht in int konvertiert werden: Und geben Sie Inkonsistenzen ein und können nicht in int num gespeichert werden jedoch int num = Integer.parseInt(sc.nextLine()); Durch Schreiben kann der von .nextLine () gelesene Wert in einen numerischen Wert konvertiert werden, so dass er in int num gespeichert werden kann! Diese Schreibweise erfordert nicht mehrere Scanner Außerdem ist es so, als würde man für jede eingegebene Zeile ".nextLine ()" aufrufen, was den Code sehr einfach verständlich macht.

Impressionen

~~ Java ist problematisch ~~ Spaß beiseite Ich möchte → Scanner sc = neuer Scanner (System.in); eingeben Ich möchte Zeile für Zeile lesen → .nextLine (); Es ist nicht zu leugnen, dass es eine kopierähnliche Idee gab, die Sie verwenden sollten. Dieses Mal verstand ich gut, dass ich ein grundlegendes Verständnis von Scanner hatte. Es gibt noch viele Dinge, die ich über Java nicht verstehe, deshalb würde ich gerne weiter hart lernen.

2018/01/19 Als ich es nach langer Zeit wieder las, machte ich mir Sorgen, also korrigierte ich eines Sie müssen keinen neuen Scanner erstellen. Scannen Sie die Rohlinge nur einmal, und es funktioniert einwandfrei.

ScanSample.java


import java.util.ArrayList;
import java.util.Scanner;

/**
 * Created 2018/01/19.
 *Korrektur
 */
public class ScanSample {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    ArrayList<String> ary = new ArrayList<String>();
    int num = sc.nextInt();
    String blank = sc.nextLine();
    for (int i = 0; i < num; i++) {
      String word = sc.nextLine();
      ary.add(word);
    }
    System.out.println(ary);
  }
}
Eingang
2
a
b
Ausführungsergebnis
[a, b]

Recommended Posts

Ich habe das Verhalten von Java Scanner und .nextLine () nicht wirklich verstanden.
Ich habe die Eigenschaften von Java und .NET verglichen
Informationen zu next () und nextLine () der Scannerklasse
Ich habe die Typen und Grundlagen von Java-Ausnahmen zusammengefasst
Ich habe versucht, die Grundlagen von Kotlin und Java zusammenzufassen
Java-Anfänger fassten das Verhalten von Array und ArrayList kurz zusammen
[Java] Ich habe über die Vorzüge und Verwendungen von "Schnittstelle" nachgedacht.
Ich habe versucht, die Methoden von Java String und StringBuilder zusammenzufassen
Informationen zur Funktionsweise von next () und nextLine ()
[Tag: 5] Ich habe die Grundlagen von Java zusammengefasst
[Java] [Spring] Testen Sie das Verhalten des Loggers
Ich habe versucht, die Grammatik von R und Java zu übersetzen [Von Zeit zu Zeit aktualisiert]
[Java] Verstehe den Unterschied zwischen List und Set
Durch die Überprüfung der Funktionsweise von Java unter Linux konnte ich die Kompilierung und Hierarchie verstehen.
Unterschied zwischen next () und nextLine () in Java Scanner
[Java] Der verwirrende Teil von String und StringBuilder
Probieren Sie Progate Free Edition [Java I]
Ich habe die Daten der Reise (Tagebuchanwendung) in Java erhalten und versucht, sie # 001 zu visualisieren
Zusammenfassung des ToString-Verhaltens mit Java- und Groovy-Annotationen
Bitte beachten Sie die Aufteilung (Aufteilung) von Java Kotlin Int und Int
Der Vergleich von enum ist == und gleich ist gut [Java]
[Für Anfänger] Verstehen Sie schnell die Grundlagen von Java 8 Lambda
Den aktuellen Status von Java organisieren und die Zukunft betrachten
Java-Sprache aus der Sicht von Kotlin und C #
Überprüfen Sie das Verhalten von Java Intrinsic Locks mit bpftrace
In der Abbildung verstandene Java-Klassen und -Instanzen
[Hinweis] Java Ausgabe der Summe von ungeraden und geraden Elementen
Befehl zum Überprüfen der Anzahl und des Status von Java-Threads
Verstehen Sie das Singleton-Muster, indem Sie Java- und JavaScript-Code vergleichen
Was soll ich nach Januar 2019 in Bezug auf die Ausgabe der Java-Zahlung und die Ausgabe des Java 8-Endes des Supports tun?
Ich habe JAX-RS ausprobiert und mir das Verfahren notiert
[Java] Ich habe versucht, die Kombination zu implementieren.
Vor- und Nachteile von Java
Bei der Java-Parallelverarbeitung bin ich mir nicht sicher
Verstehen Sie das Iterator-Muster, indem Sie Java- und JavaScript-Code vergleichen
Ich habe den Konstruktor (Java) studiert.
[Aktionsansicht :: Fehlende Vorlage] Ich habe die Bedeutung der Fehleranweisung nicht verstanden und sie nachgeschlagen.
Ich habe die Bedeutung von DI oder @Autowired oder Injektion nicht verstanden, also habe ich nachgeschlagen.
[Java] Verschiedene Zusammenfassungen an die Leiter von Klassen und Mitgliedern
[Java] Ordnen Sie die Daten des vergangenen Montags und Sonntags der Reihe nach an
Ich möchte den Ablauf der Spring-Verarbeitungsanforderungsparameter verstehen
Die Geschichte, das Verhalten von String durch Passieren von Java nicht zu kennen
Ich möchte mit Kotlin und Java zum vorherigen Bildschirm zurückkehren!
Ich habe den Eingabe- / Ausgabetyp von Java Lambda ~ Map Edition ~ ausprobiert
Lesen Sie die ersten 4 Bytes der Java-Klassendatei und geben Sie CAFEBABE aus
Vom jungen Java (3 Jahre) bis zu Node.js (4 Jahre). Und der Eindruck, nach Java zurückzukehren
Seit ich Oracle Java Bronze bestanden habe, habe ich die Umrisse des Tests zusammengefasst.
Das Verhalten von JS auf Java SE 8 Nashorn änderte sich plötzlich
Über das Verhalten von Ruby Hash # ==
[Java] Löschen Sie die Elemente von List
Ich habe PHP- und Java-Konstruktoren verglichen
Verstehen Sie den grundlegenden Mechanismus von log4j2.xml
[java8] Um die Stream-API zu verstehen
Über Biocontainer fastqc und Java
[Java Edition] Geschichte der Serialisierung