Pour commencer ce TD, vous devez avoir construit un projet, configuré pour l’utilisation de la classe TC, comme indiqué dans les activités préliminaires. Si ce n’est pas le cas, il faut commencer par cela.
Rappel, toutes les classes que vous écrirez seront dans le paquetage par défaut (default package).
À partir de maintenant et au cours de chaque TD, vous devrez déposer votre travail au fur et à mesure. N’attendez pas la fin pour tout déposer, nous devons suivre votre avancement.
Une fois déposé, votre programme va faire l’objet d’une validation automatique. Attention, si la validation dit “OK”, cela ne veut pas dire que votre programme est parfait, mais simplement qu’il a passé avec succès quelques tests qui détectent les erreurs les plus grossières.
Remarque: Il n’y a pas d’exercice 1 cette semaine, il a été remplacé par les différents exercices préliminaires. Il s’agit maintenant d’exercices qui demandent un peu plus de réflexion. On va devoir en effet déclarer des variables, faire des affectations, écrire des expressions de calculs, des conditions et des boucles.
Récupérez le programme Heures en cliquant ce lien.
Vous devez compléter la fonction chaineDe en réalisant
le calcul des valeurs des heures, minutes et secondes.
Par exemple, si la valeur qui est passée en paramètre (le nombre
total de secondes) est 4000, comme 4000 secondes = 1 h, 6
mn et 40 s, vous devez calculer ces trois valeurs 1, 6 et 40 et les
ranger dans les variables correspondantes. L’instruction
return de chaineDe assemble ces valeurs pour
former la chaîne qui est renvoyée comme valeur de la fonction. Ainsi,
pour le paramètre 4000, la fonction chaineDe
va renvoyer la chaîne 1 : 6 : 40.
Indications : Si a et b
sont deux int positifs, l’expression a / b
calcule le quotient (entier) de a par b et
l’expression a % b calcule le reste (entier) de la division
de a par b.
La fonction main affiche la valeur de retour de
chaineDe pour quelques exemples. Vous devez obtenir la
sortie suivante :
0 : 0 : 0 0 : 0 : 1 0 : 0 : 59 0 : 1 : 0 0 : 1 : 59 0 : 2 : 0 0 : 59 : 59 1 : 0 : 0 1 : 0 : 1 1 : 6 : 40 23 : 59 : 59
Déposez
ici
votre programme Heures.java (assurez vous de bien
sélectionner le programme
Heures.java qui se trouve dans le
répertoire des sources de VSCode, et pas la version initiale qui
pourrait se trouver par exemple dans le répertoire de
téléchargement).
De manière similaire à la classe TC, on installe le paquetage MacLib. Le programme de test associé permet de vérifier la bonne installation.
Récupérez ensuite la classe DessinHorloge. Vous ne devez
pas modifier cette classe mais seulement utiliser ses
fonctions tracerHeures, tracerMinutes et
tracerSecondes. Vous devez donc lire leur documentation
pour leur passer les bons paramètres.
Récupérez ensuite le programme Horloges.
Vous devez compléter la fonction tracerAiguilles pour
réaliser l’affichage graphique de l’heure. Cette fonction
ne doit pas afficher de texte sur la
console. Il faut calculer la position angulaire de chaque aiguille et
passer cette valeur en paramètre à la fonction tracer...
correspondante. Toute la difficulté de cet exercice réside dans un
calcul rigoureux qui utilise correctement les particularités de
l’arithmétique en Java lorsque l’on combine des entiers et des
flottants.
Le saviez vous ? Dans une horloge, les aiguilles des minutes et des heures avancent d’un petit cran à chaque seconde. Il s’agit de reproduire ce mécanisme.
Le résultat attendu est le suivant (vérifiez bien la position de vos aiguilles) :
|
|
|
On voit notamment sur l’exemple de gauche que la position attendue de l’aiguille des heures n’est pas la verticale (angle 0) mais qu’elle s’est déplacée de l’angle correspondant à la fraction d’heure que représentent 33 minutes et 20 secondes. De même, l’aiguille des minutes n’est pas exactement à la position qui correspond à 33, mais elle est un peu décalée du fait des 20 secondes.
Déposez
ici
votre programme Horloges.java.
Ajoutez à la classe Heures une fonction
public static int lireEntier(String invite) qui doit :
invite sur la
console, en utilisant TC.print,TC.lireInt();Vous devez tester. Par exemple, en mettant ces instructions :
String message = "combien de secondes ? ";
int secondes_1 = lireEntier(message);
TC.println(chaineDe(secondes_1));
int secondes_2 = lireEntier(message);
TC.println(chaineDe(secondes_2));
TC.print("total = ");
TC.println(chaineDe(secondes_1+secondes_2));
dans la fonction main de la classe Heures,
on doit obtenir :
combien de secondes ? 2000 0 : 33 : 20 combien de secondes ? 6000 1 : 40 : 0 total = 2 : 13 : 20
où c’est l’utilisateur qui a choisi d’entrer au clavier les valeurs
2000 et 6000 à la fin de
la première et de la troisième ligne. Notez que l’espace après le
? est celui qui est inclus dans le message d’invite. Notez
aussi qu’il n’y a pas de retour à la ligne à la fin de ce message.
Lorsque l’exécution de TC.lireInt() commence, le curseur
est donc placé en bout de ligne, après l’espace qui suit le
? et l’exécution de TC.lireInt() se fige dans
l’attente d’une entrée au clavier. Le 2000 qui
s’affiche est un écho de l’entrée au clavier et cet écho inclut le
retour à la ligne qui valide cette entrée. C’est pourquoi
TC.println(chaineDe(...)); commence à écrire au début de la
nouvelle ligne. Le retour à la ligne inhérent à la définition de
println se fait à la fin de son écriture.
Déposez
ici
Heures.java.
On veut maintenant pouvoir lire une durée sous la forme de trois
entiers qui donnent respectivement les heures, les minutes et les
secondes. Ajoutez à la classe Heures une fonction
public static int lireHMS(String invite) qui affiche le
texte donné par le paramètre invite en utilisant les
fonctions de la classe TC, lit 3 entiers et renvoie le
nombre total de secondes correspondant.
Indication : L’utilisateur peut placer les 3 nombres
sur une même ligne et le programme les récupérera au cours de 3 appels à
TC.lireInt(). Par exemple, une exécution de ces deux
instructions :
int secondes = lireHMS("entrer heures minutes secondes : ");
TC.println(secondes);
pourra donner :
entrer heures minutes secondes : 0 33 20 2000
Dans cet exemple, quand l’utilisateur aura entré 0
33 20, le premier appel à lireInt va "consommer" le
0 et il n’ira pas au delà du blanc qui suit, le
deuxième appel à lireInt va, sans attendre, "consommer" le
33 qui est déjà disponible, etc. Finalement, la
fonction lireHMS renverra la valeur
2000,
c’est le nombre de secondes qui correspond à 33 minutes et 20 secondes.
Dans le test ci-dessus, cette valeur est ensuite affichée par
l’instruction TC.println(secondes);. Sans changer le code
de lireHMS, on pourrait aussi entrer les données de la
manière suivante et obtenir le même résultat :
entrer heures minutes secondes : 0 33 20 2000
Vous devez tester. Modifiez la fonction
main de la classe Heures pour permettre une
exécution de ce type :
entrer heures minutes secondes : 0 33 20 entrer heures minutes secondes : 1 40 0 total = 2 : 13 : 20
Il s’agit de faire la somme de deux durées qui sont entrées sous la forme de 3 entiers (heures, minutes et secondes). En utilisant les fonctions déjà écrites, une simple addition suffit.
Déposez
ici
Heures.java.
On veut calculer la décomposition binaire b3b2b1b0
des entiers de 0 à 15. Complétez le programme Binaire pour réaliser cette
décomposition et afficher le résultat :
0000 = 0 0001 = 1 0010 = 2 0011 = 3 0100 = 4 ... 1111 = 15
Indication : Ces calculs peuvent se faire simplement en utilisant le quotient et le reste de divisions euclidiennes. Il y a aussi une solution plus “geek” consistant à utiliser les opérateurs de décalage et de masquage bit-à-bit définis sur les entiers.
Déposez
ici
Binaire.java.
Le codage hexadécimal permet de représenter les nombres de 0 à 15, soit un groupe de 4 bits, par un seul chiffre noté de 0 à 9 puis de A à F. On s’intéresse ici à la programmation d’un afficheur à 7 segments pour les chiffres hexadécimaux, comme illustré dans la figure ci-dessous.
On vous donne la classe Afficheur7Segments (à ne pas modifier)
qui réalise les graphiques, et la classe AffichageHexadecimal à compléter pour
obtenir l’affichage attendu. Pour chaque affichage d’un chiffre
hexadécimal, la fonction
public static boolean allumeSegment(int segment, int chiffre)
est appelée pour chaque segment afin de déterminer s’il doit être allumé
ou non. Les segments sont numérotés de 0 à 6 selon la convention
suivante :
Vous devez compléter la fonction allumeSegment; la
valeur de retour sera true quand, pour afficher le
chiffre considéré, le segment doit être allumé
(en vert) et false dans le cas contraire (le segment est
alors en noir).
Indication : On pourra par exemple enchaîner des instructions conditionnelles du genre :
if ( segment == 1 ) {
return chiffre <= 4 || 7 <= chiffre && chiffre <= 10 || chiffre == 13;
}
Rappel : en Java, l’opérateur booléen et se note
&& et il a une priorité supérieure à l’opérateur
booléen ou qui se note ||. Notez qu’il est
possible de placer des return dans les instructions
conditionnelles, ce qui permet de séparer les cas.
Déposez
ici
AffichageHexadecimal.java.
Une année est dite bissextile si elle comporte un 29 février. C’est le cas de toutes les années divisibles par 4, à l’exception de celles divisibles par 100, qui ne sont bissextiles que si elles sont également divisibles par 400.
Écrivez une classe Bissextile avec une fonction
estBissextile qui prend en paramètre un nombre entier qui
est l’année à tester, et qui renvoie true si cette année
est bissextile et false sinon.
Ajoutez une fonction
public static void affichage(int annee) qui prend en
paramètre l’année à tester et qui affiche un message indiquant en clair
si l’année est bissextile ou non.
La fonction main de votre programme sera, par exemple
:
public static void main(String[] args) {
affichage(1900);
affichage(1901);
affichage(1904);
affichage(2000);
affichage(2024);
}
Pour cet exemple, l’exécution donne :
L'annee 1900 n'est pas bissextile. L'annee 1901 n'est pas bissextile. L'annee 1904 est bissextile. L'annee 2000 est bissextile. L'annee 2024 est bissextile.
Vous devez respecter exactement le format d’affichage attendu, avec un seul espace de séparation entre les mots et pas d’espace en fin de ligne. Toutes les lignes sont terminées par un point et un retour à la ligne, y compris la dernière.
Indication : Il est rentable de réfléchir quelques minutes à l’imbrication des conditionnelles avant de se lancer dans la programmation. Veillez à tester toutes les branches de votre programme.
Déposez
ici
Bissextile.java.
On veut maintenant pouvoir utiliser les fonctions écrites à
l’exercice précédent sur autant d’années que l’on veut, sans devoir
modifier le programme à chaque fois. On va considérer que l’utilisateur
entre au clavier autant d’années positives qu’il veut, et que lorsqu’il
souhaite arrêter le programme, il entre alors une valeur strictement
négative. Dans ce cas, le programme affiche Au revoir. et
s’arrête.
Par exemple, une exécution donne quelque chose comme :
Entrer une valeur : 1900 L'annee 1900 n'est pas bissextile. Entrer une valeur : 2000 L'annee 2000 est bissextile. Entrer une valeur : -1 Au revoir.
Écrivez un nouveau programme
BoucleBissextile avec une fonction main qui
utilise les fonctions de la classe Bissextile. Les
opérations d’écriture se feront en utilisant les fonctions
TC.print(…) et TC.println(…) à votre
convenance. Il ne faut pas utiliser les fonctions similaires
System.out.print(…) et System.out.println(…).
Vous devez respecter exactement le texte et format d’affichage attendu,
avec un seul espace de séparation entre les mots et pas d’espace en fin
de ligne (mais notez que l’espace après le : doit être
écrit par le programme). Toutes les lignes, y compris la
dernière, sont terminées par un retour à la ligne.
Indication : Vous devez structurer votre programme à
l’aide d’une boucle while (annee >= 0) { ... } en
déclarant correctement la variable annee, en l’affectant au
bon moment par des appels à TC.lireInt() et en complétant
le corps de la boucle avec des appels aux fonctions de
Bissextile.
Déposez
ici
BoucleBissextile.java.
Écrivez un programme (dans Racines.java) qui calcule et qui affiche les racines réelles d’un polynôme ax2 + bx + c. On distinguera les différents cas selon le nombre de racines. On pourra supposer que a est non nul.
Les valeurs de a, b et c seront de type double
et seront introduites par TC.lireDouble().
Écrivez toutes les fonctions qui vous semblent utiles. Cet exercice ne fait pas l’objet d’une correction automatique et vous pouvez structurer votre programme comme bon vous semble.
Voici quelques exemples pour tester, vous pouvez aussi en améliorer la présentation :
Entrer a b c : 1 1 1 Discriminant = -3.0 Pas de racine
Entrer a b c : 1 -2 1 Discriminant = 0.0 Racine double : 1.0
Entrer a b c : 3 2 -1 Discriminant = 16.0 Deux racines : -1.0 et 0.3333333333333333
Entrer a b c : 0.3 0.2 -0.1 Discriminant = 0.16 Deux racines : -1.0000000000000002 et 0.33333333333333337
Entrer a b c : 0.03 0.02 -0.01 Discriminant = 0.0015999999999999999 Deux racines : -1.0 et 0.33333333333333337
Une explication des résultats obtenus sur les deux derniers exemples (en comparaison aux racines mathématiques − 1 et 1/3) est que les fractions décimales n’ont pas de représentation binaire exacte. Ces résultats peuvent varier légèrement selon la manière de les calculer.
Déposez ici votre programme (il n’y a pas de validation automatique et il sera examiné par vos enseignants).