Accueil > Programmer avec Java > Les bases de Java >
Pour ajouter de l’interaction à un programme, il faut donner la chance à l’utilisateur de nous fournir une réponse. Dans le contexte d’un programme qui se lance à la console, cela veut dire capter les réponses tapées par l’utilisateur au clavier. Dans cette leçon, nous allons voir comment faire ça en Java.
new
Type nom = new Type(arguments, ...);
.Scanner
Scanner
a accès à plusieurs méthodes d’instance pour retourner différents types de données. Un Scanner
saisie toujours du texte, donc les méthodes comme nextInt()
et nextDouble()
convertissent le texte en nombre et peuvent planter si le format des caractères saisis ne correspond pas au type attendu. C’est pourquoi il y a aussi des méthodes comme hasNextInt()
et hasNextDouble()
pour valider le format avant de tenter une conversion.Locale
Locale
pour chaque Scanner
en utilisant la méthode useLocale()
.System.in
InputStream
qui représente l’entrée standard du système d’exploitation, généralement la console. L’avantage est qu’il est toujours défini (ça fonctionne toujours). Le désavantage est que Windows gère les caractères Unicode différemment que le reste du monde, ce qui donne parfois des comportements inattendus et difficiles à résoudre.Liste des méthodes de Scanner
les plus courantes :
next()
: saisir le prochain mot (jusqu’à un espace, ignorant les espaces initiaux)nextInt()
: saisir le prochain mot et le convertir en int
nextDouble()
: saisir le prochain mot et le convertir en double
hasNextInt()
: vérifier si le prochain mot est un int
hasNextDouble()
: vérifier si le prochain mot est un double
nextLine()
: saisir la prochaine ligne de texte (jusqu’à un retour à la ligne)… il y a des nuances avec cette méthode que nous explorerons en détail ci-dessous.À la fin de cette leçon vous devrez être en mesure de :
Locale
et pourquoi il faut le spécifier si on veut saisir des valeurs décimales.Scanner
, déclarer un Scanner pour la console et utiliser ses méthodes next
, nextInt
et nextDouble
pour lire des données.Locale
approprié pour le Scanner si j’ai besoin de saisir des valeurs décimales.hasNextInt
et hasNextDouble
avant de tenter une conversion afin de réduire le nombre de plantages de mes programmes.Les Scanner sont utilisés pour lire du texte à partir de différentes sources. Pour commencer, on utilisera un Scanner
qui surveille System.in
pour complémenter le PrintStream
(System.out
) qu’on utilise déjà pour afficher des messsages texte à la console. Bref, les Scanner vont nous permettre de lire des réponses de l’utilisateur à la console et d’avoir des programmes interactifs.
Si vous ne l’aviez pas deviné,
System.in
etSystem.out
sont les entrées et sorties standard de votre système d’exploitation, notamment la console.
La structure globale d’un programme qui utilise un Scanner est la suivante :
1
2
3
4
5
6
7
import java.util.*; // importer la définition de Scanner de java.util
void main() {
Scanner console = new Scanner(System.in); // déclarer un Scanner pour la console
// ... le reste du programme
}
Le format de la déclaration d’un Scanner est le suivant :
1
Scanner nom = new Scanner(source);
où nom
est le nom de la variable qui contiendra l’objet Scanner et source
est la source de texte que le Scanner lira. Le nom est généralement un reflèt précis de la source.
On utilise System.in
, l’entrée standard, comme source.
1
Scanner console = new Scanner(System.in);
On utilise un String comme source.
1
2
String text = "Bonjour, le monde!";
Scanner textReader = new Scanner(text);
On ne ferme jamais le Scanner pour la console parce qu’on s’en sert généralement jusqu’à la fin du programme interactif. Ce Scanner sera fermé automatiquement en arrivant à la fin de la méthode main
.
Par contre, c’est important de fermer les Scanner pour toutes les autres sources de texte, comme un fichier ou un String. On ferme un Scanner avec la méthode close()
une fois qu’on a finit de le lire. Par exemple :
1
textReader.close();
Pour comprendre comment les méthodes de Scanner
fonctionnent, on va les tester sur différents String. Les sections plus bas montrent le Scanner dans le contexte d’un programme interactif.
next()
: lire le prochain motLa méthode next()
saisit le prochain mot - plus spécifiquement, le prochain ‘jeton’ - dans le texte. Un jeton est une séquence de caractères qui n’inclut pas d’espaces. Si la prochaine chose dans le texte commence par un ou plusieurs espaces, ces espaces seront ignorés en saisissant le jeton. La méthode next()
retourne le jeton saisi.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
String words = "\n \tBonjour le monde!";
Scanner wordsReader = new Scanner(words); // Scanner qui utilise le texte 'words' comme source
String word; // variable pour stocker le mot lu
word = wordsReader.next(); // ignore les espaces initiaux puis saisit tout jusqu'au prochain espace, soit "Bonjour"
System.out.println(word);
word = wordsReader.next(); // saisit "le"
System.out.println(word);
word = wordsReader.next(); // saisit "monde!"
System.out.println(word);
wordsReader.close();
nextInt()
et nextDouble()
: convertir le texte en nombrePeut être que la ligne de texte suivante représente des informations sur une personne, comme son âge et sa moyenne scolaire. Connaissant le format du texte, on peut utiliser les méthodes appropriées pour lire les valeurs.
Les méthodes nextInt()
et nextDouble()
saisissent le prochain mot et tentent de le convertir en int
ou double
respectivement. Si le texte ne peut pas être converti en nombre, le programme plantera, alors il faut faire attention de :
1
2
3
4
5
6
7
String info = "Marie 15 85.5";
Scanner infoReader = new Scanner(info);
String nom = infoReader.next(); // saisir le nom
int age = infoReader.nextInt(); // saisir le texte pour le nombre entier
double moyenne = infoReader.nextDouble(); // saisir le nombre décimal
infoReader.close();
System.out.printf("%s a %d ans et sa moyenne est %.1f\n", nom, age, moyenne);
Si le programme fonctionne correctement, il nous donnera cette sortie :
1
Marie a 15 ans et sa moyenne est 85.5
Dans notre contexte spécifique - travailler en français avec des machines configurées en français - il y a quand même un bon risque de plantage parce que le format pour le décimal est différent sur un système anglais (.
) que sur un système français (,
). À l’interne, Java utilise toujours le .
comme décimal, mais il utilisera les formats du système dans ses Scanner pour interpréter les réponses de l’utilisateur à la console.
Donc c’est possible que Java présume que le format 85,5
est le bon et lance une erreur quand il voit plutôt 85.5
. Ce n’est pas un bon système, mais il y a une façon de dire dans notre programme quel format on veut utiliser.
Quand on connaît le format des nombres décimaux dans le texte à lire, ou on dit à l’utilisateur quel format utiliser dans sa réponse interactive, on devrait spécifier ce format explicitement dans le code.
On le fait en utilisant la classe Locale
(aussi dans java.util) et les valeurs qu’elle définit par défaut pour différents formats régionaux. Dans notre contexte, on utilise l’une au l’autre des options suivantes :
Locale.CANADA
: pour utiliser le .
comme séparateur décimalLocale.CANADA_FRENCH
: pour utiliser la ,
comme séparateur décimalLe code précédent devient alors :
1
2
3
4
5
6
7
8
9
10
String info = "Marie 15 85.5";
Scanner infoReader = new Scanner(info);
infoReader.useLocale(Locale.CANADA); // spécifie le format "."
String nom = infoReader.next();
int age = infoReader.nextInt();
double moyenne = infoReader.nextDouble();
infoReader.close();
System.out.printf("%s a %d ans et sa moyenne est %.1f\n", nom, age, moyenne);
Maintenant, le programme fonctionne correctement peu importe l’ordinateur utilisé pour le lancer.
En interagissant à la console, c’est important de donner des invites de réponse claires et spécifiques à l’utilisateur afin qu’elle sache quoi taper et avec quel format, si nécessaire.
Voici un exemple en transformant le programme précédent en un programme interactif :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Scanner console = new Scanner(System.in); // source = entrée standard
console.useLocale(Locale.CANADA_FRENCH); // spécifie le format ","
System.out.print("Quel est votre prénom? "); // invite de réponse
String nom = console.next();
System.out.print("Quel est votre âge? "); // invite de réponse
int age = console.nextInt();
// invite de réponse qui reflète la déclaration du Locale plus haut dans le code
System.out.print("Quelle est votre moyenne? (utilisez le ',' comme décimal) ");
double moyenne = console.nextDouble();
System.out.printf("%s a %d ans et sa moyenne est %.1f\n", nom, age, moyenne);
// notez qu'on n'a pas fermé le Scanner pour la console
Cette section est annotée comme “avancée” parce qu’elle incorpore des éléments de programmation que nous n’avons pas encore vus avec Java, notamment les opérations logiques et les boucles. Si vous ne comprenez pas tout de suite, ne vous inquiétez pas. Vous aurez l’occasion de revoir ces concepts plus tard dans le cours.
Si vous comprenez bien comment formuler une invite de réponse précise et comment assurer la cohérence entre votre invite et ce que vous avez écrit dans votre code, peut-être que vous ne serez pas satisfait de laisser une erreur de frappe par l’utilisateur faire planter votre programme. C’est là qu’on peut commencer à rendre le code plus tolérante aux erreurs en les gérant avant qu’elles ne causent des problèmes.
Pour valider une réponse avant de la saisir, on utilise les méthodes hasNextInt()
et hasNextDouble()
pour vérifier si le prochain mot est convertible en int
ou double
respectivement. Si la réponse est valide, on la saisit, la convertit et la conserve. Sinon, on doit vider le Scanner pour préparer la saisie suivante, alors on saisit la réponse comme texte sans la conserver. On peut également afficher un message d’erreur et inviter l’utilisateur à réessayer.
1
2
3
4
5
6
7
8
9
10
11
Scanner console = new Scanner(System.in);
System.out.print("Saisissez un nombre entier : ");
while (!console.hasNextInt()) {
console.next(); // vider le Scanner du jeton incorrect
System.out.println("Ce n'est pas un nombre entier valide.");
System.out.print("Saisissez un nombre entier : ");
}
int number = console.nextInt();
System.out.println("Vous avez saisi " + number);
L’opérateur
!
est l’inverse logique (“not”). Il transformetrue
enfalse
etfalse
entrue
. Dans ce contexte,!console.hasNextInt()
signifie “tant que le Scanner n’a pas un nombre entier valide comme prochain jeton”.
aucun quiz de vérification des concepts ici encore
Travaillez dans le répertoire GitHub partagé par votre enseignant pour la pratique et les exercices.
Scanning.java
.4-5-Scanner1.png
.4-5-Scanner2.png
.4-5-Scanner3.png
.4-5-Scanner4.png
.