programmez-en-d/switch.whata

305 lines
11 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 = "[c switch] et [c case]"
partAs = chapitre
translator = "Raphaël Jakse"
proofreader = "Stéphane Goujet"
]
[c switch] est une structure qui permet de comparer la valeur d'une expression avec de multiples valeurs spéciales. Elle est similaire à une chaîne «~ if, else if, else~ » mais fonctionne un peu différemment. [c case] est utilisé pour spécifier les valeurs à comparer avec l'expression du [c switch]. [c case] fait partie de la structure [c switch] et n'est pas une structure en lui-même.
[c switch] prend une expression entre parenthèses, compare la valeur de cette expression aux valeurs des [c case] et exécute les opérations du [c case] qui est égal à la valeur de l'expression. Sa syntaxe consiste en un bloc [c switch] qui contient une ou plusieurs sections [c case] et une section [c default]~ :
[code=d <<<
switch (expression) {
case valeur_1:
// opérations à exécuter si l'expression est égale à valeur_1
// ...
break;
case valeur_2:
// opérations à exécuter si l'expression est égale à valeur_2
// ...
break;
// ... autres cases ...
default:
// opérations à exécuter si l'expression ne correspond à aucun case
// ...
break;
}
>>>]
Même si elle est utilisée dans des vérifications conditionnelles, l'expression que le [c switch] prend n'est pas utilisée comme une expression logique. Elle n'est pas évaluée comme «~ si cette condition est vraie~ » comme dans la structure [c if]. La valeur de l'expression du [c switch] est utilisée dans des comparaisons d'égalité avec les valeurs des [c case]. C'est similaire à une chaîne «~ if, else if, else~ » qui n'a que des opérations d'égalité~ :
[code=d <<<
auto valeur = expression;
if (valeur == valeur_1) {
// opérations pour valeur_1
// ...
} else if (valeur == valeur_2) {
// opérations pour valeur_2
// ...
}
// ... autres 'else if' ...
} else {
// opérations pour les autres valeurs
// ...
}
>>>]
Cependant, la chaîne «~ if, else if, else~ » ci-dessus n'est pas l'équivalent de la structure [c switch]. Les raisons à cela seront expliquées dans les sections suivantes.
Si une valeur [c case] correspond à la valeur de l'expression du [c switch], alors les opérations qui sont sous ce [c case] sont exécutées. Si aucune valeur ne correspond, alors les opérations qui sont en dessous de [c default] sont exécutées. Les opérations sont exécutées jusqu'à ce qu'une instruction [c break] ou [c goto] est rencontrée.
[ = L'instruction [c goto]
Certains usages de [c goto] sont en général déconseillés dans la plupart des langages de programmation. Cependant, [c goto] est utile dans les structures [c switch] dans quelques rares cas. L'instruction [c goto] sera vue plus en détail dans un chapitre ultérieur.
[c case] n'introduit pas un nouveau bloc comme le fait la structure [c if]. Une fois que les opérations dans un bloc [c if] ou [c else] sont finies, l'évaluation totale de la structure [c if] est également terminée. Ce n'est pas le cas avec les sections [c case]~ ; une fois qu'un [c case] correspondant est trouvé, l'exécution du programme saute vers ce [c case] et exécute les opérations sous ce [c case]. Quand ceci est nécessaire dans certains cas rares, [c goto] fait sauter l'exécution du programme vers le [c case] suivant~ :
[code=d <<<
switch (valeur) {
case 5:
writeln("cinq");
goto case; // continue sur le prochain case
case 4:
writeln("quatre");
break;
default:
writeln("inconnu");
break;
}
>>>]
Si la valeur est 5, l'exécution continue sous la ligne [c case 5:] et le programme affiche «~ ``cinq``~ ». Ensuite, l'instruction [c goto case] fait continuer l'exécution au [c case] suivant, et «~ ``quatre``~ » est également affiché~ :
[output <<<
cinq
quatre
>>>]
[c goto] peut apparaître de trois manières dans les sections [c case]~ :
- [c goto case] fait continuer l'exécution au [c case] suivant~ ;
- [c goto default] fait continuer l'exécution à la section [c default]~ ;
- [c goto case [i expression]] fait continuer l'exécution au [c case] qui correspond à cette expression.
Le programme suivant montre ces trois utilisations en utilisant une boucle [c foreach]~ :
[code=d <<<
import std.stdio;
void main()
{
foreach (valeur; [ 1, 2, 3, 10, 20 ]) {
writefln("--- valeur : %s ---", valeur);
switch (valeur) {
case 1:
writeln("case 1");
goto case;
case 2:
writeln("case 2");
goto case 10;
case 3:
writeln("case 3");
goto default;
case 10:
writeln("case 10");
break;
default:
writeln("default");
break;
}
}
}
>>>]
La sortie :
[output <<<
--- valeur : 1 ---
case 1
case 2
case 10
--- valeur : 2 ---
case 2
case 10
--- valeur : 3 ---
case 3
default
--- valeur : 10 ---
case 10
--- valeur : 20 ---
default
>>>]
]
[ = Le type de l'expression doit être un type entier, une chaîne ou un booléen
Tous les types peuvent être utilisés dans des comparaisons d'égalité dans les structures [c if]. Par contre, le type des expressions du [c switch] est limité aux entiers, aux chaînes et à [c bool].
[code=d <<<
string op = /* ... */;
// ...
switch (op) {
case "ajouter":
resultat = premier + second;
break;
case "soustraire":
resultat = premier - second;
break;
case "multiplier":
resultat = premier * second;
break;
case "diviser":
resultat = premier / second;
break;
default:
throw new Exception(format("Opération inconnue : %s", op));
}
>>>]
[p Note : | le code ci-dessus lève une exception quand l'opération n'est pas reconnue par le programme. Nous verrons les exceptions dans un chapitre ultérieur.]
Même s'il est possible d'utiliser des expression booléennes, comme [c bool] n'a que deux valeurs, utiliser une structure [c if] ou l'opérateur ternaire ([c ?:]) avec ce type est peut-être plus adapté.
]
[ = Les valeurs [c case] doivent être connues lors de la compilation
Avec les structures [c if], les valeurs qui sont des deux côtés de l'opérateur d'égalité peuvent être calculée lors de l'exécution. Par exemple, l'instruction [c if] suivante peut utiliser deux valeurs, une qui est calculée par le programme et une qui est entrée par l'utilisateur~ :
[code=d <<<
if (tentative == nombre) {
writeln("Correct !");
}
>>>]
Par contre, même si la valeur de l'expression du [c switch] est normalement calculée lors de l'exécution, les valeurs des [c case] doivent être connues lors de la compilation.
]
[ = Intervalles de valeurs
Les intervalles de valeurs peuvent être indiqués par des [c ..] entre les [c case]~ :
[code=d <<<
switch (valeurDuDé) {
case 1:
writeln("Vous avez gagné");
break;
case 2: .. case 5:
writeln("Match nul");
break;
case 6:
writeln("J'ai gagné");
break;
default:
/* Le programme ne devrait jamais arriver ici parce que les cases
* précédents couvrent l'intervalle complet des valeurs possibles d'un dé
* (voir l'instruction "final switch" un peu plus loin) */
break;
}
>>>]
Le code qui précède détermine que le jeu se fini par match nul quand la valeur du dé est 2, 3, 4 ou 5.
]
[ = Valeurs distinctes
Supposons que le match nul est obtenu seulement pour les valeurs 2 et 4, plutôt que les valeurs qui sont dans l'intervalle [m ~[2, 5~]]. Les valeurs distinctes d'un [c case] sont séparées par des virgules~ :
[code=d <<<
case 2, 4:
writeln("Match nul");
break;
>>>]
]
[ = L'instruction [c final switch]
Cette structure fonctionne de la même manière qu'un [switch] classique, avec les différences suivantes~ :
- Il ne peut pas y avoir de section [c default]. Notez que cette section n'a aucun sens dans les cas où les sections [c case] couvrent l'intervalle complet de valeurs, comme dans le cas des six valeurs du dé.
- Les intervalles de valeurs ne peuvent pas être utilisés avec les [c case] (on peut cependant utiliser les valeurs distinctes).
- Si l'expression est un type [c enum], toutes les valeurs du type doivent être couvertes par les [c case] (nous verrons les types [c enum] dans le chapitre suivant).
[code=d <<<
int valeurDuDé = 1;
final switch (valeurDuDé) {
case 1:
writeln("Vous avez gagné");
break;
case 2, 3, 4, 5:
writeln("Match nul");
break;
case 6:
writeln("J'ai gagné");
break;
}
>>>]
]
[ = Quand utiliser [c switch]
[c switch] est adapté quand on compare la valeur d'une expression avec un ensemble de valeurs connues lors de la compilation.
Quand il n'y a que deux valeurs à comparer, une instruction [c if] peut avoir plus de sens. Par exemple, pour vérifier si on obtient pile ou face~ :
[code=d <<<
if (resultatPileOuFace == pile) {
// ...
} else {
// ...
}
>>>]
En règle générale, [c switch] est plus adapté quand il y a plus de deux valeurs à comparer.
]
[ = Exercices
# [ Écrivez un programme de calculatrice qui prend en charge les opérations arithmétiques. Le programme lit une première ligne avec l'opération comme une chaîne et ensuite une seconde ligne avec deux valeurs de type [c double] depuis l'entrée. La calculatrice doit afficher le résultat de l'opération. Par exemple, quand l'opération et les valeurs sont «~ ajouter~ » et «~ 5 7~ », le programme devrait afficher 12.
[comment <<< Tel que l'énoncé était rédigé, je comprenais que l'opération et les 2 valeurs étaient à la suite sur la même ligne. >>>]
L'entrée peut être lue comme dans le code suivant~ :
[code=d <<<
string op;
double premier;
double second;
// ...
op = chomp(readln());
readf(" %s %s", &premier, &second);
>>>]
]
# Améliorez la calculatrice pour prendre en charge les opérateurs du type [c +] en plus des mots du type «~ ajouter~ ».
# Levez une exception pour les opérations inconnues.
[[part:corrections/switch | … Les solutions]]
]