programmez-en-d/ternaire.whata

175 lines
6.1 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[set
title = "L'opérateur ternaire [c ?:]"
partAs = chapitre
translator = "Raphaël Jakse"
proofreader = "Stéphane Goujet"
]
L'opérateur ternaire [c ?:] a un fonctionnement très similaire de celui de l'instruction [c if-else]~ :
[code=d <<<
if (/* condition */) {
/* ... expression(s) à exécuter si vrai */
} else {
/* ... expression(s) à exécuter si faux */
}
>>>]
L'instruction [c if] exécute soit le bloc correspondant au cas où la condition est vraie, soit le bloc correspondant au cas où la condition est fausse. Comme vous devez vous en rappeler, étant une instruction, elle n'a pas de valeur~ ; [c if] affecte principalement l'exécution des blocs de code.
En revanche, l'opérateur [c ?:] est une expression. En plus de fonctionner d'une manière similaire à l'instruction [c if-else], il produit une valeur. Ce qui suit est un équivalent du code ci-dessus~ :
[code=d <<<
/* condition */ ? /* expression si vrai */ : /* expression si faux */
>>>]
L'opérateur [c ?:] utilise trois expressions, d'où son nom d'opérateur ternaire.
La valeur qui est produite par cet opérateur est soit la valeur de l'expression si vrai, soit celle de l'expression si faux. Du fait que c'est une expression, il peut être utilisé partout où les expressions peuvent être utilisées.
Les exemples suivant comparent l'opérateur [c ?:] et l'instruction [c if-else]. L'opérateur ternaire est plus concis dans les cas similaires à ces exemples.
- [
[p Initialisation. |
Pour initialiser à 366 s'il s'agit d'une année bissextile, à 365 sinon~ :
]
[code=d <<<
int jours = estAnneeBissextile ? 366 : 365;
>>>]
Avec [c if], une façon de faire est de définir la variable sans valeur initiale explicite et d'affecter la valeur voulue~ :
[code=d <<<
int jours;
if (estAnneeBissextile) {
jours = 366;
} else {
jours = 365;
}
>>>]
Une alternative avec [c if] est d'initialiser la variable avec la valeur des années non bissextiles et de l'incrémenter s'il s'agit d'une année bissextile~ :
[code=d <<<
int jours = 365;
if (estAnneeBissextile) {
++jours;
}
>>>]
]
- [
[p Affichage. |
Afficher un message différemment selon une condition~ :
]
[code=d <<<
writeln("Le verre est à moitié ",
estOptimiste ? "plein." : "vide.");
>>>]
Avec [c if], la première et la dernière parties peuvent être affichées séparément~ :
[code=d <<<
write("Le verre est à moitié ");
if (estOptimiste) {
writeln("plein.");
} else {
writeln("vide.");
}
>>>]
Ou alors, le message entier peut être affiché séparément~ :
[code=d <<<
if (estOptimiste) {
writeln("Le verre est à moitié plein.");
} else {
writeln("Le verre est à moitié vide.");
}
>>>]
]
- [
[p Calcul. |
Augmenter le score d'un gagnant au backgammon de 2 points ou 1 point selon si le jeu s'est fini sur un gammon ou pas~ :
]
[code=d <<<
score += estGammon ? 2 : 1;
>>>]
Transposition directe avec [c if]~ :
[code=d <<<
if (estGammon) {
score += 2;
} else {
score += 1;
}
>>>]
Ou alors, on peut d'abord incrémenter de 1 et incrémenter une seconde fois s'il y a eu gammon~ :
[code=d <<<
++score;
if (estGammon) {
++score;
}
>>>]
]
Comme on peut le voir dans les exemples précédant, le code est plus consis et plus clair avec l'opérateur ternaire dans certaines situations.
[ = Les types des expressions de sélection doivent correspondre
La valeur de l'opérateur [c ?:] est soit la valeur de l'expression si vrai, soit la valeur de l'expression si faux. Les types de ces expressions n'ont pas besoin d'être les mêmes mais ils doivent correspondre. Par exemple, ils peuvent être tous deux des types entiers comme [c int] et [c long] mais ne peuvent pas être des types qui ne se correspondent pas, comme [c int] et [c string].
Dans les exemples précédents, les valeurs sélectionnées selon la valeur de [c estAnneeBissextile] étaient 366 et 365. Les deux valeurs sont du type [c int] et se correspondent.
Pour voir une erreur de compilation causée par des valeurs des expressions ne correspondant pas, considérons la composition d'un message qui rapporte le nombre d'objets à expédier. Affichons «~ Une douzaine~ » quand la valeur est 12~ : «~ Une douzaine d'objets seront expédiés~ ». Dans les autres cas, on affiche le nombre exact~ : «~ 3 objets seront expédiés~ ».
On pourrait penser que la partie variable du message peut être sélectionnée avec l'opérateur [c ?:]~ :
[code=d <<<
writeln((nombre == 12) ? "Une douzaine d'" : nombre, // ← ERREUR de compilation
" objets seront expédiés.");
>>>]
Les expression ne correspondent pas parce que le type de [c "Une douzaine d'"] est [c string] et le type de [c nombre] est [c int].
Une solution est de convertir [c nombre] en [c string]. La fonction [c to!string] du module [c std.conv] donne une valeur de type [c string] depuis le paramètre donné :
[code=d <<<
import std.conv;
// ...
writeln((nombre == 12) ? "Une douzaine d'" : to!string(nombre),
" objets seront expédiés.");
>>>]
Maintenant que les expressions de sélection de l'opérateur [c ?:] sont toutes deux du type [c string], le code compile et affiche le message attendu.
]
[ = Exercice
Le programme doit lire une [i valeur nette] de type [c int]. Quand cette valeur est positive, on l'interprète comme un gain et quand elle est négative, on l'interprète comme une perte.
Le programme doit afficher un message qui contient «~ gagnés~ » ou «~ perdus~ », selon si la quantité est positive ou négative. Par exemple, «~ 100€ gagnés~ » ou «~ 70€ perdus~ ». Même s'il se pourrait que ce soit plus approprié, n'utilisez pas l'instruction [c if] dans cet exercice.
[[part:corrections/ternaire | … La solution]]
]