TL; DR À utiliser scanner.skip("\\R")
avant chaque scanner.newLine()
appel, qui est exécuté après:
scanner.next()
scanner.next*TYPE*()
méthode.
Ce que vous devez savoir:
le texte qui représente quelques lignes contient également des caractères non imprimables entre les lignes (nous les appelons séparateurs de lignes) comme
- retour chariot (CR - dans les littéraux de chaîne représentés comme
"\r"
)
- saut de ligne (LF - dans les littéraux de chaîne représentés comme
"\n"
)
lorsque vous lisez des données à partir de la console, cela permet à l'utilisateur de taper sa réponse et lorsqu'il a terminé, il doit en quelque sorte confirmer ce fait. Pour ce faire, l'utilisateur doit appuyer sur la touche "Entrée" / "Retour" du clavier.
Ce qui est important, c'est que cette clé, en plus de garantir le placement des données utilisateur sur l'entrée standard (représentée par System.in
laquelle est lu par Scanner
), envoie également des séparateurs de ligne dépendants du système d'exploitation (comme pour Windows \r\n
).
Ainsi, lorsque vous demandez à l'utilisateur une valeur telle que age
, et que l'utilisateur tape 42 et appuie sur Entrée, l'entrée standard contient "42\r\n"
.
Problème
Scanner#nextInt
(et d'autres méthodes) ne permet pas au scanner de consommer ces séparateurs de ligne. Il les lira (comment le scanner pourrait-il savoir qu'il n'y a pas plus de chiffres de l'utilisateur qui représentent une valeur que face aux espaces blancs?) Qui les supprimera de l'entrée standard, mais il mettra également en cache ces séparateurs de ligne en interne . Ce dont nous devons nous souvenir, c'est que toutes les méthodes du scanner sont toujours en train de numériser à partir du texte mis en cache. Scanner#nextType
System.in
age
Maintenant, il Scanner#nextLine()
suffit de collecter et de retourner tous les caractères jusqu'à ce qu'il trouve des séparateurs de ligne (ou la fin du flux). Mais comme les séparateurs de lignes après avoir lu le numéro à partir de la console se trouvent immédiatement dans le cache de Scanner, il renvoie une chaîne vide, ce qui signifie que Scanner n'a pas pu trouver de caractère avant ces séparateurs de lignes (ou fin de flux).
BTW consommenextLine
également ces séparateurs de ligne.
Solution
Ainsi, lorsque vous souhaitez demander un numéro, puis une ligne entière, tout en évitant cette chaîne vide à la suite de nextLine
, soit
- consommer le séparateur de lignes laissé par le
nextInt
cache des scanners par
- appeler
nextLine
,
- ou IMO de manière plus lisible serait d'appeler
skip("\\R")
ou skip("\r\n|\r|\n")
de laisser le scanner ignorer la partie correspondant au séparateur de ligne (plus d'informations sur \R
: https://stackoverflow.com/a/31060125 )
- n'utilisez pas
nextInt
(ni next
, ni aucune nextTYPE
méthode) du tout. Au lieu de cela, lisez l'intégralité des données ligne par ligne en utilisant nextLine
et en analysant les numéros de chaque ligne (en supposant qu'une ligne ne contient qu'un seul numéro) au type approprié, comme int
via Integer.parseInt
.
BTW : les méthodes peuvent ignorer les délimiteurs (par défaut, tous les espaces comme les tabulations, les séparateurs de lignes), y compris ceux mis en cache par le scanner, jusqu'à ce qu'ils trouvent la prochaine valeur non délimitante (jeton). Merci à cela pour l'entrée comme le codeScanner#nextType
"42\r\n\r\n321\r\n\r\n\r\nfoobar"
int num1 = sc.nextInt();
int num2 = sc.nextInt();
String name = sc.next();
sera en mesure d'assigner correctement num1=42
num2=321
name=foobar
.