在之前的課程中,我們已經(jīng)知道世界上有很多編程語言,有些相互之間很類似,其中不少都受了 C語言的啟發(fā)。
事實上,C語言是很早之前被發(fā)明的(1972 年左右),所以它也成了很多近代編程語言的參考模板。
我們說編程語言相似,是說他們都汲取了它們的前輩的編程基礎(chǔ)。
說到編程基礎(chǔ),那就有很多了。其中,我們已經(jīng)學(xué)過的有:變量,運算。這一課我們來學(xué)習(xí)條件表達(dá)式。
2. if…else 條件表達(dá)式
簡單來說,條件表達(dá)式使我們可以測試變量。
打個比方,我們可以這樣說: “假如變量的值等于 7,就執(zhí)行這樣那樣的操作?!?/p>
如果 C語言里面不能做“等于”的判斷,那該多可惜啊。我們還要做“小于”,“大于”,“大于等于”,“小于等于”,“不等于”的判斷。
不必?fù)?dān)心,C語言都為你預(yù)備好了。
為了學(xué)習(xí) if…else 語句,我們準(zhǔn)備按照下面的順序來進(jìn)行:
- 預(yù)先需要了解的幾個符號
- if 語句
- else 語句
- else…if 語句
- 多個條件
- 一些需要避免的錯誤
在我們學(xué)習(xí)寫 if…else 表達(dá)式前,須要先了解幾個基本符號,這些符號對于實現(xiàn)條件判斷是必不可少的。
幾個需要了解的符號
下表列出了 C語言中需要用心記住的幾個符號:
| 符號 | 含義 |
|---|---|
| == | 等于 |
| > | 大于 |
| < | 小于 |
| >= | 大于等于 |
| <= | 小于等于 |
| != | 不等于 |
判斷“等于”需要兩個等號( == )! 一個很常見的錯誤是只寫一個等號,在 C語言中一個等號和兩個等號具有不同的含義。一個等號表示賦值,兩個等號才是判斷是否相等。
其實做為一個學(xué)習(xí)者,有一個學(xué)習(xí)的氛圍跟一個交流圈子特別重要這里我推薦一個C/C++基礎(chǔ)交流583650410,不管你是小白還是轉(zhuǎn)行人士歡迎入駐,大家一起交流成長。
單一的 if 語句
if 表示“如果,假如”。
邏輯是這樣的:
如果變量的值是這樣 則 執(zhí)行如下操作
所以單一的 if 語句是這樣寫的:
- 先寫一個 if 。
- 接著寫一個括號 (),在這個括號中寫條件。
- 接著寫一個大括號 {},在大括號中寫在 () 中條件為真時所要執(zhí)行的操作。
格式如下:
if (/* 條件 */)
{
// 如果條件為真,所要執(zhí)行的操作
}
復(fù)制代碼
我們把上面注釋的地方換成實際的代碼,寫一個程序測試一下:
#include <stdio.h>
int main(int argc, char *argv[]) {
int age = 20;
if (age >= 18)
{
printf("你成年了!\n");
}
return 0;
}
復(fù)制代碼
解釋:
int age = 20;
復(fù)制代碼
首先定義一個 int 型的變量,名字是 age(表示“年齡”),值為 20。
if 語句的括號 () 中的條件是 age >=18 ,意思是“假如 age 的值大于或等于 18”。
if 語句的大括號 {} 中的語句是
printf("你成年了!\n");
復(fù)制代碼
就是說當(dāng) age 的值大于或等于 18 時,顯示“你成年了!”這句話。
因為程序中變量 age 的值是 20, 大于 18,所以條件為真,所以程序運行起來后顯示:
你成年了!
復(fù)制代碼
如果我們把變量 age 的值改為 12,再次運行程序,什么也沒顯示,因為 12 小于 18,所以 age >= 18 這個條件不為真,不執(zhí)行大括號里的 printf 語句。
嘮叨一下代碼的格式
假如我們將上面的代碼寫成這樣:
if(age>=18){printf("你成年了!");}
復(fù)制代碼
程序也是可以正確運行的,但是 非常不推薦 這樣的代碼格式!
如果我們的程序沒有空行,沒有空格,不縮進(jìn),都寫在一行里,那將會使代碼非常難以閱讀。
所以從一開始學(xué)習(xí)編程就請養(yǎng)成良好的編碼習(xí)慣,不然以后寫一些大型程序,別人根本不知道怎么閱讀你的代碼,你也會迷失在自己的代碼里。
推薦看林銳老師的《高質(zhì)量C++/C編程指南》一書,里面提到了編碼規(guī)范。
當(dāng)然,每個程序員的代碼風(fēng)格都不一樣,但是我們推薦大家遵從本系列課程中的代碼格式或者一些著名公司的代碼格式(例如 Google,阿里,等等),因為是比較通用的編碼格式。
else 語句
現(xiàn)在你知道怎么寫單一的 if 語句了。那當(dāng)條件為假時,我們想要電腦也執(zhí)行對應(yīng)的操作怎么辦呢?對了,此時就輪到 else 關(guān)鍵字出場了。
else 表示“否則”。
但是 else 語句一定要跟 if 語句配合才能使用,獨立的 else 語句是不可用的!
至于關(guān)鍵字,是電腦語言里事先定義的,有特別意義的標(biāo)識符,有時又叫保留字,是有特別意義的變量。 C語言有不少關(guān)鍵字,比如 int,float,char,double,if,else,等,暫時我們不多涉及,可以去了解一下。之前關(guān)于變量的那一課,提到變量的命名時,其實漏講了一點: 變量的名字不要跟關(guān)鍵字重名 。
所以一個完整的 if...else 語句的格式是:
if (/* 條件 */)
{
// 條件為真的時候,所要執(zhí)行的操作
}
else // 如果上面 () 里的條件為假
{
// 條件為假的時候,所要執(zhí)行的操作
}
復(fù)制代碼
再用之前測試年齡的例子,來寫一下實際的程序
if (age >= 18) // 如果 age 變量的值大于或等于 18
{
printf("你成年了!");
}
else // 如果age變量的值小于 18
{
printf("你還未成年,可以適當(dāng)任性!");
}
復(fù)制代碼
如果 age 的值大于或等于 18,則打印“你成年了!”;如果 age 的值小于 18,則打印“你還未成年,可以任性!”。
else...if 語句
上面我們學(xué)習(xí)了如何用單一的 if 語句,以及 if...else 語句
其實除了“假如...”(if 語句)和“否則...”(else 語句),還有else...if(“又假如”)語句,用于在 if 語句的條件不為真時對其他的情況的判斷,else…if 語句放在 if 語句和 else 語句之間。
邏輯是這樣的:
如果變量值為 A, 則 執(zhí)行 if 對應(yīng)操作; 如果 變量值不為 A,而為 B, 則 執(zhí)行 else...if 對應(yīng)操作; 如果 變量值不為 A 也不為 B, 則 執(zhí)行 else 對應(yīng)操作。
我們也用一個實例來看一下 if,else…if 和 else 合在一起用的情況:
if (age >= 18) // 如果 age 變量的值大于或等于 18
{
printf("你成年了 !");
}
else if (age > 2) // 如果 age 小于 18 但是大于 2
{
printf("還好你不是太年幼。");
}
else // 如果 age 小于或等于 2
{
printf("mama, guagua, blablabla..."); // 兒語,聽不懂
}
復(fù)制代碼
流程是這樣的:
首先判斷第一個 if 語句中的括號里的表達(dá)式,如果為真,則執(zhí)行第一個大括號里的語句。
如果 if 的條件不為真,則接著判斷 else…if 語句的括號里的表達(dá)式,如果為真,則執(zhí)行對應(yīng)的大括號里面的語句。
如果 if 和 else…if 里的表達(dá)式都為假,則無需再判斷,直接執(zhí)行 else 語句的大括號里的命令。
在完整的條件語句塊中,else…if 和 else 語句不是必須的,但是必須要有一個 if 語句。
我們可以寫任意多的 else…if 語句,但是 if 語句和 else 語句則都是最多有一個。
else 后面是沒有括號 () 的,但是 if 和 else…if 后面都有括號,也就是都包含判斷條件,應(yīng)該不難理解吧,很合乎邏輯。
3. 多個條件
我們也可以在條件語句的括號 () 中測試多個條件表達(dá)式。
例如,你想要測試這個人的年齡是不是介于 18 歲和 25 歲之間,就需要兩個條件表達(dá)式來判斷了。
為了達(dá)成我們的目的,我們需要用到新的符號:
| 符號 | 含義 |
|---|---|
| && | 邏輯與 |
| II | 邏輯或 |
| ! | 邏輯非 |
本來其實上表中的幾個應(yīng)該也叫做:與,或,非。但為什么叫“邏輯與”,“邏輯或”和“邏輯非”呢?
那是因為之后我們還會學(xué)到 & , | 等符號,稱為“按位或”和“按位與”。暫時不用知道什么意思,之后會學(xué)到。
邏輯與
為了做邏輯與判斷,我們則要用到兩個 & 符號。這個符號在美式鍵盤上需要按下 Shift + 數(shù)字鍵 7。
如果我們要做上面提到過的年齡的判斷,則需要用邏輯與:
if (age > 18 && age < 25)
復(fù)制代碼
兩個 & 號連在一起表示邏輯與,就是說當(dāng)兩邊的表達(dá)式都為真時,括號中的整個表達(dá)式才為真,所以這里只有當(dāng) age 大于 18 并且小于 25 的情況下,括號里的表達(dá)式才為真。
邏輯或
為了做邏輯或判斷,我們則要用到兩個 | 符號。這個符號在美式鍵盤上需要按下 Shift + \ 鍵。
邏輯或只要其兩邊的兩個表達(dá)式有一個為真,整個表達(dá)式就為真。
假設(shè)我們現(xiàn)在要寫一個程序,目的是判斷一個人是不是夠資格開設(shè)銀行賬戶。
眾所周知,要開一個銀行賬戶,申請人不能太年幼(我們假定需要大于 20 歲)或者有很多錢(“有錢任性”嘛,即使是 10 歲小孩,也得讓他開戶。開個玩笑~)。
所以我們的程序如下:
if (age > 20 || money > 150000)
{
printf("歡迎來到**銀行 !");
}
else
{
printf("我還不夠資格,悲催啊 !");
}
復(fù)制代碼
所以這個測試只要申請人年齡大于 20 歲或者擁有超過 15 萬現(xiàn)金時,就可以讓其開戶。
邏輯非
我們最后要看的符號是感嘆號 ! ,表示“取反”,加在表達(dá)式之前。這個符號在美式鍵盤上需要按下 Shift + 數(shù)字鍵 1。
如果表達(dá)式為真,那么加上感嘆號則為假;如果表達(dá)式為假,那么加上感嘆號則為真。就是跟你“唱反調(diào)”。
例如:
if (!(age < 18))
復(fù)制代碼
上面的表達(dá)式表示“假如已經(jīng)成年”(不小于 18 歲)。
當(dāng)然,邏輯與和邏輯或可以連用,甚至多個一起用,例如:
if ((age > 18 && age < 25) || age < 4)
復(fù)制代碼
其實做為一個學(xué)習(xí)者,有一個學(xué)習(xí)的氛圍跟一個交流圈子特別重要這里我推薦一個C/C++基礎(chǔ)交流583650410,不管你是小白還是轉(zhuǎn)行人士歡迎入駐,大家一起交流成長。
4. 一些容易犯的錯誤
== 號
不要忘了之前講過的 == (兩個等號)是用于判斷是否相等。例如:
if (age == 18)
{
printf("你剛成年 !");
}
復(fù)制代碼
上例中如果錯把 == (兩個等號)寫成了 = (單個等號),那后果很嚴(yán)重,表達(dá)式就變成 age = 18 了。單個等號是賦值,所以 age 變?yōu)?18,整個表達(dá)式的值變?yōu)?18,就起不到判斷的作用了。
一種避免這樣錯誤的寫法是 18 == age ,這樣如果我們漏寫了一個等號,變成 18 = age ,那編譯器會報錯,因為常量(例如 18)不能做左值。
關(guān)于左值和右值,可以去搜索網(wǎng)上的資料,簡單來說,位于賦值運算符兩側(cè)的兩個值,左邊的就叫左值,右邊的就叫右值。
多余的分號(;)
還有一個經(jīng)常會犯的錯誤是:在 if 的括號或者 else...if 的括號后面多加了一個分號,如下:
if (age == 18); // 注意這個分號,本來不應(yīng)該出現(xiàn)的
{
printf("你剛好成年");
}
復(fù)制代碼
上面的代碼實際上相當(dāng)于
if (age == 18)
{
;
}
{
printf ("你剛好成年");
}
復(fù)制代碼
看到?jīng)]有,分號就相當(dāng)于 if 語句的大括號里的執(zhí)行語句,而 ; 是空語句,什么也不執(zhí)行。
我們原先想讓其在 age 等于 18 時執(zhí)行的 printf 語句卻成了一個必定會被執(zhí)行的語句,不論 age 的值是不是等于 18(大括號是可以把多個語句集合起來的分隔區(qū)域,可以拿掉大括號再來理解)。
可能有點暈,請多看幾遍代碼。
5. 布爾值,條件語句的核心
我們現(xiàn)在更加深入地來看 if...else 條件語句。事實上,條件表達(dá)式(這里指括號里的表達(dá)式)在其內(nèi)部是做了布爾值的判斷。
布爾類型英語叫 boolean,是只能取“真”或者“假”的一種變量類型。
事實上,在其他的一些編程語言,如 Java,C++,C# 中,本身定義了 boolean 類型,只能有兩個值,true(表示“真”)和 false(表示“假”)。
但是 C語言沒有定義 boolean 類型,怎么辦呢?
不用擔(dān)心,C語言把零作為假,非零的一切值都算為真。
我們可以做幾個小測試來加深理解:
if (1)
{
printf("真!");
}
else
{
printf("假!");
}
復(fù)制代碼
以上代碼執(zhí)行結(jié)果是顯示:
真!
復(fù)制代碼
我們可以把 1 換成非零的任意 int 型整數(shù):5,9,13,-2,448,等等,結(jié)果都會顯示: 真! 。
if (0)
{
printf("真!");
}
else
{
printf("假!");
}
復(fù)制代碼
以上代碼執(zhí)行結(jié)果是顯示:
假!
復(fù)制代碼
所以 C語言中只有 0 是假,其他非零的值都被看作真。這就是 C語言的“布爾類型”,因為 C語言沒有定義真正的布爾值類型。
必要的一些解釋
事實上,每當(dāng)你在條件表達(dá)式里做判斷時,如果表達(dá)式是真的,則整個表達(dá)式的值是 1;如果是假的,則整個表達(dá)式的值為 0。
例如:
if (age >= 18)
復(fù)制代碼
假如 age 的值為 25,是大于等于 18 的,那么 age >= 18 這個表達(dá)式的值為真,電腦其實會把它替換為 1。
假如 age 的值為 15,是小于 18 的,那么 age >= 18 這個表達(dá)式的值為假,電腦其實會把它替換為 0。
用變量來測試一下:
#include <stdio.h>
int main(int argc, char *argv[]) {
int age = 25;
int adult = 0;
adult = age >= 18;
printf("adult 的值是 : %d\n", adult);
return 0;
}
復(fù)制代碼
運行,顯示:
adult 的值是 : 1
復(fù)制代碼
如果 age 為 15,則顯示:
adult 的值是 : 0
復(fù)制代碼
那句 adult = age >= 18; ,其實等價于 adult = (age >= 18); 。因為 >= 這個符號的優(yōu)先級比 = 符號要高。運算符的優(yōu)先級,不需要死記硬背,如果實在記不住,就加上括號 () 吧。
這里的 adult 其實已經(jīng)是一個 C語言中的“布爾值”了。
6. switch 語句
我們剛學(xué)的 if...else 類型的條件語句是最常用的。
但是 C語言還給出了 if...else 語句的一個替代語句:switch 語句。
因為,有時候,當(dāng)我們的條件判斷很多時,就會感覺冗余。例如下面的代碼:
if (age == 2)
{
printf("寶寶,你好 !");
}
else if (age == 6)
{
printf("小朋友,你好 !");
}
else if (age == 12)
{
printf("少年,你好 !");
}
else if (age == 16)
{
printf("青少年,你好 !");
}
else if (age == 18)
{
printf("成年人,你好 !");
}
else if (age == 67)
{
printf("爺爺,你好 !");
}
else
{
printf("對你的年齡我還沒有對應(yīng)的問候方式。");
}
復(fù)制代碼
之前我們也說過,程序員(IT 工作者)是很會“偷懶”的,他們不喜歡做重復(fù)、單調(diào)的工作。
因此,為了避免重復(fù)寫一些代碼,他們發(fā)明了新的 switch 語句。switch 表示“轉(zhuǎn)換,替換”。
以下展示了用 switch 語句改寫的上面那個 if...else 語句的例子:
switch (age)
{
case 2:
printf("寶寶,你好 !");
break;
case 6:
printf("小朋友,你好 !");
break;
case 12:
printf("少年,你好 !");
break;
case 16:
printf("青少年,你好 !");
break;
case 18:
printf("成年人,你好 !");
break;
case 67:
printf("爺爺,你好 !");
break;
default:
printf("對你的年齡我還沒有對應(yīng)的問候方式。");
break;
}
復(fù)制代碼
switch 語句雖然沒有 if...else 語句那么常用,但是對于判斷情況很多的條件語句,用 switch 可以少寫不少代碼呢,而且程序也一目了然,比較清晰。
switch 語句的格式
首先,寫
switch這個關(guān)鍵字,接著寫一個括號,括號里面是要判斷的變量。case加上變量可能的取值,再加一個冒號(:),再加上對應(yīng)取值時的操作,再加上一個break;。
要注意:case 后面的值只能是整型或字符型的常量或常量表達(dá)式。
default負(fù)責(zé)處理除了各個 case 以外的情況。多個 case 就相當(dāng)于 if...else 語句里的 if 和 else...if 。
default 相當(dāng)于 if...else 語句里的 else。
想想看,switch 語句是不是很像我們?nèi)ワ埖暧貌停?/p>
服務(wù)員拿了一個酒水單給你,上面有好多飲料,就像好多個 case 后面的取值,你點一種飲料,服務(wù)生就去給你拿對應(yīng)的飲料,這個操作就像 case 的冒號后面的語句。
假如你什么都不要,說:還是給我來杯水吧,那服務(wù)生就只能給你拿一杯水了,就相當(dāng)于 default。
每個 case 語句的結(jié)尾絕對不要忘了加 break,否則將導(dǎo)致多個分支重疊(除非有意使多個分支重疊)。
假如上例中我們少寫了一個 break; ,看看會變成怎樣:
int age = 2;
switch (age)
{
case 2:
printf("寶寶,你好 !\n");
// 這里我們沒有寫 break;
case 6:
printf("小朋友,你好 !\n");
break;
case 12:
printf("少年,你好 !");
break;
case 16:
printf("青少年,你好 !");
break;
case 18:
printf("成年人,你好 !");
break;
case 67:
printf("爺爺,你好 !");
break;
default:
printf("對你的年齡我還沒有對應(yīng)的問候方式。");
break;
}
復(fù)制代碼
上面的代碼,當(dāng) age 的值為 2 的時候,顯示的內(nèi)容是:
寶寶,你好 !
小朋友,你好 !
復(fù)制代碼
很奇怪吧,這是因為沒有 break,程序就不跳出 switch 的大括號,而繼續(xù)執(zhí)行,“穿透”了 case 6 。雖然 age 的值是 2,不等于 6,但是也執(zhí)行了 case 6 對應(yīng)的語句
printf("小朋友,你好 !\n");
復(fù)制代碼
因為 case 6 的執(zhí)行語句后面加了 break,所以程序執(zhí)行完
printf("小朋友,你好 !\n");
復(fù)制代碼
就跳出了 switch 語句。當(dāng)然有時候也有故意不加 break,使得多個情況做同一個操作的,例如:
switch (age)
{
case 2:
case 6:
case 12:
case 16:
printf("未成年人,你好 !");
break;
case 18:
printf("成年人,你好 !");
break;
case 67:
printf("爺爺,你好 !");
break;
default:
printf("對你的年齡我還沒有對應(yīng)的問候方式。");
break;
}
復(fù)制代碼
上面的代碼,當(dāng) age 的值為 2 或 6 或 12 或 16 時,都會執(zhí)行
printf("未成年人,你好 !");
復(fù)制代碼
是不是也很妙呢?
break 關(guān)鍵字的作用不僅于此(用于跳出 switch 語句),在下一課 循環(huán)語句 中我們會更深入學(xué)習(xí) break 的作用。
還有要注意的是:最后必需使用 default 分支。 雖然 default 不加其實也不會報錯,但即使程序真的不需要 default 處理,也應(yīng)該保留語句,這樣做并非畫蛇添足,可以避免讓人誤以為你忘了 default 處理。 要把 default 子句用于檢查真正的默認(rèn)情況。
稍微有點暈?沒關(guān)系,讓我們用一個更完整的例子來加深對 switch 語句的理解:
假設(shè)你到了一個飯店,服務(wù)員給你看當(dāng)日菜單:
=== 菜單 ===
- 北京烤鴨
- 鍋包肉
- 地三鮮
- 梅菜扣肉
您的選擇是?
然后根據(jù)你的選擇做出不同反應(yīng)。應(yīng)該怎么寫呢?希望不要看答案,先自己寫代碼試試。
下面給出完整的示例程序:
#include <stdio.h>
int main(int argc, char *argv[]) {
int choiceMenu;
printf("=== 菜單 ===\n\n");
printf("1\. 北京烤鴨\n");
printf("2\. 鍋包肉\n");
printf("3\. 地三鮮\n");
printf("4\. 梅菜扣肉\n");
printf("\n您的選擇是 ? ");
scanf("%d", &choiceMenu);
printf("\n");
switch (choiceMenu)
{
case 1:
printf("您選了北京烤鴨。這是本店的招牌菜!");
break;
case 2:
printf("您選了鍋包肉。您是東北人吧?");
break;
case 3:
printf("您選了地三鮮。實惠好吃,就是油有點多.");
break;
case 4:
printf("您選了梅菜扣肉。嗯,那個味道很棒!");
break;
default:
printf("您沒有選擇餐單上的數(shù)字,難道您要餓肚子嗎 ?");
break;
}
printf("\n");
return 0;
}
復(fù)制代碼
以上代碼可以根據(jù)用戶輸入的不同數(shù)字做出相應(yīng)的回答。
7. 三元表達(dá)式:精簡的條件語句
除了 if...else 語句和 switch 語句,還有第三種條件語句,比 switch 更少用。
我們稱其為 三元表達(dá)式 。
更確切地說,其實它就是一個 if...else 的變體,只不過我們把它寫在一行里了。
因為實例總比長篇的解釋來得更清晰易懂,所以我們用兩個例子來說明。
這兩個例子的功能相同,只不過第一個使用 if...else 語句,第二個使用三元表達(dá)式。
假設(shè)我們有一個布爾類型的變量 adult,當(dāng)“成年”時它的值為真(1),當(dāng)“未成年”時它的值為假(0)。
我們還有一個 int 型變量 age,要根據(jù) adult 的值來改變 age 變量的值,下面先給出 if...else 的實現(xiàn):
if (adult)
age = 18;
else
age = 17;
復(fù)制代碼
注意:上例中我把 if 和 else 對應(yīng)的大括號給去掉了。在只有一句執(zhí)行語句的時候,去掉大括號是可以的,兩句或以上就須要加上大括號了。 不過其實按照良好的代碼習(xí)慣,應(yīng)該無論如何都加上大括號。
上例用三元表達(dá)式實現(xiàn)則是這樣:
age = (adult) ? 18 : 17;
復(fù)制代碼
三元表達(dá)式使我們可以只用一行代碼來根據(jù)條件改變變量的值。
問號表示首先判斷 adult 是不是真值,如果是真,則取問號后面的 18,將 18 賦給 age;如果為假,取冒號后面的 17,將 17 賦給 age。
這里的問號就有點像 if 的條件判斷,冒號就像 else。
事實上,三元表達(dá)式并不是那么常用,因為它會使代碼變得難讀,特別是當(dāng)判斷條件多且復(fù)雜的時候。