在其它類似Ruby的語言中,switch
語句可以處理任意類型的表達(dá)式。一些語言比如Python沒有switch
語句,因為帶有布爾表達(dá)式的if
語句可以做相同的事情。對于這些語言,switch
語句比if
語句更加靈活,然而內(nèi)部的機(jī)制是一樣的。
C中的switch
語句與它們不同,實際上是一個“跳轉(zhuǎn)表”。你只能夠放置結(jié)果為整數(shù)的表達(dá)式,而不是一些隨機(jī)的布爾表達(dá)式,這些整數(shù)用于計算從swicth
頂部到匹配部分的跳轉(zhuǎn)。下面有一段代碼,我要分解它來讓你理解“跳轉(zhuǎn)表”的概念:
#include <stdio.h>
int main(int argc, char *argv[])
{
if(argc != 2) {
printf("ERROR: You need one argument.\n");
// this is how you abort a program
return 1;
}
int i = 0;
for(i = 0; argv[1][i] != '\0'; i++) {
char letter = argv[1][i];
switch(letter) {
case 'a':
case 'A':
printf("%d: 'A'\n", i);
break;
case 'e':
case 'E':
printf("%d: 'E'\n", i);
break;
case 'i':
case 'I':
printf("%d: 'I'\n", i);
break;
case 'o':
case 'O':
printf("%d: 'O'\n", i);
break;
case 'u':
case 'U':
printf("%d: 'U'\n", i);
break;
case 'y':
case 'Y':
if(i > 2) {
// it's only sometimes Y
printf("%d: 'Y'\n", i);
}
break;
default:
printf("%d: %c is not a vowel\n", i, letter);
}
}
return 0;
}
在這個程序中我們接受了單一的命令行參數(shù),并且用一種極其復(fù)雜的方式打印出所有原因,來向你演示switch
語句。下面是swicth
語句的工作原理:
swicth
語句的頂端,我們先把它記為地址Y。switch
中的表達(dá)式求值,產(chǎn)生一個數(shù)字。在上面的例子中,數(shù)字為argv[1]
中字母的原始的ASCLL碼。case 'A'
的case
代碼塊翻譯成這個程序中距離語句頂端的地址,所以case 'A'
就在Y + 'A'
處。Y+letter
位于switch
語句中,如果距離太遠(yuǎn)則會將其調(diào)整為Y+Default
。case
代碼塊中有break
而另外一些沒有的原因。'a'
,那它就會跳到case 'a'
,它里面沒有break
語句,所以它會貫穿執(zhí)行底下帶有代碼和break
的case 'A'
。break
完全跳出switch
語句塊。譯者注:更常見的情況是,gcc會在空白處單獨構(gòu)建一張?zhí)D(zhuǎn)表,各個偏移處存放對應(yīng)的
case
語句的地址。Y不是switch
語句的起始地址,而是這張表的起始地址。程序會跳轉(zhuǎn)到*(Y + 'A')
而不是Y + 'A'
處。
這是對swicth
語句工作原理的一個深究,然而實際操作中你只需要記住下面幾條簡單的原則:
default:
分支,可以讓你接住被忽略的輸入。//fallthrough
的注釋。case
和break
,再編寫其中的代碼。if
語句代替。下面是我運(yùn)行它的一個例子,也演示了傳入命令行參數(shù)的不同方法:
$ make ex13
cc -Wall -g ex13.c -o ex13
$ ./ex13
ERROR: You need one argument.
$
$ ./ex13 Zed
0: Z is not a vowel
1: 'E'
2: d is not a vowel
$
$ ./ex13 Zed Shaw
ERROR: You need one argument.
$
$ ./ex13 "Zed Shaw"
0: Z is not a vowel
1: 'E'
2: d is not a vowel
3: is not a vowel
4: S is not a vowel
5: h is not a vowel
6: 'A'
7: w is not a vowel
$
記住在代碼的開始有個if
語句,當(dāng)沒有提供足夠的參數(shù)時使用return 1
返回。返回非0是你提示操作系統(tǒng)程序出錯的辦法。任何大于0的值都可以在腳本中測試,其它程序會由此知道發(fā)生了什么。
破壞一個switch
語句塊太容易了。下面是一些方法,你可以挑一個來用:
break
,程序就會運(yùn)行兩個或多個代碼塊,這些都是你不想運(yùn)行的。default
,程序會在靜默中忽略你所忘記的值。switch
中,比如帶有奇怪的值的int
。switch
中是否未初始化的值。你也可以使用一些別的方法使這個程序崩潰。試著看你能不能自己做到它。
switch
中移除所有額外的大寫字母。','
(逗號)在for
循環(huán)中初始化letter
。for
循環(huán)來讓它處理你傳入的所有命令行參數(shù)。switch
語句轉(zhuǎn)為if
語句,你更喜歡哪個呢?if
代碼塊外面寫了個break
。這樣會產(chǎn)生什么效果?如果把它移進(jìn)if
代碼塊,會發(fā)生什么?自己試著解答它,并證明你是正確的。