III. Chapitre 4▲
III-A. La classe ConvertisseurTemperatures▲
J'ai ici décidé cette fois-ci d'inclure la méthode main() dans la classe ConvertisseurTemperatures elle-même.
Sur Internet on trouve facilement les formules de conversion. Soient Tc la température en degrés celcius et Tf la température en degrés Farenheit.
Tc = (5/9) * (Tf - 32)
Tf = (9/5) * Tc + 32
Il convient de traiter les différents cas possibles pour la méthode convertirTemperature :
- l'utilisateur a employé le format 'C' ;
- l'utilisateur a employé le format 'F' ;
- l'utilisateur n'a pas du tout employé un format attendu.
J'ai alors pensé à l'utilisation d'une structure switch. Sachez que le cas default correspond à toute valeur du switch que nous n'avons pas choisi de traiter.
Par conséquent, on peut ici s'en servir pour retourner un message d'erreur (la fonction doit retourner un String, profitons-en).
Par contre, ne pas oublier d'utiliser le mot-clé break pour chaque cas, hormis le cas default étant donné que c'est le dernier à traiter.
III-A-1. La division entière et la division réelle▲
Certains d'entre vous ont certainement entendu parler (ou appris) de la division euclidienne. Ce n'est pas compliqué.
Si vous calculez 6 / 3 : pas de problème, vous obtiendrez un nombre entier. Et ce, que cela soit par vous-même ou à l'aide d'un programme Java. En revanche, une opération telle que 9 / 4 dépendra énormément de la manière dont vous la coderez.
Pourquoi ? Parce que l'ordinateur peut aboutir sur deux valeurs :
- ou bien 2,25 : qui est le résultat auquel, à priori, tout le monde s'attend ;
- ou bien 2 : qui est le quotient (ou simple valeur entière) de la division.
Quand aura-t-on 2,25 et quand aura-t-on 2 ?
- si vous calculez la division avec deux int, vous aurez forcément un int en retour. Donc vous obtiendrez la valeur 2 en calculant 9 / 4 ;
- mais si vous calculez la division avec un float et un int, ou avec deux float, alors vous aurez un float en retour. Donc ici : 2,25.
Eh bien, sachez-le, en codant 9f et non simplement 9, je déclare : "Je veux utiliser la valeur flottante de 9 et non pas simplement la valeur entière de 9.".
Ainsi :
- en utilisant les formules de conversion, le résultat sera beaucoup plus précis ;
- en calculant 5f/9f je n'aurais pas la valeur 0 (qui faussera donc toute la formule de conversion en degrés celcius), mais une valeur comprise entre 0 et 1. Avec précision en plus.
Et ça, c'était vraiment le piège à éviter.
III-A-2. Variable locale et initialisation▲
Enfin une dernière difficulté technique : toute variable déclarée (c'est-à-dire créée) à l'intérieur d'une méthode doit être initialisée (c'est-à-dire qu'on lui donne sa première valeur) avant d'être utilisée.
En d'autres termes, toute variable locale doit être initialisée avant toute utilisation.
Dans le code suivant, la variable locale valeurDeRetour n'a pas été initialisée à sa création. Quant à son utilisation, il n'y en a qu'une seule : lors du retour de la méthode convertirTemperature (return valeurDeRetour).
En revanche, dans le switch, tous les cas possibles aboutissent à une initialisation.
C'est-à-dire que pour toutes les valeurs que peut prendre la variable (de type char) convertirEn, on aboutit à une initialisation de la variable valeurDeRetour. Des valeurs à tester, il y en a trop : car un char peut avoir 256 valeurs. D'où l'utilité du mot-clé default dans le switch.
III-A-3. Code▲
III-B. Modification de la classe BulletinAppreciation▲
Pour rendre la méthode convertirNiveaux() statique, rien de plus simple. Sa nouvelle signature sera :
public
static
char
convertirNiveaux
(
int
noteDevoir)
On n'a rien à changer dans son corps.
Et comme elle est statique, nul besoin de créer une instance de BulletinAppreciation pour appeler la méthode convertirNiveaux() :
BulletinAppreciation.convertirNiveaux
(
valeurIntPassee);
Ce qui donne le code suivant :
public
class
BulletinAppreciation {
/**
Cette methode attend un argument entier ? la note du devoir
- et retourne une mention, I, P, A, B, T ou E, en fonction
de sa valeur.
*/
public
static
char
convertirNiveaux
(
int
noteDevoir) {
char
niveau;
if
(
noteDevoir >=
18
) {
niveau =
'E'
;
}
else
if
(
noteDevoir >=
16
&&
noteDevoir <
18
){
niveau =
'T'
;
}
else
if
(
noteDevoir >=
14
&&
noteDevoir <
16
){
niveau =
'B'
;
}
else
if
(
noteDevoir >=
12
&&
noteDevoir <
14
){
niveau =
'A'
;
}
else
if
(
noteDevoir >=
10
&&
noteDevoir <
12
){
niveau =
'P'
;
}
else
{
niveau =
'I'
;
}
return
niveau;
}
public
static
void
main
(
String[] args) {
char
tonNiveau =
BulletinAppreciation.convertirNiveaux
(
17
);
System.out.println
(
"Ton premier niveau est "
+
tonNiveau);
tonNiveau =
BulletinAppreciation.convertirNiveaux
(
15
);
System.out.println
(
"Ton second niveau est "
+
tonNiveau);}
}
III-C. Exercice pour les petits malins : félicitations aux joueurs▲
Pour les impatients, aller directement à la section réponse.
III-C-1. Le code original avec le mot-clé continue▲
Voici, à peu de choses près, le code utilisé dans le chapitre avec continue. J'ai juste englobé le code dans une classe. Sa méthode main() plus précisément. Et bien sûr, j'ai aussi initialisé les différentes variables utilisées.
public
class
FelicitationsAuxJoueurs {
public
static
void
main
(
String[] args) {
String [] joueurs =
{
"David"
, "Daniel"
, "Anna"
, "Gregory"
}
;
int
compteur =
0
;
int
nombreJoueurs =
joueurs.length;
while
(
compteur <
nombreJoueurs) {
compteur++
;
String leJoueur =
joueurs[compteur];
if
(
leJoueur.equals
(
"David"
)) {
continue
;
}
System.out.println
(
"Felicitations, "
+
leJoueur +
" !"
);
}
}
}
On comprend aisément que tous les joueurs, à l'excepté de David, soient félicités. Si vous n'en êtes pas totalement convaincus, il faut analyser le code plus en détail.
Pour ce faire, on peut "simuler" l'exécution du code par l'ordinateur. Vous pouvez imprimer le code, puis griffonner et gommer au crayon à papier les valeurs des variables. Ceci, au fur et à mesure que vous avancez dans le code. Et lors de vos différents passages dans la boucle while simulez aussi, dans une zone de votre feuille, la sortie de la console.
Si vous parvenez ainsi à deviner le résultat de la console avant même d'avoir lancé le programme : cela voudra dire que vous avez vraiment bien assimilé le concept de boucles et d'irrégularités (par break / continue).
III-C-2. Le code qu'il nous est demandé d'évaluer▲
public
class
FelicitationsAuxJoueurs {
public
static
void
main
(
String[] args) {
String [] joueurs =
{
"David"
, "Daniel"
, "Anna"
, "Gregory"
}
;
int
compteur =
0
;
int
nombreJoueurs =
joueurs.length;
while
(
compteur <
nombreJoueurs) {
String leJoueur =
joueurs[compteur];
if
(
leJoueur.equals
(
"David"
)) {
continue
;
}
System.out.println
(
"Felicitations, "
+
leJoueur +
" !"
);
// On a laissé compteur++ a la fin de la boucle while
compteur++
;
}
}
}
On nous demande alors ce qu'il peut bien se passer.
Vous n'avez pas encore testé ce code à l'ordinateur et vous avez été étonné parce que le code bloquait ? Bravo. Si tel est le cas, vous avez vraiment compris comment fonctionnent les boucles.
En effet, ce code ne s'arrêtera jamais de lui-même. Pourquoi ? Parce que la variable compteur vaudra toujours 0 et par conséquent, le test de la boucle while donnera toujours le résultat de 0 < 4 : soit true.
Démonstration par la simulation :
public
class
FelicitationsAuxJoueurs {
public
static
void
main
(
String[] args) {
String [] joueurs =
{
"David"
, "Daniel"
, "Anna"
, "Gregory"
}
;
int
compteur =
0
;
int
nombreJoueurs =
joueurs.length; // soit 4
while
(
compteur /* 0 */
<
nombreJoueurs /* 4 */
) {
// true
String leJoueur =
joueurs[compteur]; //David
if
(
leJoueur.equals
(
"David"
)) {
// true
continue
; // Donc, on revient au test de la boucle while
}
System.out.println
(
"Felicitations, "
+
leJoueur +
" !"
); // Non execute
compteur++
; // Non execute
}
}
}
public
class
FelicitationsAuxJoueurs {
public
static
void
main
(
String[] args) {
String [] joueurs =
{
"David"
, "Daniel"
, "Anna"
, "Gregory"
}
;
int
compteur =
0
;
int
nombreJoueurs =
joueurs.length; // soit 4
while
(
compteur /* 0 */
<
nombreJoueurs /* 4 */
) {
// true
String leJoueur =
joueurs[compteur]; //David
if
(
leJoueur.equals
(
"David"
)) {
// true
continue
; // Donc, on revient au test de la boucle while
}
System.out.println
(
"Felicitations, "
+
leJoueur +
" !"
); // Non execute
compteur++
; // Non execute
}
}
}
public
class
FelicitationsAuxJoueurs {
public
static
void
main
(
String[] args) {
String [] joueurs =
{
"David"
, "Daniel"
, "Anna"
, "Gregory"
}
;
int
compteur =
0
;
int
nombreJoueurs =
joueurs.length; // soit 4
while
(
compteur /* 0 */
<
nombreJoueurs /* 4 */
) {
// true
String leJoueur =
joueurs[compteur]; //David
if
(
leJoueur.equals
(
"David"
)) {
// true
continue
; // Donc, on revient au test de la boucle while
}
System.out.println
(
"Felicitations, "
+
leJoueur +
" !"
); // Non execute
compteur++
; // Non execute
}
}
}
Ainsi de suite ...
III-D. Synthèse▲
Nous avons donc vu :
- comment traiter, dans un switch, tous les cas non pris en compte grâce au mot-clé default ;
- comment utiliser une méthode statique sans initialiser la classe où elle se situe ;
- quel est le danger d'une boucle while mal utilisée : on peut bloquer son application.