IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Cours complet pour apprendre à programmer en D


précédentsommairesuivant

34. switch et case

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. case est utilisé pour spécifier les valeurs à comparer avec l'expression du switch. case fait partie de la structure switch et n'est pas une structure en lui-même.

switch prend une expression entre parenthèses, compare la valeur de cette expression aux valeurs des case et exécute les opérations du case qui est égal à la valeur de l'expression. Sa syntaxe consiste en un bloc switch qui contient une ou plusieurs sections case et une section default :

 
Sélectionnez
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 case ...
 
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 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 if. La valeur de l'expression du switch est utilisée dans des comparaisons d'égalité avec les valeurs des case. C'est similaire à une chaîne if, else if, else qui n'a que des opérations d'égalité :

 
Sélectionnez
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 switch. Les raisons à cela seront expliquées dans les sections suivantes.

Si une valeur case correspond à la valeur de l'expression du switch, alors les opérations qui sont sous ce case sont exécutées. Si aucune valeur ne correspond, alors les opérations qui sont en dessous de default sont exécutées. Les opérations sont exécutées jusqu'à ce qu'une instruction break ou goto est rencontrée.

34-1. L'instruction goto

Certains usages de goto sont en général déconseillés dans la plupart des langages de programmation. Cependant, goto est utile dans les structures switch dans quelques rares cas. L'instruction goto sera vue plus en détail dans un chapitre ultérieur.

case n'introduit pas un nouveau bloc comme le fait la structure if. Une fois que les opérations dans un bloc if ou else sont finies, l'évaluation totale de la structure if est également terminée. Ce n'est pas le cas avec les sections case ; une fois qu'un case correspondant est trouvé, l'exécution du programme saute vers ce case et exécute les opérations sous ce case. Quand ceci est nécessaire dans certains cas rares, goto fait sauter l'exécution du programme vers le case suivant :

 
Sélectionnez
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 case 5: et le programme affiche « cinq ». Ensuite, l'instruction goto case fait continuer l'exécution au case suivant, et « quatre » est également affiché :

 
Sélectionnez
cinq
quatre

goto peut apparaître de trois manières dans les sections case :

  • goto case fait continuer l'exécution au case suivant ;
  • goto default fait continuer l'exécution à la section default ;
  • goto case expression fait continuer l'exécution au case qui correspond à cette expression.

Le programme suivant montre ces trois utilisations en utilisant une boucle foreach :

 
Sélectionnez
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 :

 
Sélectionnez
--- 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

34-2. 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 if. Par contre, le type des expressions du switch est limité aux entiers, aux chaînes et à bool.

 
Sélectionnez
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));
}

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 expressions booléennes, comme bool n'a que deux valeurs, utiliser une structure if ou l'opérateur ternaire (?:) avec ce type est peut-être plus adapté.

34-3. Les valeurs case doivent être connues lors de la compilation

Avec les structures if, les valeurs qui sont des deux côtés de l'opérateur d'égalité peuvent être calculées lors de l'exécution. Par exemple, l'instruction if suivante peut utiliser deux valeurs, une qui est calculée par le programme et une qui est entrée par l'utilisateur :

 
Sélectionnez
if (tentative == nombre) {
   writeln("Correct !");
}

Par contre, même si la valeur de l'expression du switch est normalement calculée lors de l'exécution, les valeurs des case doivent être connues lors de la compilation.

34-4. Intervalles de valeurs

Les intervalles de valeurs peuvent être indiqués par des .. entre les case :

 
Sélectionnez
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 case
    * 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 termine par match nul quand la valeur du dé est 2, 3, 4 ou 5.

34-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 [2,5]. Les valeurs distinctes d'un case sont séparées par des virgules :

 
Sélectionnez
case 2, 4:
   writeln("Match nul");
   break;

34-6. L'instruction final switch

Cette structure fonctionne de la même manière qu'un classique, avec les différences suivantes :

  • il ne peut pas y avoir de section default. Notez que cette section n'a aucun sens dans les cas où les sections 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 case (on peut cependant utiliser les valeurs distinctes) ;
  • si l'expression est un type enum, toutes les valeurs du type doivent être couvertes par les case (nous verrons les types enum dans le chapitre suivant).
 
Sélectionnez
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;
}

34-7. Quand utiliser switch ?

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 if peut avoir plus de sens. Par exemple, pour vérifier si on obtient pile ou face :

 
Sélectionnez
if (resultatPileOuFace == pile) {
   // ...
 
} else {
   // ...
}

En règle générale, switch est plus adapté quand il y a plus de deux valeurs à comparer.

34-8. Exercices

  1. É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 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.
    L'entrée peut être lue comme dans le code suivant :

     
    Sélectionnez
    string op;
    double premier;
    double second;
     
    // ...
     
    op = chomp(readln());
    readf(" %s %s", &premier, &second);
  2. Améliorez la calculatrice pour prendre en charge les opérateurs du type + en plus des mots du type « ajouter ».

  3. Levez une exception pour les opérations inconnues.

Les solutionsswitch et case - Correction.


précédentsommairesuivant