TD 1 - Les outils indispensables
Les objectifs de ce TD sont :
- la configuration de son compte informatique ;
- la prise en main de l'environnement de travail ;
- l'écriture de quelques programmes simples en Java.
Configuration
Durant ce TD, il faut changer ses mots de passe.
Documentation sur l'environnement de travail
Les pages qui suivent fournissent une documentation sur les manipulations de base qui serviront pour les travaux dirigés de programmation en java, ce trimestre et aussi l'année prochaine. Par la suite, vous pourrez les consulter à tout moment depuis la page du cours.
- quelques informations sur l'environnement KDE
- les principales commandes utiles à la manipulation des fichiers (ces commandes sont également décrites dans le mémento).
- quelques informations sur le navigateur Firefox
- Pour éditer les programmes, on utilisera l'éditeur Emacs. Ceux qui connaissent peuvent aussi utiliser Eclipse, qui n'est pas un éditeur mais un environnement de développement intégré (par exemple, Eclipse compile au fur et à mesure que vous écrivez). L'utilisation d'Eclipse est plus compliquée quand on débute en Java.
Une documentation beaucoup plus complète est fournie dans le manuel d'utilisation
rédigé par la DSI et sur les pages de Philippe Chassignet.
Premiers programmes
L'exercice qui suit permet de vérifier que l'on
maîtrise les trois phases de la mise en oeuvre d'un programme.
Pour les réaliser, il n'est pas nécessaire de comprendre
le langage Java.
Pour l'instant, il suffit de suivre fidèlement les instructions
données ci-dessous.
- Commencer proprement.
Ouvrir un terminal en cliquant sur l'icône
dans le bandeau en bas de l'écran. Ce terminal fait l'interface avec un shell interpréteur des commandes Unix.
Créez au moyen de la commande mkdir un répertoire
(par exemple INF321) pour placer les fichiers que
vous écrirez au cours des TD. Créez ensuite, à l'intérieur de ce
répertoire, un répertoire TD1 pour stocker les
programmes de ce premier TD. Placez-vous dans le répertoire TD1 au moyen de la commande cd INF321/TD1
Les semaines suivantes, il faudra veiller à créer un répertoire pour
chaque nouveau TD.
- Ecrire un programme à l'aide d'un éditeur de texte.
Le programme Emacs est l'éditeur de texte recommandé pour l'enseignement. Il est très utilisé pendant les travaux dirigés de programmation mais, plus généralement, il peut servir à créer ou modifier tout fichier texte.
Ceux qui le souhaitent peuvent aussi utiliser un autre éditeur qu'ils connaissent, voire un environnement de développement intégré comme Eclipse.
On lance l'éditeur Emacs par la commande :
emacs &
Le caractère & qui est à la fin de la commande sert
à la lancer en "arrière-plan", ce qui libère
le terminal pendant l'édition et permet d'entrer d'autres commandes,
pour la compilation par exemple.
Pour ouvrir sous Emacs un nouveau fichier, appelé Vide.java, dans le répertoire INF321/TD1, sélectionner le menu Files, Visit New File. Puis, choisissez le répertoire INF321/TD1 et entrez le nom du fichier : Vide.java
-
Voici le texte d'un programme vide :
// Programme Vide
// Ce programme minimal en Java ne fait rien !
class Vide {
// fonction principale
public static void main(String[] args) {
} // fin de la fonction principale
} // fin du programme
Recopiez ce programme dans Vide.java.
Pour coller à la souris sous Emacs, il faut se placer avec le bouton gauche au point d'insertion, puis cliquer avec le bouton du milieu.
- Sauvez le fichier Vide.java. Dans le menu Files, sélectionner Save Buffer, qui sauve le fichier déjà ouvert (dans la terminologie d'Emacs, le buffer est la zone de
mémoire qui contient la version du texte en cours d'édition).
- Compilez le fichier Vide.java puis exécutez le programme. La ligne
public static void main(String[] args) {
présente dans tout programme Java, introduit la fonction principale.
Ce programme se compile au moyen de la
commande :
javac Vide.java
et on l'exécute par :
java Vide
- Programme Bonjour.
On se propose maintenant de modifier ce programme pour qu'il affiche
le message Bonjour. On sauve donc le programme précédent sous le nom
Bonjour.java (dans Emacs, utilisez le menu Files ... Save Buffer as).
Ensuite, on remplace
class Vide par class Bonjour et on insère
l'instruction :
System.out.println("Bonjour");
entre les lignes
public static void main(String[] args) {
et
}
On doit prendre tout de suite l'habitude de ne mettre qu'une instruction par ligne et d'indenter correctement ses
programmes. Pour
indenter une ligne sous Emacs, on appuie sur la touche
Tab.
Après l'avoir sauvé, ce programme sera compilé et
exécuté par les commandes ad-hoc.
-
Le nom du programme, ici
Bonjour, qui figure dans la première ligne class Bonjour n'est pas nécessairement identique au nom du fichier. On peut ainsi remplacer
class Bonjour
par class ProgrammeBonjour
Pour compiler le programme, on utilise le nom du fichier :
javac Bonjour.java
On peut remarquer en exécutant la commande ls que la compilation produit un fichier qui porte le nom du programme suivi du suffixe .class, ici ProgrammeBonjour.class
Puis, pour l'exécuter, on utilise le nom du programme :
java ProgrammeBonjour
-
Cas d'un programme qui "boucle".
Si on insère :
while (true)
avant
System.out.println("Bonjour");
on obtient un programme qui affiche sans fin.
Pour l'interrompre, il faut entrer Ctrl-c dans la fenêtre
terminal.
Exercices de base
Veillez à faire au moins les 3 exercices qui suivent, qui pointent un certain nombre de sources d'erreurs (ou d'incompréhension) fréquentes.
Exercice 1 : les types primitifs
1. Calculer et afficher 20!, en utilisant une
variable i de type int puis une variable n
de type long. Pouvez-vous expliquer la différence
de comportement ?
2. a) Quel est le résultat des instructions: double d = 0;
d = 1+1/2+1/3;
System.out.println(d);
Que faire pour obtenir un résultat plus conforme à l'intuition ?
b) De même, comprenez-vous le résultat des instructions suivantes ?
double d1 = 1e-20, d2 = 1e40, d3 = 1e40;
System.out.println(d1+(d2-d3));
System.out.println((d1+d2)-d3);
3. Écrire un programme qui calcule et affiche à l'écran les
quantités:

Vous pouvez jeter un oeil sur la documentation
de java.lang.Math.
4. Écrire un programme qui calcule la représentation polaire du nombre
complexe z = 1.5+2.3 i. Rappelons qu'il s'agit d'écrire
z = x+i y sous la forme

avec

On utilisera les fonctions présentes dans java.lang.Math.
Exercice 2 : déboguer un programme
On programme rarement sans faire d'erreur. Il est donc important de savoir détecter les erreurs dans un programme et les corriger rapidement. Pour cela, le programmeur dispose de plusieurs outils qui lui facilitent considérablement la tâche :
- les messages d'erreur du compilateur : ils sont relativement explicites en Java ; en particulier, le numéro de la ligne où est détectée la première erreur est souvent pertinent ;
- les messages d'erreur à l'exécution ;
-
- l'affichage de valeurs intermédiaires quand le programme ne produit pas le bon résultat.
Il est très important de compiler et de tester son programme très régulièrement, par exemple après l'écriture de chaque fonction.
Pour vous entraîner à déboguer rapidement, voici plusieurs versions erronées d'un même programme censé calculer la valeur de n! où n est un entier entré au clavier par l'utilisateur. L'objectif de cet exercice est de trouver l'erreur dans chacun de ces programmes en utilisant les différents messages d'erreur retournés par le compilateur ou à l'exécution.
Pour récupérer les huit fichiers suivants, il suffit par exemple de cliquer sur chaque lien avec le bouton de droite et en choisissant Save Link As... dans le menu. Prenez garde à les sauver dans le répertoire approprié (a priori, INF321/TD1). On peut aussi tous les récupérer en une seule fois sous la forme du fichier archive (zip) suivant Bug.zip. Une fois ce fichier archive recopié dans le répertoire adéquat, on retrouve les huit fichiers composants au moyen de la commande unzip Bug.zip.
Exercice 3 : calcul d'une approximation de e
On veut calculer une approximation de

à ε près en calculant

On utilisera la majoration :
a) Programmer le calcul du plus petit entier N tel que

où epsilon est passé en argument.
b) On évalue eN à l'aide du schéma

Écrire le programme correspondant, qui calcule e
à epsilon près. Comparer avec la constante Math.E.
Exercices à la mode de l'ACM
Voici quelques exercices, proposés par François Morain. Ils manipulent les tableaux et les boucles.
Utilisez les indications fournies à la fin de chacun des énoncés.
La documentation et les sources de la classe Ppl se trouvent ici.
Exercice 4 : collecte de votes
Un vote a eu lieu dans un pays imaginaire pour élire un président de
la république parmi nc candidats. Le pays contient nr
régions. On suppose que chaque région renvoie au Ministère de
l'intérieur le résultat du vote sous la forme d'un fichier
contenant pour chaque candidat le nombre de voix qu'il a obtenues au
scrutin. Le but de l'exercice est de déterminer le ou les candidats
ayant obtenu le plus grand nombre de suffrages.
On suppose qu'on donne en entrée un fichier contenant sur sa
première ligne le nombre de candidats, sur la deuxième le nombre
de régions. Sur les autres lignes, on trouve les résultats de
chaque région mis bout à bout. Par exemple, le fichier contiendra :
4
2
0 10
1 20
2 30
3 100
0 20
1 50
2 80
3 10
Chaque ligne au-delà des deux premières contient deux entiers : le
premier est le numéro du candidat (un entier entre 0 et nc-1),
le second le nombre de voix qu'il a obtenues au scrutin.
On demande d'écrire un programme Votes qui prend un tel fichier
et affiche à l'écran le ou les numéros des candidats
ayant obtenu le maximum des votes sur une seule ligne, séparés par
un espace.
Dans l'exemple donné ci-dessus, on obtient :
2 3
Pour tester votre programme, vous pouvez utiliser les fichiers
f1.question, f2.question, auquels correspondent les fichiers correction
f1.correction, f2.correction.
Indications.
- Pour lire le contenu du fichier, on écrira le programme comme si les données étaient entrées au clavier en utilisant la fonction de lecture de la classe
Ppl : Ppl.readInt. Puis, on redirigera l'entrée standard vers le fichier au lancement du programme à l'aide de l'opérateur < d'Unix. La commande à utiliser pour tester le programme sera donc du style
java Votes < fichier
où fichier est le nom du fichier contenant les données.
- Pour créer un tableau
tab de N entiers, il faut le déclarer par
int[] tab;
puis utiliser l'instruction d'allocation
tab = new int[N];.
Ses deux instructions peuvent être regroupées en
int[] tab = new int[N];.
Les valeurs initiales des éléments de tab
sont alors mises à zéro.
Exercice 5 : vitesse limite
La vitesse sur le périphérique de l'École est limitée à 50 km/h. Pour
vérifier que cette limitation est bien respectée, un radar muni d'un
télémètre laser et d'un détecteur de badge est caché dans les
fourrés. Ce radar est capable de mesurer la vitesse d'un véhicule en
même temps qu'il peut lire le numéro de badge de son conducteur. Le
but de l'exercice est d'afficher les mauvais conducteurs.
Le fichier d'entrée comprend des lignes d'entiers. La première ligne
contient un entier vmax, qui est la vitesse limite à ne pas
dépasser. Les lignes suivantes contiennent deux entiers: le premier est
la vitesse mesurée, le second le numéro de badge.
Le programme doit afficher les lignes correspondant aux véhicules
dépassant strictement la vitesse limite.
Par exemple, le fichier input1 contient:
50
100 1
45 2
50 3
65 10
70 20
20 50
Le programme devra afficher:
100 1
65 10
70 20
Indications.
- Pour manipuler le contenu du fichier, on utilisera la fonction
Ppl.readInt de la classe Ppl, comme si les données étaient entrées au clavier. Puis, on redirigera l'entrée standard sur un fichier de données au lancement du programme à l'aide de l'opérateur < d'Unix. Pour détecter la fin de la lecture, on utilisera la fonction Ppl.endOfInput qui retourne un booléen qui vaut true si la fin du fichier est détectée. On peut ainsi lire des mots tant que la condition
!Ppl.endOfInput()
est vraie.
Exercice 6 : gestion d'une caisse
On suppose qu'un commerçant dans un aéroport doit gérer une double caisse en euros et en dollars. Pour chaque transaction, il entre le montant
en dollars ou euros des achats faits par un client. À la fin de la
journée, il doit comparer le total des euros et le total des dollars
avec celui des pièces et billets présents dans ses deux caisses.
On lit un fichier dont chaque ligne correspond à un
montant d'achats. Le premier caractère de la ligne est E ou D et
indique ainsi si le montant a été réglé en euros ou en
dollars. Ce caractère est suivi par un entier
qui correspond au montant. Le but du programme est de lire le
fichier et d'afficher sur une ligne le montant en euros, suivi du
montant en dollars, les deux étant séparés par un espace.
Pour tester votre programme, vous pouvez utiliser les fichiers
f1.question, f2.question, auquels correspondent les fichiers correction
f1.correction, f2.correction.
Indications.
- Pour manipuler le contenu du fichier, on utilisera les fonctions
Ppl.readChar, Ppl.readInt et Ppl.endOfInput, ainsi que l'opérateur < d'Unix.
Exercice 7 : compression de bitmaps
On représente une image en noir et blanc par une suite de lignes
contenant des 0 et des 1 (0 = blanc, 1 = noir), comme dans l'exemple
qui suit :
000000000000000000000000000011111111111111000000000
000000000000000000000000001111111111111111110000000
000000000000000000000001111111111111111111111110000
000000000000000000000011111111111111111111111111000
000000000000000000001111111111111111111111111111110
000000000000000000011111110000000000000000001111111
000000000000000000011111000000000000000000000011111
000000000000000000011100000000000000000000000000111
000000000000000000011100000000000000000000000000111
000000000000000000011100000000000000000000000000111
000000000000000000011100000000000000000000000000111
000000000000000000001111000000000000000000000001110
000000000000000000000011100000000000000000000111000
011111111111111111111111111111111111111111111111111
011111111111111111111111111111111111111111111111111
011111111111111111111111111111111111111111111111111
011111111111111111111111111111111111111111111111111
011111111111111111111111111111111111111111111111111
011000000000000000000000000000000000000000000000011
On suppose que toutes les lignes ont la même longueur.
Comme on le constate dans l'exemple précédent, une image typique
contient des suites assez longues de 0 et de 1 consécutifs. L'idée
pour compresser ce dessin est de remplacer une ligne par une suite de
nombres. Le premier nombre est le nombre de 0 consécutifs à partir
du début, suivi d'un espace, suivi du nombre de 1, etc. Ainsi la
première ligne du dessin ci-dessus est remplacée par :
28 14 9
ce qui représente un gain de place certain.
Écrire un programme Compresser qui prend un
fichier au format ci-dessus et qui le sort au format compressé.
Pour tester votre programme, vous pouvez utiliser les fichiers
f1.question et f2.question, auquels correspondent les fichiers correction
f1.correction et f2.correction.
Indications.
- Pour manipuler le contenu du fichier, on utilisera la fonction
Ppl.readWordAsCharArray de la classe Ppl : cette fonction retourne un tableau de char correspondant aux caractères du mot lu (un mot est une suite de caractères délimitée par des espaces ou des passages à la ligne). Cette fonction effectue également l'allocation de ce tableau nécessaire pour définir sa taille.
- Pour détecter la fin de la lecture, on utilisera la fonction
Ppl.endOfInput qui retourne un booléen qui vaut true si la fin du fichier est détectée. On peut ainsi lire des mots tant que la condition
!Ppl.endOfInput()
est vraie.
- La taille d'un tableau
tab est donnée par tab.length.
- Les constantes de type
char s'écrivent entre apostrophes. Par exemple, pour tester si la variable c de type char correspond au caractère 0, on écrit
if (c == '0')
Exercice 8 : alphabet OTAN
L'alphabet OTAN associe à chaque lettre de l'alphabet latin (a-z) un
mot par lettre, selon la table suivante :
String[] alphabet = {
"alpha", "bravo", "charlie", "delta", "echo", "foxtrot",
"golf", "hotel", "india", "juliet", "kilo", "lima",
"mike", "november", "oscar", "papa", "quebec", "romeo",
"sierra", "tango", "uniform", "victor", "whiskey", "xray",
"yankee", "zulu"};
Ainsi alphabet[0] contient la chaîne alpha qui
représente le a. Cet alphabet permet d'épeler des mots par
radio dans des cas de mauvaise réception.
Un mot du langage normal est constitué de lettres. Chaque lettre est
remplacée par son équivalent OTAN, séparé par un espace de la
lettre suivante. Quand on épelle une phrase, on écrit un mot par
ligne. Par exemple, la phrase ``ecole polytechnique'' sera
affichée sous la forme :
echo charlie oscar lima echo
papa oscar lima yankee tango echo charlie hotel november india quebec uniform echo
Ecrire un programme VersOTAN qui lit
un fichier qui contient un texte
écrit en langage courant et qui affiche à l'écran les mots
correspondants en alphabet OTAN, une liste de lettres OTAN par ligne.
Pour tester votre programme, vous pouvez utiliser les fichiers
f1.question, f2.question, auquels correspondent les fichiers correction
f1.correction, f2.correction.
Indications.
- Pour manipuler le contenu du fichier, on utilisera les fonctions
Ppl.readWordAsCharArray et Ppl.endOfInput, ainsi que l'opérateur < d'Unix.
- Le code entier d'un caractère
c s'obtient par (int)c. Les caractères sont codés de façon contiguë. Ainsi (int)(c-'a') retourne un entier entre 0 et 25 si c est un caractère de l'ensemble {a, ..., z}.
Si vous désirez utiliser Java sur votre machine personnelle, le
Binet Réseau propose des
outils en téléchargement.
Dernière mise à jour :
03/05/2011
Avec des emprunts aux pages de Philippe Chassignet, David Monniaux et François Morain.
Pour tout commentaire : Anne [point] Canteaut [arobase] inria [point] fr