Saisir des données envoyées par le clavier

publicité
Iut Lannion
Département informatique
Algorithmique 1ère Année (AP4)
2012-2013
TP 1
L'environnement JAVA
Ce premier TP concerne la compilation et l’exécution d’un premier programme écrit en Java et la
conception de programmes Java élémentaires. Toute la documentation JAVA se trouve à l’adresse
internet http://java.sun.com/j2se/1.5.0/docs/api/ ou bien http://webetu12/DOCAPI/.
Vous pouvez saisir le code source d'une application JAVA avec n'importe quel éditeur de texte. La
compilation sous l'invite Unix se fait par la commande javac :
javac monappli.java
Le fichier à compiler doit avoir l'extension .java. Son exécution se fait par la commande java :
java monappli
Exercice 1
Ecrivez et compilez un programme qui affiche la chaîne de caractères bonjour à l'écran.
Quelques explications :
1.
Les parties de code situées entre /* et */ sont des commentaires qui ne seront pas compilés.
2.
La première instruction
public class bonjour
déclare que nous créons une classe publique (accessible par tous) qui se nomme bonjour. Cette
classe doit être enregistrée dans un fichier de même nom et d'extension .java. Attention, java
différencie les majuscules et les minuscules. La classe bonjour est différente de la classe
Bonjour, et le fichier bonjour.java n'est pas l'équivalent du fichier Bonjour.java.
3.
Java étant un langage orienté objets, tout fichier source définit une classe, c'est à dire un objet
possédant des champs et des méthodes. La définition de la classe se fait dans un bloc
d'instructions contenu entre 2 accolades.
4.
Notre classe bonjour contient une unique méthode annoncée par l'instruction
public static void main(String args[]).
Il s'agit de la méthode principale d'un programme, celle qui sera exécutée lors du lancement. Le
nom et la déclaration de cette méthode ne peuvent pas être modifiés.
5. La définition d'une méthode est une suite d'instructions située entre 2 nouvelles accolades. Dans
le cas qui nous intéresse, la méthode main n'a qu'une seule instruction qui provoque l'affichage
du message "Bonjour", par l'intermédiaire de la méthode System.out.println. Les lignes
contenant une instruction simple comme celle-ci doivent se terminer par un point-virgule.
Exercice 2/
Proposez une petite calculatrice se présentant sous la forme d’un menu. Vous utiliserez les méthode de
classe de la classe Math pour effectuer les calculs (limitez vous aux calculs d’un cosinus, d’un sinus et
d’une tangente : méthodes de classe cos(double a), sin(double a) et tan(double a) dont
le résultat est de type primitif double et dont l’argument est la mesure d’un angle en radian). Le menu
demande le type d’opération à effectuer (cosinus, sinus ou tangente) puis lit un double au clavier et
affiche le résultat de l’opération (tant que l’utilisateur n’a pas quitté le menu).
Pour saisir au clavier un type primitif il est nécessaire de mettre la saisie dans une instance de la classe
String. Les déclarations sont :
String ligne;
BufferedReader entree=new BufferedReader
(new InputStreamReader (System.in));
Le code pour une saisie est :
// saisie d'une ligne
System.out.println("Tapez une ligne");
ligne = entree.readLine();
Il faut alors convertir la saisie en type primitif. Voici quelques méthodes nécessaires aux conversions :

la méthode de classe parseInt(String str) de la classe Integer a comme argument
une instance de la classe String (elle délivre la conversion de cette instance en type primitif
int),

la méthode de classe valueOf(String str) de la classe Double a comme argument une
instance de classe String (elle délivre la conversion de la chaîne en instance de Double),

la méthode d’instance doubleValue() délivre la conversion d’une instance de Double en
type primitif double,

la méthode de classe valueOf(String str) de la classe Float a comme argument une
instance de classe String (elle délivre la conversion de la chaîne en instance de Float),

la méthode d’instance floatValue() délivre la conversion d’une instance de Float en type
primitif float.
Saisir des données envoyées par le clavier
Si vous voulez lire des données envoyées tout simplement par le clavier, nous vous indiquons deux
méthodes illustrées ci-dessous.
Les deux programmes d'illustration ont pour objectif de lire des entiers envoyés par l'intermédiaire du
clavier, et d'en faire la somme. Leurs cahiers des charges diffèrent uniquement sur la façon d'indiquer la
fin de la saisie.
Nous notons en rouge les instructions significatives sur le thème de la saisie des données au clavier.
Première méthode : utiliser un Bufferedreader
On utilise deux classes de java.io, la classe InputStreamReader et la classe BufferedReader.
La classe InputStreamReader admet un constructeur InputStreamReader(InputStream), c'est-à-dire un
constructeur qui admet en paramètre un flot d'entrée. System.in est une instance de la classe InputStream.
Avec une instance de InputStreamReader, on ne peut grosso modo que lire des caractères un à un.
La classe BufferedReader a un constructeur qui prend en argument une instance de Reader dont hérite la
classe InputStreamReader. Cette classe permet en particulier de lire une ligne d'un texte, mais en
revanche, on ne peut pas lui demander de lire un entier, un double etc...
On lit ici ce qui est envoyé par le clavier ligne par ligne et on découpe le contenu de chaque ligne avec un
StringTokenizer pour récupérer les entiers attendus.
L'utilisateur devra taper return deux fois de suite pour interrompre la saisie.
Voici le programme que nous proposons.
import import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.StringTokenizer;
class SaisieClavier
{
public static void main (String[] argv) throws IOException,
NumberFormatException
{
int somme = 0;
String ligne;
StringTokenizer st;
BufferedReader entree = new BufferedReader
(new InputStreamReader(System.in));
ligne = entree.readLine();
while(ligne.length() > 0)
{
st = new StringTokenizer(ligne);
while(st.hasMoreTokens())
somme += Integer.parseInt(st.nextToken());
ligne = entree.readLine();
}
System.out.println("La somme vaut : "+somme);
}
}
Voici une execution :
$ java SaisieClavier
31
2
Deuxième méthode : utiliser un Scanner
Depuis le JDK 5.0 , la saisie à partir de la fenêtre d'exécution est plus simple. La classe java.util.Scanner,
qui possède différents constructeurs dont un de type InputStream que nous utilisons dans notre exemple,
permet de saisir différents types de données.
class SaisieClavierBis {
public static void main (String[] arg) {
java.util.Scanner entree = new java.util.Scanner(System.in);
System.out.println("Donnez votre prénom et votre nom");
String prenom = entree.next();
String nom = entree.next();
System.out.println("Donnez votre âge");
int age = entree.nextInt();
entree.nextLine();
System.out.println("Ecrire votre phrase");
String phrase = entree.nextLine();
System.out.println(prenom + " " + nom + ", " +
age + " ans, dit : " + phrase);
}
}
Voici une execution :
Donnez votre prénom et votre nom
Lou
Charon
Donnez votre âge
12
Ecrire votre phrase
Coucou de Lou
Lou Charon, 12 ans, dit : Coucou de Lou
Vous pouvez récupérer ce programme.
Exercice 3/
Les méthodes que vous avez écrites dans les exercices précédents sont déjà implémentées en Java.
Etudiez et testez la class Scanner de la documentation JAVA.
Pour saisir au clavier un type primitif il est nécessaire de mettre la saisie dans une instance de la classe
String. Les déclarations sont :
String ligne;
Scanner sc = new Scanner(System.in);
Le code pour une saisie est :
// saisie d'une ligne
System.out.println("Tapez une ligne");
ligne = sc.nextLine();
Au coeur du JDK : la classe Scanner De Olivier Croisier
http://thecodersbreakfast.net/index.php?post/2010/03/03/Au-coeur-du-JDK-la-classe-Scanner
Une classe injustement méconnue du JDK est Scanner (java.util.Scanner).
Elle offre pourtant des fonctionnalités très intéressantes pour parser des chaînes de caractères, et en
extraire et convertir les composants.
Un Scanner peut se brancher sur à peu près n'importe quelle source : InputStream, Readable (et donc
Reader), File... et bien sûr une simple String. Ensuite, deux options s'offrent à vous : utiliser les méthodes
de type hasNext...() / next...(), ou alors les méthodes de type find...() / match() / group().
Dans ce billet, nous verrons comment utiliser ces deux jeux d'instructions.
Première méthode : hasNext() / next()
Voyons une première façon d'utiliser un Scanner pour lire des flux de texte.
Elle se décompose en deux étapes :

Premièrement, découper la chaîne de caractères en tokens grâce à un délimiteur ; il s'agit par
défaut d'un caractère "blanc" (espace, tabulation, retour à la ligne...), mais il est évidemment
possible de fournir sa propre expression via la méthode useDelimiter(expression).

Ensuite, utiliser les méthodes de type hasNext...() et next...() pour parcourir, récupérer et
convertir ces tokens.
Les méthodes de type hasNext...() (hasNextInt(), hasNextFloat()...) fonctionnent sur le même principe
qu'un Iterator, et indiquent si le prochain token existe et s'il est bien du type spécifié. Une fois cette
vérification effectuée, les méthodes de la forme next...() (nextInt(), nextFloat()...) permettent de récupérer
ledit token, directement converti dans le type adéquat.
A noter qu'existent également les méthodes simples hasNext() et next(), qui permettent de savoir s'il existe
un token (de n'importe quel type) et de le récupérer sous forme de String.
A l'aide de ces méthodes, il est très facile de parser une chaîne dont vous maîtrisez parfaitement le format,
par exemple un fichier .csv :
1.
String s =
2.
"Dalton;Joe;1.4\n" +
3.
"Dalton;Jack;1.6\n" +
4.
"Dalton;William;1.8\n" +
5.
"Dalton;Averell;2.0";
6.
Scanner scan = new Scanner(s);
7.
scan.useDelimiter(";|\n");
8.
scan.useLocale(Locale.US); // Pour les floats
9.
10.
11.
12.
while(scan.hasNextLine()) {
System.out.printf("%2$s %1$s : %3$.1f m %n", scan.next(), scan.next(),
scan.nextFloat());
}
Joe Dalton : 1,4 m
Jack Dalton : 1,6 m
William Dalton : 1,8 m
Averell Dalton : 2,0 m
Si au contraire le format de la chaîne vous est inconnu, par exemple si elle est saisie par l'utilisateur, il est
plus prudent de recourir au pattern suivant, pour éviter les erreurs de conversion de type
(InputMismatchException) :
1.
Scanner scan = new Scanner(System.in);
2.
System.out.println("Entrez un nombre entier à incrémenter :");
3.
// Existe-t-il un token ?
4.
while(scan.hasNext()) {
5.
// Est-ce un int ? On l'incrémente
6.
if (scan.hasNextInt()) {
7.
int nb = scan.nextInt();
8.
System.out.println(nb + " +1 = " + ++nb);
9.
}
10.
// Ce n'est pas un int, affichage d'un message d'erreur.
11.
else {
12.
System.out.println(scan.next() + " n'est pas un nombre.");
13.
}
14.
}
15.
scan.close();
Notez que la classe Scanner simplifie beaucoup votre code, car vous n'avez plus à convertir manuellement
les tokens ni à gérer des exceptions de bas niveau.
A titre de comparaison, voici le code effectuant le même traitement sans utiliser la classe Scanner :
1.
BufferedReader reader = null;
2.
String line = null;
3.
try {
4.
reader = new BufferedReader(new InputStreamReader(System.in));
5.
while ((line=reader.readLine()) != null) {
6.
try {
7.
System.out.println(Integer.parseInt(line)+1);
8.
} catch (NumberFormatException e) {
9.
System.out.println(line + " n'est pas un nombre.");
10.
}
11.
12.
}
} catch (IOException e) {
13.
14.
e.printStackTrace();
} finally {
15.
if (reader!=null) {
16.
try {
17.
reader.close();
18.
} catch (IOException e) {
19.
}
20.
21.
}
}
Même pour une simple lecture de fichier ligne par ligne, Scanner remplace avantageusement le
traditionnel BufferedReader :
1.
2.
public static void readFileWithBufferedReader(String fileName) {
BufferedReader reader = null;
3.
try {
4.
reader = new BufferedReader(new FileReader(fileName));
5.
String line = null;
6.
while ((line=reader.readLine())!=null) {
7.
System.out.println(line);
8.
}
9.
} catch (FileNotFoundException e) {
10.
e.printStackTrace();
11.
} catch (IOException e) {
12.
e.printStackTrace();
13.
} finally {
14.
if (reader!=null) {
15.
try {
16.
reader.close();
17.
} catch (IOException e) {
18.
}
19.
}
20.
21.
}
}
22.
23.
public static void readFileWithScanner(String fileName) {
24.
Scanner scan = null;
25.
try {
26.
scan = new Scanner(new File(fileName));
27.
while(scan.hasNextLine()) {
28.
System.out.println(scan.nextLine());
29.
30.
}
} catch (FileNotFoundException e) {
31.
32.
33.
e.printStackTrace();
} finally {
if (scan!=null) scan.close();
34.
35.
}
}
-------------------------
Téléchargement