switchNous avons vu que, lorsquon devait choisir entre deux possibilités, on utilisait une instruction de branchement if...else. Il existe une autre instruction de branchement, nommée switch, dont la syntaxe est la suivante :
switch (expression) {
case constante1 : instructions1;
case constante2 : instructions2;
............................
case constanteN : instructionsN;
default : instructions0;
}
Lexpression expression est évaluée (elle doit être dun type numérique), puis comparée à constante1, constante2, etc., jusquà ce quune identité soit trouvée ; dans ce cas, les instructions qui suivent (il peut y en avoir plusieurs) sont exécutées, jusquà laccolade fermante finale, et non jusquà linstruction case suivante. Si aucune des constantes nest égale à lexpression, ce sont les instructions qui suivent default qui sont exécutées. Cette dernière clause est semblable au else du branchement simple, et peut également être omise.
Il est important de noter que toutes les instructions suivant la constante qui coïncide avec lexpression sont exécutées. Ainsi, si lon écrit :
switch (i) {
case 1 : i = 0;
case 2 : i = 10; // probablement erroné
default i++;
}
la variable i sera mise à 11 si elle valait 1 ou 2 au départ, sinon elle sera incrémentée. En effet, si i vaut 1 au départ, les trois instructions i = 0; i = 10; i++; sont exécutées à la suite.
Dans ce cas, il sagit certainement dune erreur. Pour la corriger, on utilise linstruction dinterruption break, qui interrompt la circulation dans linstruction de branchement, passant directement à celle qui suit laccolade fermante :
switch (i) {
case 1 : i = 0; break;
case 2 : i = 10; break;
default i++;
}
Ici, on a bien le comportement imaginé. Cette utilisation de break dans une instruction switch est extrêmement fréquente ; il est important de ne pas loublier.
Dans certains cas cependant on ne souhaite pas placer de break derrière certaines constantes, en particulier lorsquil y en a plusieurs. Voici par exemple une fonction qui remplace dans une chaîne les caractères accentués par leur équivalent sans accent :
char *sansaccent(char *chaine)
{
for (char *s = chaine; *s; s++)
switch (*s) {
case 'à':; case 'â':; // continuer...
case 'ä': *s = 'a'; break; // ... ici
case 'é':; case 'è':; case 'ê':; // idem
case 'ë': *s = 'e'; break;
case 'ì':; case 'î':; // idem
case 'ï': *s = 'i'; break;
case 'ô':; case 'ò':; // idem
case 'ö': *s = 'o'; break;
case 'ù':; case 'ü':; // idem
case 'û': *s = 'u'; break;
case 'ÿ': *s = 'y'; break;
}
return chaine;
}
Seules les minuscules ont été traitées ; le lecteur étendra sans peine la méthode aux majuscules. On notera le point-virgule obligatoire entre le deux-points et le case suivant, même sil ny a pas dinstruction. Il ny a pas ici de clause default, puisquil ny a pas daction si le caractère nest pas accentué.
Lécriture dun branchement multiple nest pas toujours la meilleure méthode. Il est parfois préférable dutiliser des systèmes plus rapides. Ainsi, dans notre exemple, un tableau de correspondance des caractères initialisé une fois pour toutes aurait permis un traitement plus expéditif.
Dans certains cas, il est franchement impossible dutiliser une instruction switch, parce quelle serait trop pénible à écrire. Ainsi, la fonction toupper de la librairie <ctype.h>, qui transforme un caractère en la majuscule correspondante, devrait être écrite avec un switch :
char toupper(char c)
{
switch (c) {
case 'a' : return 'A';
case 'b' : return 'B';
// etc...
case 'z' : return 'Z';
default : return c;
}
}
Il sagit évidemment dune écriture bien trop longue. On notera toutefois deux points importants à son sujet. Tout dabord, le fait décrire une instruction return nous dispense décrire un break, puisque cela termine directement la fonction. Dautre part, il sagit dune situation typique où le compilateur ne peut pas savoir si tous les cas ont été traités ou non ; en conséquence, si lon oublie la clause default ici essentielle, la fonction retournera une valeur aléatoire si son argument nétait pas une minuscule (cest dailleurs le comportement de la variante _toupper de cette fonction).
| Exercice 4.1 |
Comment programmer plus facilement cette fonction, sans utiliser |
| Voir solution |
Enfin, il ne faut pas tenter dutiliser switch pour des intervalles de nombres, puisquon ne peut pas placer une condition derrière case ; pour la même raison, il vaut mieux ne pas lutiliser avec des décimaux.
Les mots switch, case et default sont réservés en C++.
| Suivant |