دستور switch نوعی تصمیمگیری چندحالته است که بررسی میکند آیا مقدار یک عبارت با یکی از چند مقدار ثابت عددی برابر است یا نه، و بر اساس آن شاخهی مناسب را اجرا میکند:
switch (expression) {
case const-expr: statements
case const-expr: statements
default: statements
}
هر case با یک یا چند مقدار ثابت عددی برچسبگذاری میشود.
اگر مقدار عبارت با یکی از caseها برابر باشد، اجرا از همان نقطه شروع میشود. تمام مقادیر case باید متفاوت باشند.
بخش default زمانی اجرا میشود که هیچکدام از caseها منطبق نباشند.
وجود default اختیاری است — اگر نباشد و هیچ caseی هم منطبق نشود، هیچ کاری انجام نمیشود.
ترتیب قرارگیری caseها و default آزاد است.
در فصل ۱، برنامهای نوشتیم که تعداد رقمها، فاصلهها (white space) و سایر کاراکترها را میشمرد، با استفاده از if ... else if ... else.
در اینجا همان برنامه را با switch بازنویسی کردهایم:
#include <stdio.h>
main() /* count digits, white space, others */
{
int c, i, nwhite, nother, ndigit[10];
nwhite = nother = 0;
for (i = 0; i < 10; i++)
ndigit[i] = 0;
while ((c = getchar()) != EOF) {
switch (c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
ndigit[c - '0']++;
break;
case ' ':
case '\n':
case '\t':
nwhite++;
break;
default:
nother++;
break;
}
}
printf("digits =");
for (i = 0; i < 10; i++)
printf(" %d", ndigit[i]);
printf(", white space = %d, other = %d\n", nwhite, nother);
return 0;
}
دستور break باعث خروج فوری از switch میشود.
چون caseها فقط نقش برچسب دارند، اگر از break استفاده نکنید، اجرای برنامه به case بعدی سرازیر (fall through) میشود.
برای خروج صریح از switch معمولاً از break یا return استفاده میشود.
(همچنین break در حلقههای while، for و do هم کاربرد دارد — که در ادامهی فصل به آن میرسیم.)
سرازیر شدن بین caseها یک ویژگی دولبه است.
از یک سو، امکان میدهد چند case را به یک عمل متصل کنید (مثل مثال بالا برای ارقام)، اما از سوی دیگر باعث میشود در حالت عادی باید در انتهای هر case یک break بنویسید تا جلوی سرازیر شدن ناخواسته گرفته شود.
چنین رفتارهایی معمولاً شکننده هستند و در تغییرات بعدی برنامه ممکن است باگ ایجاد کنند.
به جز زمانی که چند case عمداً به یک دستور اشاره دارند، از سرازیر شدن باید به ندرت استفاده کرد و حتماً آن را با کامنت توضیح دهید.
بهعنوان یک عادت خوب، بعد از آخرین case (مثلاً default) هم break بگذارید — حتی اگر از نظر منطقی لازم نباشد.
چون ممکن است بعداً کسی case جدیدی به انتها اضافه کند، و همین کار کوچک میتواند جلوی یک باگ بزرگ را بگیرد.
تمرین 2-3:
تابعی بنویسید به نام escape(s, t) که هنگام کپی رشتهی t به s، کاراکترهایی مثل newline و tab را به توالی escape قابلنمایش (مثل \n و \t) تبدیل کند.
برای این کار از switch استفاده کنید.
همچنین تابعی در جهت برعکس بنویسید که توالیهای escape را به کاراکترهای واقعی تبدیل کند.