Le Scanner saute nextLine() après avoir utilisé next () ou nextFoo ()?
j'utilise les Scanner
méthodes nextInt()
et nextLine()
pour lire l'entrée.
il ressemble à ceci:
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)
le problème est qu'après avoir entré la valeur numérique, le premier input.nextLine()
est sauté et le second input.nextLine()
est exécuté, de sorte que ma sortie ressemble à ceci:
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
j'ai testé mon application et il semble que le problème réside dans l'utilisation de input.nextInt()
. Si Je supprimer, puis les deux string1 = input.nextLine()
et string2 = input.nextLine()
sont exécutés comme je veux qu'ils soient.
15 réponses
c'est parce que la méthode Scanner.nextInt
ne consomme pas le caractère dernier newline de votre entrée, et donc que newline est consommé dans le prochain appel à Scanner.nextLine
.
vous rencontrerez le même comportement lorsque vous utilisez Scanner.nextLine
après Scanner.next()
ou toute méthode Scanner.nextFoo
(sauf nextLine
elle-même).
contournement:
-
soit lancer un blanc
Scanner.nextLine
appeler aprèsScanner.nextInt
ouScanner.nextFoo
pour consommer le reste de cette ligne, y compris newline 1519220920"int option = input.nextInt(); input.nextLine(); // Consume newline left-over String str1 = input.nextLine();
-
Ou, ce serait encore mieux, si vous lisez l'entrée
Scanner.nextLine
et de convertir votre entrée pour le format approprié vous avez besoin. Pour des exemples, à un entier en utilisantInteger.parseInt(String)
la méthode.int option = 0; try { option = Integer.parseInt(input.nextLine()); } catch (NumberFormatException e) { e.printStackTrace(); } String str1 = input.nextLine();
le problème est avec l'entrée .nextInt () méthode-il lit seulement la valeur int. Ainsi, lorsque vous continuer la lecture.nextLine () vous recevez la touche "\n" Enter. Donc, pour sauter ceci, vous devez ajouter l'entrée .nextLine () . Espérons que cela devrait être clair maintenant.
essayez comme ça:
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();
c'est parce que quand vous entrez un nombre puis appuyez sur entrer , input.nextInt()
consomme seulement le nombre, pas la"fin de ligne". Lorsque input.nextLine()
s'exécute, il consomme la" fin de ligne " toujours dans le tampon à partir de la première entrée.
à la place, utilisez input.nextLine()
immédiatement après input.nextInt()
il semble y avoir beaucoup de questions à ce sujet avec java.util.Scanner
. Je pense qu'une solution plus lisible / idiomatique serait d'appeler scanner.skip("[\r\n]+")
pour supprimer tous les caractères newline après avoir appelé nextInt()
.
EDIT: comme @PatrickParker noté ci-dessous, cela causera une boucle infinie si l'utilisateur entre n'importe quel espace après le nombre. Voir leur réponse pour un meilleur modèle à utiliser avec skip: https://stackoverflow.com/a/42471816/143585
il fait cela parce que input.nextInt();
ne capture pas la nouvelle ligne. vous pouvez faire comme les autres proposées en ajoutant un input.nextLine();
en dessous.
Alternativement vous pouvez le faire c # style et analyser un nextLine à un entier comme ainsi:
int number = Integer.parseInt(input.nextLine());
faire cela fonctionne aussi bien, et il vous sauve une ligne de code.
choses que vous devez savoir:
-
texte qui représente peu de lignes contient également des caractères non imprimables entre les lignes (nous les appelons séparateurs de ligne) comme
- retour de chariot (CR - dans les littéraux de Chaîne représentée comme
"\r"
) - saut de ligne (LF - dans les littéraux de Chaîne représentée comme
"\n"
)
- retour de chariot (CR - dans les littéraux de Chaîne représentée comme
-
quand vous lisez les données de la console, il permet à l'utilisateur de taper sa réponse et quand il est fait, il a besoin de en quelque sorte confirmer ce fait. Pour ce faire, l'utilisateur doit appuyer sur la touche "entrer"/touche"retour" sur le clavier.
ce qui est important est que cette clé en plus d'assurer le placement des données de l'utilisateur à entrée standard (représenté par
System.in
qui est lu parScanner
) envoie également les séparateurs de ligne dépendants de L'OS (comme pour Windows\r\n
) après lui.Ainsi , lorsque vous demandez à l'utilisateur une valeur comme
age
, et que les types d'utilisateurs 42 et les presses entrent, l'entrée standard contiendra"42\r\n"
.
problème
Scanner#nextInt
(et d'autres méthodes Scanner#nextType
) ne permet pas au Scanner de consommer ces séparateurs de ligne. Il les lira de System.in
(comment Scanner sauriez-vous qu'il n'y a pas plus de chiffres de l'utilisateur qui représentent age
valeur que face espace blanc?) qui va les supprimer de l'entrée standard, mais il sera également cache ces séparateurs de ligne en interne . Ce que nous devons nous rappeler, c'est que toutes les méthodes de Scanner sont toujours en train de numériser à partir du texte caché.
maintenant Scanner#nextLine()
recueille simplement et renvoie tous les caractères jusqu'à il trouve les séparateurs de ligne (ou fin de flux). Mais puisque les séparateurs de ligne après avoir lu le numéro de la console se trouvent immédiatement dans le cache du Scanner, il retourne la chaîne vide, ce qui signifie que le Scanner n'a pas pu trouver de caractère avant ces séparateurs de ligne (ou fin de flux).
BTW nextLine
aussi consomme ces séparateurs de ligne.
Solution
donc quand vous voulez pour demander le nombre et ensuite pour la ligne entière tout en évitant cette chaîne vide à la suite de nextLine
, soit
- consommer de séparateur de ligne à gauche par
nextInt
à partir de Scanners cache par- appelant
nextLine
, - ou en appelant
skip("\R")
pour laisser le Scanner sauter la partie correspondant à\R
qui représente le séparateur de ligne (plus d'informations sur\R
: https://stackoverflow.com/a/31060125 )
- appelant
- n'utilisez pas
nextInt
(ninext
, ni aucune méthodenextTYPE
). Au lieu de cela, Lire la totalité des données ligne par ligne en utilisantnextLine
et les numéros d'analyse de chaque ligne (en supposant qu'une ligne ne contient qu'un seul numéro) au type approprié commeint
viaInteger.parseInt
.
BTW : Scanner#nextType
les méthodes peuvent sauter les délimiteurs (par défaut tous les espaces comme les tabs, les séparateurs de ligne) y compris ceux mis en cache par scanner, jusqu'à ce qu'ils trouvent la valeur suivante non-délimiteur (jeton). Merci à cela pour l'entrée comme "42\r\n\r\n321\r\n\r\n\r\nfoobar"
code
int num1 = sc.nextInt();
int num2 = sc.nextInt();
String name = sc.next();
sera en mesure d'attribuer correctement num1=42
num2=321
name=foobar
.
au lieu de input.nextLine()
utilisez input.next()
, cela devrait résoudre le problème.
code modifié:
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();
}
pour éviter l'émission, utilisez nextLine();
immédiatement après nextInt();
car il aide à éliminer le tampon. Lorsque vous appuyez sur ENTER
le nextInt();
ne capture pas la nouvelle ligne et donc, saute le code Scanner
plus tard.
Scanner scanner = new Scanner(System.in);
int option = scanner.nextInt();
scanner.nextLine(); //clearing the buffer
si vous voulez numériser l'entrée rapidement sans se confondre dans la classe de Scanner méthode nextLine (), utilisez le Scanner D'entrée personnalisé pour cela .
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;
}
}
avantages:
- scanne L'entrée plus rapidement que BufferReader
- Réduit La Complexité Du Temps
- tampon de rinçage pour chaque entrée suivante
méthodes:
- scanChar() - scan caractère unique
- scanInt() - scan valeur entière
- scanLong() - analyse Long de la valeur
- scanString() - analyse de la Chaîne de valeur
- scanDouble () - scan Double value
- scanInt(int tableau []) - analyse complète Array(Integer)
- scanLong(long tableau []) - analyse complète de la Matrice de(Long)
Utilisation :
- Copiez le Code indiqué sous votre code java.
- initialiser L'objet pour une classe donnée
ScanReader sc = new ScanReader(System.in);
3. Catégories nécessaires à l'importation:
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
4. Lancez IOException à partir de votre méthode principale pour gérer L'Exception
5. Utilisez Les Méthodes Fournies.
6. Profiter de
exemple:
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....
si vous voulez lire à la fois les chaînes et les ints, une solution est d'utiliser deux Scanners:
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()
est meilleur que l'analyse de l'entrée.
Parce que la performance sage ce sera bon.
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);
}
mes tests ont donné les mêmes résultats que Prine, mais j'ai pensé à une solution assez simple:
en utilisant BufferedReader#nextLine()
, où vous voulez Scanner#readLine()
, évite ce bug. Vous pouvez même écrire votre propre wrapper de Scanner pour outrepasser la fonction readline de Scanner avec la fonction nextLine de BufferedReader.
je suppose que je suis en retard à la fête..
comme indiqué précédemment, appeler input.nextLine()
après avoir obtenu votre valeur int résoudra votre problème. La raison pour laquelle votre code n'a pas fonctionné était parce qu'il n'y avait rien d'autre à stocker à partir de votre entrée (où vous avez entré l'int) dans string1
. Je vais juste apporter un peu plus de lumière à tout le sujet.
prendre en considération nextLine() comme l'intrus parmi les nextFoo () méthodes dans la classe de Scanner. Prenons un exemple rapide.. Disons que nous avons deux lignes de code comme celles ci-dessous:
int firstNumber = input.nextInt();
int secondNumber = input.nextInt();
si nous entrons la valeur ci-dessous (en une seule ligne d'entrée)
54 234
la valeur de nos variables firstNumber
et secondNumber
devient respectivement 54 et 234. La raison pour laquelle cela fonctionne de cette façon est parce qu'une nouvelle ligne d'alimentation ( I. e \n ) N'est pas généré automatiquement lorsque la méthode nextInt() prend les valeurs. Il prend simplement le "int suivant" et se déplace sur. C'est la même chose pour le reste des méthodes nextFoo() sauf nextLine().
nextLine () génère une nouvelle alimentation de ligne immédiatement après avoir pris une valeur; c'est ce que @RohitJain signifie en disant que la nouvelle alimentation de ligne est "consommée".
enfin, la méthode next() prend simplement la chaîne la plus proche sans générant une nouvelle ligne; ce qui en fait la Méthode préférentielle pour prendre des chaînes séparées à l'intérieur de la même ligne simple.
j'espère que cela aidera.. Joyeux codage!
pourquoi ne pas utiliser un nouveau Scanner pour chaque lecture? Comme ci-dessous. Avec cette approche, vous n'affronterez pas votre problème.
int i = new Scanner(System.in).nextInt();