Instrukcja wyboru (ang. switch statement) w zasadzie zawsze może być zastąpiona instrukcjami warunkowymi, ale czasem czytelniej jest użyć właśnie instrukcji wyboru. Jej najbardziej ogólna postać to:
switch (wyr_calk) {
case stala1: lista1
case stala2: lista2
// ...
dafault: lista
}
gdzie
wyr_calk
jest wyrażeniem o wartości całkowitej,
stala1,
stala2, ..., są wyrażeniami
stałymi o wartości całkowitej, a
lista1,
lista2, ..., są listami instrukcji (być może pustymi).
Wyrażeniem stałym całkowitym może być tu liczba podana
w postaci literału, nazwa całkowitej zmiennej ustalonej lub wyrażenie
całkowite składające się z tego typu podwyrażeń.
Liczba fraz
case
może być dowolna. Stałe występujące
w każdej z fraz
case
muszą być różne. Listy instrukcji
mogą też być puste. Fraza
default
jest opcjonalna: jeśli
występuje, to może wystąpić tylko raz, choć niekoniecznie na końcu.
Najpierw obliczane jest wyr_calk. Następnie, jeśli obliczona wartość jest równa wartości którejś ze stałych stala1, stala2, ..., to wykonywane są instrukcje ze wszystkich list instrukcji, poczynając od listy we frazie case odpowiadającej tej stałej. A więc wykonywane są nie tylko instrukcje z listy w znalezionej frazie case, ale również ze wszystkich dalszych list!
Jeśli żadna ze stałych stala1, stala2, ..., nie jest równa wartości wyr_calk, a fraza default istnieje, to wykonywane są wszystkie instrukcje poczynając od tych we frazie default. Jeśli natomiast żadna ze stałych stala1, stala2, ..., nie jest równa wyr_calk, a fraza default nie istnieje, to wykonanie całej instrukcji wyboru uznaje się za zakończone.
Dowolną z instrukcji może być instrukcja zaniechania break. Jeśli sterowanie przejdzie przez tę instrukcję, to wykonanie całej instrukcji wyboru kończy się.
Instrukcję wyboru zilustrowano w poniższym programie; funkcja
sw
powoduje wypisanie różnej liczby gwiazdek w zależności
od wartości argumentu: cztery gwiazdki dla argumentu 1, dwie dla
argumentu 5, zero dla argumentu 2 lub 3 i trzy gwiazdki dla każdej
innej wartości argumentu.
1. #include <iostream>
2. using namespace std;
3.
4. void g( ) {
5. cout << '*';
6. }
7.
8. void sw(int k) {
9. cout << k << ": ";
10. switch ( k ) {
11. default: g( ); ➊
12. case 5: g( ); g( ); ➋
13. case 3:
14. case 2: break; ➌
15. case 1: g( ); g( ); g( ); g( );
16. }
17. cout << endl;
18. }
19.
20. int main() {
21. sw(9);
22. sw(5);
23. sw(4);
24. sw(3);
25. sw(2);
26. sw(1);
27. sw(0);
28. }
Działanie programu widać z wyników
9: ***
5: **
4: ***
3:
2:
1: ****
0: ***
Zauważmy, że dla argumentów różnych od 1, 2, 3, 5 sterowanie
przechodzi do instrukcji występującej we frazie
default
(linia ➊) i przechodzi następnie do instrukcji we frazach
case
odpowiadających wartościom 5, 3 i 2. Dopiero
w linii ➌ napotykana jest instrukcja
break, która kończy
wykonywanie całej instrukcji wyboru. Dlatego drukowane są wtedy trzy
gwiazdki: jedna w linii ➊ i dwie w linii ➋ programu.
Fraza default wcale nie musi, jak widać z programu, występować na końcu.
Jeśli jedną z instrukcji jest instrukcja
return, to
przejście przez nią sterowania spowoduje oczywiście również
zakończenie wykonywania instrukcji wyboru i zakończenie
wykonywania funkcji w której występuje. Funkcja
hexVal
w poniższym programie wyznacza wartość liczbową odpowiadającą
cyfrze szesnastkowej podanej w postaci znaku lub dostarcza -1, jeśli
podany znak nie odpowiada żadnej cyfrze szesnastkowej:
1. #include <iostream>
2. using namespace std;
3.
4. int hexVal(char c) {
5. switch ( c ) {
6. case '0': case '1': case '2': ➊
7. case '3': case '4': case '5':
8. case '6': case '7': case '8':
9. case '9':
10. return c - '0'; ➋
11.
12. case 'a': case 'b': case 'c':
13. case 'd': case 'e':
14. case 'f':
15. return 10 + c - 'a'; ➌
16.
17. case 'A': case 'B': case 'C':
18. case 'D': case 'E':
19. case 'F':
20. return 10 + c - 'A'; ➍
21.
22. default: return -1; ➎
23. }
24. }
25.
26. int main() {
27. cout << "A = " << hexVal('A') << endl
28. << "f = " << hexVal('f') << endl
29. << "9 = " << hexVal('9') << endl
30. << "b = " << hexVal('b') << endl
31. << "Z = " << hexVal('Z') << endl;
32. }
W linii ➊ i trzech następnych zgrupowanych jest wiele fraz case pustych, z wyjątkiem ostatniej, która zawiera instrukcję return. Dzięki temu zawsze, gdy argumentem funkcji jest znak odpowiadający którejś z cyfr, sterowanie dojdzie do linii ➋ zwracając właściwą wartość (bo liczbowo zmienna c ma wartość kodu ASCII odpowiedniej cyfry; odejmując kod ASCII znaku '0' otrzymamy wartość liczbową znaku c). Podobnie dla dowolnej małej litery odpowiadającej którejś z cyfr szesnastkowych sterowanie dojdzie do linii ➌, a dla dużej litery — do linii ➍. Jeśli znak nie odpowiada żadnej cyfrze szesnastkowej, wejdziemy do frazy default i zwrócona zostanie w linii ➎ wartość -1. Wynik tego programu:
A = 10
f = 15
9 = 9
b = 11
Z = -1
T.R. Werner, 21 lutego 2016; 20:17