Question Scanner ignore nextLine () après avoir utilisé next () ou nextFoo ()?


J'utilise le Scanner méthodes nextInt() et nextLine() pour lire l'entrée.

Cela 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 la seconde 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 input.nextInt(). Si je le supprime, alors les deux string1 = input.nextLine() et string2 = input.nextLine() sont exécutés comme je le veux.


484
2017-10-27 16:37


origine


Réponses:


C'est parce que le Scanner.nextInt méthode ne consomme pas le dernière ligne de commande caractère de votre contribution, et donc que nouvelle ligne est consommé dans le prochain appel à Scanner.nextLine.

Vous rencontrerez le comportement similaire lorsque vous utilisez Scanner.nextLine après Scanner.next() ou tout Scanner.nextFoo méthode (sauf nextLine lui-même).

Solution de contournement:

  • Soit tirer un blanc Scanner.nextLine appeler après Scanner.nextInt ou Scanner.nextFoo pour consommer le reste de cette ligne, y compris nouvelle ligne 

    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 par le biais Scanner.nextLine et convertissez votre entrée au format approprié dont vous avez besoin. Par exemple, à un entier utilisant Integer.parseInt(String) méthode.

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

576
2017-10-27 16:39



Le problème est avec le input.nextInt () méthode - il ne lit que la valeur int. Donc, lorsque vous continuez à lire avec input.nextLine (), vous recevez la touche "\ n" Entrée. Donc, pour sauter ceci vous devez ajouter le input.nextLine (). J'espère que cela devrait être clair maintenant.

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

166
2017-08-14 12:24



C'est parce que lorsque vous entrez un numéro, appuyez sur Entrer, input.nextInt() consomme seulement le nombre, pas la "fin de ligne". Quand input.nextLine() s'exécute, il consomme la "fin de ligne" toujours dans le tampon de la première entrée.

Au lieu de cela, utilisez input.nextLine() juste après input.nextInt()


60
2017-08-14 12:25



Il semble y avoir beaucoup de questions sur ce problème avec java.util.Scanner. Je pense qu'une solution plus lisible / idiomatique serait d'appeler scanner.skip("[\r\n]+") supprimer les caractères de nouvelle ligne après l'appel nextInt().

EDIT: comme @PatrickParker noté ci-dessous, cela provoquera une boucle infinie si l'utilisateur entre des espaces après le nombre. Voir leur réponse pour un meilleur modèle à utiliser avec skip: https://stackoverflow.com/a/42471816/143585


32
2018-03-23 16:35



Ça fait ça parce que input.nextInt(); ne capture pas la nouvelle ligne. vous pourriez faire comme les autres proposés en ajoutant un input.nextLine(); sous.
Sinon, vous pouvez le faire en style C # et analyser un nextLine en un entier comme ceci:

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

Cela fonctionne aussi bien, et cela vous évite une ligne de code.


23
2018-02-23 22:01



Les choses que vous devez savoir:

  • le texte qui représente peu de lignes contient aussi des caractères non imprimables entre les lignes (nous les appelons séparateurs de lignes) comme

    • retour chariot (CR - in String littéraux représentés comme "\r")
    • saut de ligne (littéraux LF - in représentés par "\n")
  • lorsque vous lisez des données depuis la console, cela permet à l'utilisateur de taper sa réponse et quand il a terminé, il doit en quelque sorte confirme ce fait. Pour ce faire, l'utilisateur doit appuyer sur la touche "Entrée" / "Retour" du clavier.

    Ce qui est important est que cette clé à côté de la garantie de placer les données de l'utilisateur entrée standard (représenté par System.in qui est lu par Scanner) envoie également des séparateurs de lignes dépendant du système d'exploitation (comme pour Windows \r\n) après ça.

    Donc, lorsque vous demandez à l'utilisateur une valeur comme age, et les types d'utilisateur 42 et appuie sur entrer, l'entrée standard contiendra "42\r\n".

Problème

Scanner#nextInt (et autre Scanner#nextType méthodes) ne permet pas à Scanner de consommer ces séparateurs de ligne. Il les lira de System.in (Sinon, Scanner saurait qu'il n'y a plus de chiffres de l'utilisateur qui représentent age valeur que face aux espaces blancs?) qui va les retirer de l'entrée standard, mais ça va aussi cache ces séparateurs de lignes en interne. Ce dont nous devons nous souvenir, c'est que toutes les méthodes Scanner numérisent toujours à partir du texte mis en cache.

À présent Scanner#nextLine() recueille et retourne simplement tous les caractères jusqu'à ce qu'il trouve des séparateurs de ligne (ou fin du flux). Mais puisque les séparateurs de ligne après avoir lu le numéro de la console sont trouvés immédiatement dans le cache de Scanner, il renvoie String vide, ce qui signifie que 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 demander un nombre et ensuite pour une ligne entière et éviter cette chaîne vide en résultat de nextLine, non plus

  • après nextInt endroit Additionnel  nextLine appel pour consommer les séparateurs de ligne du cache Scanners,
  • ne pas utiliser nextInt (ni next, ou tout nextTYPE méthodes) du tout. Au lieu de cela, lisez des données entières ligne par ligne en utilisant nextLine et analyser les nombres de chaque ligne (en supposant qu'une ligne ne contient qu'un seul numéro) au type approprié int via Integer.parseInt.

BTW: Scanner#nextType les méthodes peuvent sauter délimiteurs (par défaut tous les espaces blancs comme les tabulations, les séparateurs de lignes) y compris ceux mis en cache par le scanner, jusqu'à ce qu'ils trouvent la valeur non-délimiteur suivante (jeton). Merci à cela pour les entrées 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'affecter correctement num1=42  num2=321  name=foobar.


15
2017-10-09 22:51



Au lieu de input.nextLine() utilisation 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();
}

4
2017-07-23 10:20



Afin d'éviter le problème, utilisez nextLine(); juste après nextInt(); car cela aide à nettoyer le tampon. Lorsque vous appuyez sur ENTER la nextInt(); ne capture pas la nouvelle ligne et, par conséquent, saute la Scanner code plus tard.

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

4
2017-11-17 00:51