Scanner Skipt NEXTSLINE () na gebruik van volgende () of nextfoo ()?

Ik gebruik de Scannermethoden nextInt()en nextLine()voor het lezen van invoer.

Het ziet er als volgt uit:

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)

Het probleem is dat na het invoeren van de numerieke waarde de eerste input.nextLine()wordt overgeslagen en de tweede input.nextLine()wordt uitgevoerd, zodat mijn uitvoer ziet er als volgt uit:

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

Ik heb mijn applicatie getest en het lijkt erop dat het probleem ligt in het gebruik van input.nextInt(). Als ik het verwijder, dan string1 = input.nextLine()en string2 = input.nextLine()worden uitgevoerd zoals ik wil dat ze zijn.


1, Autoriteit 100%

Dat komt omdat de Scanner.nextInt-methode leest het teken newlineniet in uw invoer die is gemaakt door op “Enter” te drukken, dus de aanroep naar Scanner.nextLineretourneert na het lezen van die nieuwe regel.

U zult hetzelfde gedrag tegenkomen wanneer u Scanner.nextLinegebruikt na Scanner.next()of een Scanner.nextFoo-methode (behalve nextLinezelf).

Oplossing:

  • Plaats een Scanner.nextLine-aanroep na elke Scanner.nextIntof Scanner.nextFooom de rest van die regel te gebruiken, inclusief nieuwe regel

    int option = input.nextInt();
    input.nextLine();  // Consume newline left-over
    String str1 = input.nextLine();
    
  • Of, nog beter, lees de invoer via Scanner.nextLineen converteer uw invoer naar het juiste formaat dat u nodig heeft. U kunt bijvoorbeeld converteren naar een geheel getal met Integer.parseInt(String)methode.

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

Antwoord 2, autoriteit 24%

Het probleem is met de -invoer.Nextint () methode – het leest alleen de int-waarde. Dus wanneer u doorgaat met input.volgline () ontvangt u de “\ n” -toets. Dus om dit over te slaan, moet je de Input.volgline () toevoegen. Ik hoop dat dit nu duidelijk moet zijn.

Probeer het zo:

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

3, Autoriteit 9%

Het is omdat wanneer u een nummer invoert en vervolgens op invoeren , input.nextInt()verbruikt alleen het nummer, niet het "Einde van de lijn". Wanneer input.nextLine()uitvoert, verbruikt het het "einde van de lijn" nog in de buffer van de eerste ingang.

Gebruik in plaats daarvan input.nextLine()onmiddellijk na input.nextInt()


4, Autoriteit 5%

Er lijken veel vragen te zijn over dit probleem met java.util.Scanner. Ik denk dat een meer leesbare / idiomatische oplossing zou zijn om scanner.skip("[\r\n]+")om eventuele nieuwlijntekens te laten vallen na het bellen van nextInt().

EDIT: als @patrickparker hieronder vermeld, zal dit een oneindige lus veroorzaken als de gebruiker na het nummer een witruimte invoert. Zie hun antwoord voor een beter patroon om te gebruiken met Skip: https://stackoveroverflow.com/a/42471816/143585


5, Autoriteit 4%

Het doet dat omdat input.nextInt();niet vangt de nieuwlijn. Je zou kunnen doen als de anderen die worden voorgesteld door een input.nextLine();eronder.
Als alternatief kunt u het C # Style doen en een nummers op een geheel getal vinden, zoals SO:

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

Dit werkt ook net zo goed, en het bespaart u een regel van code.


6, Autoriteit 2%

In plaats van input.nextLine()Gebruik input.next(), die het probleem moet oplossen.

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

7, Autoriteit 2%

Als je zowel strings als ints wilt lezen, is een oplossing om twee scanners te gebruiken:

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

Antwoord 8

Als u invoer snel wilt scannen zonder in de war te raken met de methode Scanner class nextLine() , gebruik dan Custom Input Scanner daarvoor .

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

Voordelen:

  • Scans invoeren sneller dan bufferreder
  • vermindert de tijdcomplexiteit
  • flushes buffer voor elke volgende ingang

Methoden:

  • Scanchar () - Single Character
  • SCANINT () - Getinale waarde Scan
  • ScanLong () - Scan Long-waarde
  • ScantRing () - Scan String-waarde
  • Scandouble () - Scan dubbele waarde
  • Scanint (int [] array) - Scans complete array (integer)
  • ScanLong (Long [] array) - Scans complete array (lang)

Gebruik:

  1. Kopieer de gegeven code onder uw Java-code.
  2. Initialiseer object voor de gegeven klasse

ScanReader sc = new ScanReader(System.in);

3. Importeer de nodige klassen:

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;

4. Gooi IoException van uw hoofdmethode om uitzondering te verwerken
5. Gebruik verstrekte methoden.
6. Geniet

Voorbeeld:

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....

9

Om het probleem te voorkomen, gebruik nextLine();onmiddellijk na nextInt();omdat dit helpt bij het opruimen van de buffer. Wanneer u op ENTERdrukt, neemt de nextInt();de nieuwe regel niet op en slaat daarom de Scanner-code later over.

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

Antwoord 10

sc.nextLine()is beter in vergelijking met het ontleden van de invoer.
Omdat het qua prestaties goed zal zijn.


Antwoord 11

Ik denk dat ik vrij laat op het feest ben..

Zoals eerder vermeld, zal het aanroepen van input.nextLine()na het verkrijgen van uw int-waarde uw probleem oplossen. De reden waarom je code niet werkte, was omdat er niets anders was om op te slaan van je invoer (waar je de int invoerde) in string1. Ik zal wat meer licht werpen op het hele onderwerp.

Beschouw nextLine()als de vreemde eend in de bijt van de nextFoo()methoden in de Scanner-klasse. Laten we een snel voorbeeld nemen. Laten we zeggen dat we twee regels code hebben, zoals hieronder:

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

Als we de onderstaande waarde invoeren (als een enkele invoerregel)

54 234

De waarde van onze firstNumberen secondNumbervariabele wordt respectievelijk 54 en 234. De reden waarom dit op deze manier werkt, is omdat een nieuwe regelinvoer (ie \n) NIETautomatisch wordt gegenereerd wanneer de methode nextInt() in de waarden. Het neemt gewoon de "next int"en gaat verder. Dit is hetzelfde voor de rest van de nextFoo()-methoden, behalve nextLine().

nextLine() genereert een nieuwe regelinvoer onmiddellijk na het nemen van een waarde; dit is wat @RohitJain bedoelt door te zeggen dat de nieuwe regelfeed "geconsumeerd" is.

Ten slotte neemt de methode next() gewoon de dichtstbijzijnde String zondereen nieuwe regel te genereren; dit maakt dit de voorkeursmethode voor het nemen van afzonderlijke Strings binnen dezelfde enkele regel.

Ik hoop dat dit helpt.. Vrolijk coderen!


Antwoord 12

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

Antwoord 13

als ik een niet-lege invoer verwacht

vermijdt:
–  verlies van gegevens als de volgende invoer wordt opgegeten door een niet-aangevinkte scan.nextLine()als tijdelijke oplossing
–  gegevensverlies door slechts gedeeltelijk gelezen regels omdat scan.nextLine()is vervangen door scan.next()(voer in: "yippie ya yeah" )
–  Exceptions die worden gegenereerd bij het parseren van invoer met Scanner-methoden (eerst lezen, daarna ontleden)

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

gebruikt in bovenstaand voorbeeld:

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

Antwoord 14

Gebruik 2 scannerobjecten in plaats van één

Scanner input = new Scanner(System.in);
System.out.println("Enter numerical value");    
int option;
Scanner input2 = new Scanner(System.in);
option = input2.nextInt();

Antwoord 15

In een van mijn usecases had ik het scenario van het lezen van een tekenreekswaarde voorafgegaan door een aantal gehele waarden. Ik moest een "for / while-lus" gebruiken om de waarden te lezen. En geen van de bovenstaande suggesties werkte in dit geval.

Het gebruik van input.next()in plaats van input.nextLine()loste het probleem op. Ik hoop dat dit nuttig kan zijn voor degenen die met een vergelijkbaar scenario te maken hebben.


Antwoord 16

Omdat nextXXX()methoden newlineniet lezen, behalve nextLine(). We kunnen de newlineoverslaan na het lezen van een non-stringwaarde (intin dit geval) door scanner.skip()zoals hieronder:

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

17

Gebruik deze code. Het zal uw probleem opstellen.

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)

18

Waarom niet een nieuwe scanner gebruiken voor elke lezing? Zoals hieronder. Met deze aanpak confronteert u niet uw probleem.

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

19

Het probleem is met de methode van de invoer.Nextint () - het leest alleen de int-waarde. Dus wanneer u doorgaat met input.volgline () ontvangt u de "\ n" -toets. Dus om dit over te slaan, moet je de input.volgline () toevoegen. Ik hoop dat dit nu duidelijk moet zijn.

Probeer het zo:

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

Antwoord 20

Om dit probleem op te lossen, maakt u gewoon een scan.nextLine(), waarbij scaneen instantie is van het Scanner-object. Ik gebruik bijvoorbeeld een eenvoudig HackerRank-probleem voor de uitleg.

package com.company;
import java.util.Scanner;
public class hackerrank {
public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    int i = scan.nextInt();
    double d = scan.nextDouble();
    scan.nextLine(); // This line shall stop the skipping the nextLine() 
    String s = scan.nextLine();
    scan.close();
    // Write your code here.
    System.out.println("String: " + s);
    System.out.println("Double: " + d);
    System.out.println("Int: " + i);
}

}

Other episodes