Scanner inputMismatchException

[Fermé]
Signaler
Messages postés
95
Date d'inscription
samedi 30 juillet 2011
Statut
Membre
Dernière intervention
13 mai 2017
-
Messages postés
16372
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
23 juillet 2021
-
Bonjour,

Avec scanner, j'ai un inputMismatchException quand je mais des espace? Comment faire alors ?

Merci

2 réponses

Messages postés
16372
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
23 juillet 2021
2 858
Bonjour,

Quel type de données essaies-tu de lire ?
Quelle méthode de Scanner utilises-tu pour la récupérer ?
Messages postés
95
Date d'inscription
samedi 30 juillet 2011
Statut
Membre
Dernière intervention
13 mai 2017
1
Voici mon code

public class TestPersonneAutorisee {
public static Scanner scanner = new Scanner(System.in);
	public static void main(String[] args) {
		PersonneAutorisee liste = new PersonneAutorisee();
		System.out.println("Entrez une nouvelle personne: ");
		System.out.println("Prenom : ");
		String prenom = scanner.next();
		System.out.println("Nom : ");
		String nom = scanner.next();
		System.out.println("Adresse : ");
		String adresse = scanner.next();
		System.out.println("Age : ");
		int age = scanner.nextInt();


J'ai un inputMismatchException à la ligne 13, juste après avoir entrée l'adresse.
Messages postés
16372
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
23 juillet 2021
2 858
Il y a un piège à utiliser Scanner avec System.in à cause de la touche Entrée.

Il vaut donc mieux faire toujours des scanner.nextLine() et après appliquer une conversion sur le résultat obtenu plutôt que de manipuler les autres méthodes qui n'ont pas toutes le même comportement vis à vis de la touche Entrée.

Exemple :

public static final Scanner scanner = new Scanner(System.in);

public static String nextString() {
    return scanner.nextLine();
}

public static int nextInt() {
    return Integer.parseInt(scanner.nextLine());
}

public static void main(String[] args) {
    PersonneAutorisee liste = new PersonneAutorisee();
    System.out.println("Entrez une nouvelle personne: ");
    System.out.println("Prenom : ");
    String prenom = nextString();
    System.out.println("Nom : ");
    String nom = nextString();
    System.out.println("Adresse : ");
    String adresse = nextString();
    System.out.println("Age : ");
    int age = nextInt();
}

Ce découpage permet également de mieux gérer les cas particuliers, par exemple tu parlais d'accepter les espaces dans la saisie, alors il faut d'abord supprimer ces espaces en trop avant de faire la conversion.

public static int nextInt() {
    return Integer.parseInt(scanner.nextLine().trim());
}

On peut bien sûr aller plus loin et gérer tous les cas d'exception, en particulier si ce qui est saisi n'est pas un nombre, ou alors s'il n'est pas dans un intervalle de valeurs données.

public static int nextInt(Optional<Integer> min, Optional<Integer> max) {
    while (true) {
        try {
            int n = Integer.parseInt(scanner.nextLine().trim());
            if (min.isPresent() && n < min.get())
                throw new ArithmeticException("Number must be greater than or equal to " + min.get());
            if (max.isPresent() && n > max.get())
                throw new ArithmeticException("Number must be less than or equal to " + max.get());
        } catch (RuntimeException e) {
            System.err.println("Wrong int, please retry: " + e);
        }
    }
}

public static int nextInt() {
    return nextInt(Optional.empty(), Optional.empty());
}

public static int nextPositiveInt() {
    return nextInt(Optional.of(0), Optional.empty());
}

public static int nextNegativeInt() {
    return nextInt(Optional.empty(), Optional.of(0));
}

public static String nextString() {
    return scanner.nextLine();
}
Messages postés
83
Date d'inscription
dimanche 19 juin 2016
Statut
Membre
Dernière intervention
19 janvier 2018

Salut,

Une exception InputMismatchException est lancée quand tu essaie de mettre une valeur dans un type de variable pas prévu à cet effet.
Voici une solution:

public static void main(String[] args) {
PersonneAutorisee liste = new PersonneAutorisee();
System.out.println("Entrez une nouvelle personne: ");
System.out.println("Prenom : ");
String prenom = scanner.nextLine();
System.out.println("Nom : ");
String nom = scanner.nextLine();
System.out.println("Adresse : ");
String adresse = scanner.nextLine();
System.out.println("Age : ");
int age = scanner.nextInt();




Et aussi, petite précision:
-nextLine doit être utilisée pour transformer ton input en string
-nextInt, en int
-next... tu connais la suite
-La méthode "next" ne sert presque à rien.

Bonne journée.
Messages postés
16372
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
23 juillet 2021
2 858
Bonjour,

La méthode "next" ne sert presque à rien.
Avec la configuration par défaut non, surtout sur System.in
Mais sur un fichier texte ça devient très intéressant en le combinant au useDelimiter, par exemple pour lire un fichier CSV la méthode next() permettra de lire chaque valeur séparée par les points-virgules...

Pour le reste : ATTENTION à ma remarque "les autres méthodes qui n'ont pas toutes le même comportement vis à vis de la touche Entrée"
Parce que nextLine() utilise bien un délimiteur sur les sauts de lignes, mais nextInt() utilise lui un délimiteur sur les espaces, donc il ne consomme pas la fin de ligne.

Exemple, je voudrais saisir :
1
2
x
y
Et obtenir :
a> 1
b> 2
c> x
d> y
Un code naïf pourrait donc être :
int a = scanner.nextInt();
int b = scanner.nextInt();
String c = scanner.nextLine();
String d = scanner.nextLine();
System.out.println("a> " + a);
System.out.println("b> " + b);
System.out.println("c> " + c);
System.out.println("d> " + d);

Or en réalité cela donne ceci (la touche Entrée après le 2 a été pris dans le c)
1
2
x
a> 1
b> 2
c>
d> x
Et en bidouillant on peut aussi faire ceci (le délimiteur entre 1 et 2 n'est alors plus le saut de ligne mais l'espace)
1 2
x
a> 1
b> 2
c>
d> x
Ou encore ceci (en enlevant le saut de ligne après le 2 pour avoir directement la ligne du x dans le c... mais avec un espace en trop)
1 2 x
y
a> 1
b> 2
c> x
d> y
Au final, aucune des trois saisies n'est correcte. La bonne solution étant de forcer la consommation de la fin de ligne après la lecture de chaque nextInt()

int a = scanner.nextInt(); scanner.nextLine();
int b = scanner.nextInt(); scanner.nextLine();
String c = scanner.nextLine();
String d = scanner.nextLine();
System.out.println("a> " + a);
System.out.println("b> " + b);
System.out.println("c> " + c);
System.out.println("d> " + d);

Remarque : ce piège vient juste du fait que l'on utilise System.in
Si on pense à un fichier texte il est normal de se dire que plusieurs nextInt() successifs vont lire plusieurs entiers sur la même ligne de texte.

Pour System.in le mieux est donc d'utiliser des petites méthodes utilitaires comme j'ai pu en montrer plus haut afin de ne pas se poser trop de questions à chaque utilisation de Scanner.