Sto usando i metodi Scanner
nextInt()
e nextLine()
per l’input di lettura.
Sembra questo:
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)
Il problema è che dopo aver inserito il valore numerico, il primo input.nextLine()
viene saltato e viene eseguito il secondo input.nextLine()
, in modo che il mio output assomigli a questo:
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
Ho provato la mia applicazione e sembra che il problema risieda nell’uso di input.nextInt()
. Se lo elimino, allora sia string1 = input.nextLine()
che string2 = input.nextLine()
vengono eseguiti come voglio che siano.
Questo perché il metodo Scanner.nextInt
non consuma l’ ultimo carattere di nuova riga del tuo input, e quindi quella nuova riga viene consumata nella prossima chiamata a Scanner.nextLine
.
Si verificherà un comportamento simile quando si utilizza Scanner.nextLine
dopo Scanner.next()
o qualsiasi metodo Scanner.nextFoo
(ad eccezione di nextLine
stesso).
Soluzione:
Esegui una chiamata Scanner.nextLine
vuota dopo Scanner.nextInt
o Scanner.nextFoo
per consumare il resto di tale linea, incluso newline
int option = input.nextInt(); input.nextLine(); // Consume newline left-over String str1 = input.nextLine();
Oppure, sarebbe ancora meglio se leggi l’input tramite Scanner.nextLine
e converti l’input nel formato corretto di cui hai bisogno. Ad esempio, a un intero che utilizza il metodo Integer.parseInt(String)
.
int option = 0; try { option = Integer.parseInt(input.nextLine()); } catch (NumberFormatException e) { e.printStackTrace(); } String str1 = input.nextLine();
Il problema è con il metodo input.nextInt () – legge solo il valore int. Quindi quando continui a leggere con input.nextLine () ricevi il tasto “\ n” Invio. Quindi per saltare questo devi aggiungere l’ input.nextLine () . Spero che questo dovrebbe essere chiaro ora.
Provalo così:
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();
È perché quando inserisci un numero, premi Invio , input.nextInt()
consuma solo il numero, non il “fine della riga”. Quando input.nextLine()
eseguito input.nextLine()
, esso consuma la “fine della riga” ancora nel buffer dal primo input.
Utilizzare invece input.nextLine()
immediatamente dopo input.nextInt()
Sembra che ci siano molte domande su questo problema con java.util.Scanner
. Penso che una soluzione più leggibile / idiomatica sarebbe chiamare scanner.skip("[\r\n]+")
per eliminare qualsiasi carattere di nuova riga dopo aver chiamato nextInt()
.
EDIT: come indicato da @PatrickParker di seguito, ciò causerà un loop infinito se l’utente immette qualsiasi spazio bianco dopo il numero. Vedi la loro risposta per un modello migliore da usare con skip: https://stackoverflow.com/a/42471816/143585
Lo fa perché input.nextInt();
non cattura la nuova riga. potresti fare come gli altri proposti aggiungendo un input.nextLine();
sotto.
In alternativa puoi farlo in stile C # e analizzare un nextLine in un intero in questo modo:
int number = Integer.parseInt(input.nextLine());
Fare questo funziona altrettanto bene e ti fa risparmiare una riga di codice.
Cose che devi sapere:
il testo che rappresenta poche righe contiene anche caratteri non stampabili tra linee (noi li chiamiamo separatori di linee) come
"\r"
) "\n"
) quando stai leggendo i dati dalla console, consente all’utente di digitare la sua risposta e quando ha finito ha bisogno di confermare in qualche modo quel fatto. Per fare ciò, l’utente deve premere il tasto “invio” / “ritorno” sulla tastiera.
Ciò che è importante è che questo tasto oltre a garantire l’immissione dei dati utente sullo standard input (rappresentato da System.in
che viene letto da Scanner
) invia anche i separatori di riga dipendenti dal SO (come per Windows \r\n
) dopo di esso.
Pertanto, quando si chiede all’utente valori come age
e tipi di utente 42 e si preme Invio, l’input standard conterrà "42\r\n"
.
Scanner#nextInt
(e altri metodi del Scanner#next Type
Scanner#nextInt
Scanner#next Type
) non consente a Scanner di consumare questi separatori di riga. Li leggerà da System.in
(in quale altro modo Scanner potrebbe sapere che non ci sono più cifre da parte dell’utente che rappresentano il valore age
rispetto agli spazi bianchi?) Che li rimuoverà dall’input standard, ma memorizzerà internamente anche i separatori di riga . Quello che dobbiamo ricordare, è che tutti i metodi dello scanner sono sempre in scansione a partire dal testo memorizzato nella cache.
Now Scanner#nextLine()
semplicemente raccoglie e restituisce tutti i caratteri fino a quando non trova i separatori di riga (o la fine del stream). Ma poiché i separatori di riga dopo aver letto il numero dalla console si trovano immediatamente nella cache dello Scanner, restituiscono String vuota, ovvero Scanner non è stato in grado di trovare alcun carattere prima di questi separatori di riga (o fine del stream).
BTW nextLine
consuma anche quei separatori di linea.
Quindi quando vuoi chiedere il numero e poi per l’intera riga evitando quella stringa vuota come risultato di nextLine
, neanche
nextInt
dalla cache degli scanner di
nextLine
, skip("\\R")
per lasciare che Scanner salvi la parte abbinata a \R
che rappresenta il separatore di riga (maggiori informazioni su \R
: https://stackoverflow.com/a/31060125 ) nextInt
(né next
o nextTYPE
). Piuttosto, leggi interi dati riga per riga usando nextLine
e analizza i numeri da ogni riga (assumendo che una riga contenga un solo numero) al tipo corretto come int
tramite Integer.parseInt
. BTW : Scanner#next Type
metodi Scanner#next Type
possono saltare i delimitatori (per impostazione predefinita tutti gli spazi bianchi come tabs, separatori di riga) inclusi quelli memorizzati nello scanner, fino a quando non troveranno il successivo valore non delimitatore (token). Grazie a quello per l’input come il codice "42\r\n\r\n321\r\n\r\n\r\nfoobar"
int num1 = sc.nextInt(); int num2 = sc.nextInt(); String name = sc.next();
sarà in grado di assegnare correttamente num1=42
num2=321
name=foobar
.
Invece di input.nextLine()
usa input.next()
, questo dovrebbe risolvere il problema.
Codice modificato:
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(); }
Per evitare il problema, usa nextLine();
immediatamente dopo nextInt();
come aiuta a chiarire il buffer. Quando si preme ENTER
il nextInt();
non acquisisce la nuova riga e quindi salta il codice dello Scanner
secondo momento.
Scanner scanner = new Scanner(System.in); int option = scanner.nextInt(); scanner.nextLine(); //clearing the buffer
Se si desidera eseguire la scansione veloce dell’input senza confondersi con il metodo nextLine () della class Scanner, utilizzare Custom Input Scanner per questo.
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; } }
ScanReader sc = new ScanReader(System.in);
3. Importare le classi necessarie:
import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream;
4. Lanciare IOException dal metodo principale per gestire Eccezione 5. Utilizzare i metodi forniti. 6. Divertiti
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....
Se si desidera leggere stringhe e stringhe, una soluzione consiste nell’utilizzare due scanner:
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()
è migliore rispetto sc.nextLine()
dell’input. Perché le prestazioni saggi saranno buone.
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); }
Il mio test ha prodotto gli stessi risultati di Prine, tuttavia ho pensato a una soluzione abbastanza semplice:
Usando BufferedReader#nextLine()
, dove si dovrebbe Scanner#readLine()
, evita questo bug. Si potrebbe anche scrivere il proprio wrapper Scanner per sovrascrivere la funzione readLine dello scanner con la funzione nextLine di BufferedReader.
Immagino di essere in ritardo per la festa ..
Come precedentemente affermato, la chiamata a input.nextLine()
dopo aver ottenuto il valore int risolverà il problema. Il motivo per cui il tuo codice non ha funzionato era perché non c’era nient’altro da memorizzare dal tuo input (dove hai immesso l’int) in string1
. Farò solo un po ‘più di luce sull’intero argomento.
Considera nextLine () come il dispari tra i metodi nextFoo () nella class Scanner. Facciamo un esempio veloce. Diciamo che abbiamo due righe di codice come quelle qui sotto:
int firstNumber = input.nextInt(); int secondNumber = input.nextInt();
Se inseriamo il valore sotto (come una singola riga di input)
54 234
Il valore della variabile firstNumber
e secondNumber
diventa rispettivamente 54 e 234. Il motivo per cui questo funziona in questo modo è perché un nuovo feed di riga ( cioè \ n ) NON viene generato automaticamente quando il metodo nextInt () accetta i valori. Prende semplicemente il “prossimo int” e procede. Questo è lo stesso per il resto dei metodi nextFoo () tranne nextLine ().
nextLine () genera un nuovo feed di riga immediatamente dopo aver preso un valore; questo è ciò che @RohitJain intende dicendo che il nuovo feed di riga è “consumato”.
Infine, il metodo next () prende semplicemente la Stringa più vicina senza generare una nuova linea; questo rende questo il metodo preferenziale per prendere Stringhe separate all’interno della stessa linea singola.
Spero che questo aiuti .. Buon codice!
Perché non utilizzare un nuovo scanner per ogni lettura? Come sotto Con questo approccio non affronterai il tuo problema.
int i = new Scanner(System.in).nextInt();