做者 謝恩銘,公衆號「程序員聯盟」。 轉載請註明出處。 原文:www.jianshu.com/p/49fdba563…git
《C語言探索之旅》全系列程序員
上一課是 C語言探索之旅 | 第一部分第七課:運算那點事 。github
在以前的課程中,咱們已經知道世界上有不少編程語言,有些相互之間很相似,其中很多都受了 C語言的啓發。編程
事實上,C語言是很早以前被髮明的(1972 年左右),因此它也成了不少近代編程語言的參考模板。bash
咱們說編程語言類似,是說他們都汲取了它們的前輩的編程基礎。編程語言
說到編程基礎,那就有不少了。其中,咱們已經學過的有:變量,運算。這一課咱們來學習條件表達式。學習
簡單來講,條件表達式使咱們能夠測試變量。測試
打個比方,咱們能夠這樣說: 「假如變量的值等於 7,就執行這樣那樣的操做。」ui
若是 C語言裏面不能作「等於」的判斷,那該多惋惜啊。咱們還要作「小於」,「大於」,「大於等於」,「小於等於」,「不等於」的判斷。編碼
沒必要擔憂,C語言都爲你預備好了。
爲了學習 if…else 語句,咱們準備按照下面的順序來進行:
在咱們學習寫 if…else 表達式前,需要先了解幾個基本符號,這些符號對於實現條件判斷是必不可少的。
下表列出了 C語言中須要用心記住的幾個符號:
符號 | 含義 |
---|---|
== | 等於 |
> | 大於 |
< | 小於 |
>= | 大於等於 |
<= | 小於等於 |
!= | 不等於 |
判斷「等於」須要兩個等號(
==
)! 一個很常見的錯誤是隻寫一個等號,在 C語言中一個等號和兩個等號具備不一樣的含義。一個等號表示賦值,兩個等號纔是判斷是否相等。
if 表示「若是,假如」。
邏輯是這樣的:
若是 變量的值是這樣 則 執行以下操做
因此單一的 if 語句是這樣寫的:
格式以下:
if (/* 條件 */)
{
// 若是條件爲真,所要執行的操做
}
複製代碼
咱們把上面註釋的地方換成實際的代碼,寫一個程序測試一下:
#include <stdio.h>
int main(int argc, char *argv[])
{
int age = 20;
if (age >= 18)
{
printf("你成年了!\n");
}
return 0;
}
複製代碼
解釋:
int age = 20;
複製代碼
首先定義一個 int 型的變量,名字是 age(表示「年齡」),值爲 20。
if 語句的括號 () 中的條件是 age >=18
,意思是「假如 age 的值大於或等於 18」。
if 語句的大括號 {} 中的語句是
printf("你成年了!\n");
複製代碼
就是說當 age 的值大於或等於 18 時,顯示「你成年了!」這句話。
由於程序中變量 age 的值是 20, 大於 18,因此條件爲真,因此程序運行起來後顯示:
你成年了!
複製代碼
若是咱們把變量 age 的值改成 12,再次運行程序,什麼也沒顯示,由於 12 小於 18,因此 age >= 18
這個條件不爲真,不執行大括號裏的 printf 語句。
假如咱們將上面的代碼寫成這樣:
if(age>=18){printf("你成年了!");}
複製代碼
程序也是能夠正確運行的,可是很是不推薦這樣的代碼格式!
若是咱們的程序沒有空行,沒有空格,不縮進,都寫在一行裏,那將會使代碼很是難以閱讀。
因此從一開始學習編程就請養成良好的編碼習慣,否則之後寫一些大型程序,別人根本不知道怎麼閱讀你的代碼,你也會迷失在本身的代碼裏。
推薦看林銳老師的《高質量C++/C編程指南》一書,裏面提到了編碼規範。
固然,每一個程序員的代碼風格都不同,可是咱們推薦你們聽從本系列課程中的代碼格式或者一些著名公司的代碼格式(例如 Google,阿里,等等),由於是比較通用的編碼格式。
如今你知道怎麼寫單一的 if 語句了。那當條件爲假時,咱們想要電腦也執行對應的操做怎麼辦呢?對了,此時就輪到 else 關鍵字出場了。
else 表示「不然」。
可是 else 語句必定要跟 if 語句配合才能使用,獨立的 else 語句是不可用的!
至於關鍵字,是電腦語言裏事先定義的,有特別意義的標識符,有時又叫保留字,是有特別意義的變量。 C語言有很多關鍵字,好比 int,float,char,double,if,else,等,暫時咱們很少涉及,能夠去了解一下。以前關於變量的那一課,提到變量的命名時,其實漏講了一點:變量的名字不要跟關鍵字重名。
因此一個完整的 if...else 語句的格式是:
if (/* 條件 */)
{
// 條件爲真的時候,所要執行的操做
}
else // 若是上面 () 裏的條件爲假
{
// 條件爲假的時候,所要執行的操做
}
複製代碼
再用以前測試年齡的例子,來寫一下實際的程序
if (age >= 18) // 若是 age 變量的值大於或等於 18
{
printf("你成年了!");
}
else // 若是age變量的值小於 18
{
printf("你還未成年,能夠適當任性!");
}
複製代碼
若是 age 的值大於或等於 18,則打印「你成年了!」;若是 age 的值小於 18,則打印「你還未成年,能夠任性!」。
上面咱們學習瞭如何用單一的 if 語句,以及 if...else 語句
其實除了「假如...」(if 語句)和「不然...」(else 語句),還有else...if(「又假如」)語句,用於在 if 語句的條件不爲真時對其餘的狀況的判斷,else…if 語句放在 if 語句和 else 語句之間。
邏輯是這樣的:
若是變量值爲 A,則執行 if 對應操做; 若是變量值不爲 A,而爲 B,則執行 else...if 對應操做; 若是變量值不爲 A 也不爲 B,則執行 else 對應操做。
咱們也用一個實例來看一下 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..."); // 兒語,聽不懂
}
複製代碼
流程是這樣的:
首先判斷第一個 if 語句中的括號裏的表達式,若是爲真,則執行第一個大括號裏的語句。
若是 if 的條件不爲真,則接着判斷 else…if 語句的括號裏的表達式,若是爲真,則執行對應的大括號裏面的語句。
若是 if 和 else…if 裏的表達式都爲假,則無需再判斷,直接執行 else 語句的大括號裏的命令。
在完整的條件語句塊中,else…if 和 else 語句不是必須的,可是必需要有一個 if 語句。
咱們能夠寫任意多的 else…if 語句,可是 if 語句和 else 語句則都是最多有一個。
else 後面是沒有括號 () 的,可是 if 和 else…if 後面都有括號,也就是都包含判斷條件,應該不難理解吧,很合乎邏輯。
咱們也能夠在條件語句的括號 () 中測試多個條件表達式。
例如,你想要測試這我的的年齡是否是介於 18 歲和 25 歲之間,就須要兩個條件表達式來判斷了。
爲了達成咱們的目的,咱們須要用到新的符號:
符號 | 含義 |
---|---|
&& | 邏輯與 |
II | 邏輯或 |
! | 邏輯非 |
原本其實上表中的幾個應該也叫作:與,或,非。但爲何叫「邏輯與」,「邏輯或」和「邏輯非」呢?
那是由於以後咱們還會學到 &
,|
等符號,稱爲「按位或」和「按位與」。暫時不用知道什麼意思,以後會學到。
爲了作邏輯與判斷,咱們則要用到兩個 &
符號。這個符號在美式鍵盤上須要按下 Shift + 數字鍵 7。
若是咱們要作上面提到過的年齡的判斷,則須要用邏輯與:
if (age > 18 && age < 25)
複製代碼
兩個 & 號連在一塊兒表示邏輯與,就是說當兩邊的表達式都爲真時,括號中的整個表達式才爲真,因此這裏只有當 age 大於 18 而且小於 25 的狀況下,括號裏的表達式才爲真。
爲了作邏輯或判斷,咱們則要用到兩個 |
符號。這個符號在美式鍵盤上須要按下 Shift + \
鍵。
邏輯或只要其兩邊的兩個表達式有一個爲真,整個表達式就爲真。
假設咱們如今要寫一個程序,目的是判斷一我的是否是夠資格開設銀行帳戶。
衆所周知,要開一個銀行帳戶,申請人不能太年幼(咱們假定須要大於 20 歲)或者有不少錢(「有錢任性」嘛,即便是 10 歲小孩,也得讓他開戶。開個玩笑~)。
因此咱們的程序以下:
if (age > 20 || money > 150000)
{
printf("歡迎來到**銀行 !");
}
else
{
printf("我還不夠資格,悲催啊 !");
}
複製代碼
因此這個測試只要申請人年齡大於 20 歲或者擁有超過 15 萬現金時,就可讓其開戶。
咱們最後要看的符號是感嘆號 !
,表示「取反」,加在表達式以前。這個符號在美式鍵盤上須要按下 Shift + 數字鍵 1。
若是表達式爲真,那麼加上感嘆號則爲假;若是表達式爲假,那麼加上感嘆號則爲真。就是跟你「唱反調」。
例如:
if (!(age < 18))
複製代碼
上面的表達式表示「假如已經成年」(不小於 18 歲)。
固然,邏輯與和邏輯或能夠連用,甚至多個一塊兒用,例如:
if ((age > 18 && age < 25) || age < 4)
複製代碼
不要忘了以前講過的 ==
(兩個等號)是用於判斷是否相等。例如:
if (age == 18)
{
printf("你剛成年 !");
}
複製代碼
上例中若是錯把 ==
(兩個等號)寫成了 =
(單個等號),那後果很嚴重,表達式就變成 age = 18
了。單個等號是賦值,因此 age 變爲 18,整個表達式的值變爲 18,就起不到判斷的做用了。
一種避免這樣錯誤的寫法是 18 == age
,這樣若是咱們漏寫了一個等號,變成 18 = age
,那編譯器會報錯,由於常量(例如 18)不能作左值。
關於左值和右值,能夠去搜索網上的資料,簡單來講,位於賦值運算符兩側的兩個值,左邊的就叫左值,右邊的就叫右值。
還有一個常常會犯的錯誤是:在 if 的括號或者 else...if 的括號後面多加了一個分號,以下:
if (age == 18); // 注意這個分號,原本不該該出現的
{
printf("你恰好成年");
}
複製代碼
上面的代碼實際上至關於
if (age == 18)
{
;
}
{
printf ("你恰好成年");
}
複製代碼
看到沒有,分號就至關於 if 語句的大括號裏的執行語句,而 ;
是空語句,什麼也不執行。
咱們原先想讓其在 age 等於 18 時執行的 printf 語句卻成了一個一定會被執行的語句,不論 age 的值是否是等於 18(大括號是能夠把多個語句集合起來的分隔區域,能夠拿掉大括號再來理解)。
可能有點暈,請多看幾遍代碼。
咱們如今更加深刻地來看 if...else 條件語句。事實上,條件表達式(這裏指括號裏的表達式)在其內部是作了布爾值的判斷。
布爾類型英語叫 boolean,是隻能取「真」或者「假」的一種變量類型。
事實上,在其餘的一些編程語言,如 Java,C++,C# 中,自己定義了 boolean 類型,只能有兩個值,true(表示「真」)和 false(表示「假」)。
可是 C語言沒有定義 boolean 類型,怎麼辦呢?
不用擔憂,C語言把零做爲假,非零的一切值都算爲真。
咱們能夠作幾個小測試來加深理解:
if (1)
{
printf("真!");
}
else
{
printf("假!");
}
複製代碼
以上代碼執行結果是顯示:
真!
複製代碼
咱們能夠把 1 換成非零的任意 int 型整數:5,9,13,-2,448,等等,結果都會顯示:真!
。
if (0)
{
printf("真!");
}
else
{
printf("假!");
}
複製代碼
以上代碼執行結果是顯示:
假!
複製代碼
因此 C語言中只有 0 是假,其餘非零的值都被看做真。這就是 C語言的「布爾類型」,由於 C語言沒有定義真正的布爾值類型。
事實上,每當你在條件表達式裏作判斷時,若是表達式是真的,則整個表達式的值是 1;若是是假的,則整個表達式的值爲 0。
例如:
if (age >= 18)
複製代碼
假如 age 的值爲 25,是大於等於 18 的,那麼 age >= 18
這個表達式的值爲真,電腦其實會把它替換爲 1。
假如 age 的值爲 15,是小於 18 的,那麼 age >= 18
這個表達式的值爲假,電腦其實會把它替換爲 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;
}
複製代碼
運行,顯示:
adult 的值是 : 1
複製代碼
若是 age 爲 15,則顯示:
adult 的值是 : 0
複製代碼
那句 adult = age >= 18;
,其實等價於 adult = (age >= 18);
。由於 >=
這個符號的優先級比 =
符號要高。運算符的優先級,不須要死記硬背,若是實在記不住,就加上括號 () 吧。
這裏的 adult 其實已是一個 C語言中的「布爾值」了。
咱們剛學的 if...else 類型的條件語句是最經常使用的。
可是 C語言還給出了 if...else 語句的一個替代語句:switch 語句。
由於,有時候,當咱們的條件判斷不少時,就會感受冗餘。例以下面的代碼:
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("對你的年齡我尚未對應的問候方式。");
}
複製代碼
以前咱們也說過,程序員(IT 工做者)是很會「偷懶」的,他們不喜歡作重複、單調的工做。
所以,爲了不重複寫一些代碼,他們發明了新的 switch 語句。switch 表示「轉換,替換」。
如下展現了用 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("對你的年齡我尚未對應的問候方式。");
break;
}
複製代碼
switch 語句雖然沒有 if...else 語句那麼經常使用,可是對於判斷狀況不少的條件語句,用 switch 能夠少寫很多代碼呢,並且程序也一目瞭然,比較清晰。
首先,寫 switch
這個關鍵字,接着寫一個括號,括號裏面是要判斷的變量。
case
加上變量可能的取值,再加一個冒號(:
),再加上對應取值時的操做,再加上一個 break;
。
要注意:case 後面的值只能是整型或字符型的常量或常量表達式。
default
負責處理除了各個 case 之外的狀況。
多個 case 就至關於 if...else 語句裏的 if 和 else...if 。
default 至關於 if...else 語句裏的 else。
想一想看,switch 語句是否是很像咱們去飯店用餐:
服務員拿了一個酒水單給你,上面有好多飲料,就像好多個 case 後面的取值,你點一種飲料,服務生就去給你拿對應的飲料,這個操做就像 case 的冒號後面的語句。
假如你什麼都不要,說:仍是給我來杯水吧,那服務生就只能給你拿一杯水了,就至關於 default。
每一個 case 語句的結尾絕對不要忘了加 break,不然將致使多個分支重疊(除非有意使多個分支重疊)。
假如上例中咱們少寫了一個 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("對你的年齡我尚未對應的問候方式。");
break;
}
複製代碼
上面的代碼,當 age 的值爲 2 的時候,顯示的內容是:
寶寶,你好 !
小朋友,你好 !
複製代碼
很奇怪吧,這是由於沒有 break,程序就不跳出 switch 的大括號,而繼續執行,「穿透」了 case 6
。雖然 age 的值是 2,不等於 6,可是也執行了 case 6
對應的語句
printf("小朋友,你好 !\n");
複製代碼
由於 case 6
的執行語句後面加了 break,因此程序執行完
printf("小朋友,你好 !\n");
複製代碼
就跳出了 switch 語句。固然有時候也有故意不加 break,使得多個狀況作同一個操做的,例如:
switch (age)
{
case 2:
case 6:
case 12:
case 16:
printf("未成年人,你好 !");
break;
case 18:
printf("成年人,你好 !");
break;
case 67:
printf("爺爺,你好 !");
break;
default:
printf("對你的年齡我尚未對應的問候方式。");
break;
}
複製代碼
上面的代碼,當 age 的值爲 2 或 6 或 12 或 16 時,都會執行
printf("未成年人,你好 !");
複製代碼
是否是也很妙呢?
break 關鍵字的做用不只於此(用於跳出 switch 語句),在下一課循環語句中咱們會更深刻學習 break 的做用。
還有要注意的是:最後必需使用 default 分支。 雖然 default 不加其實也不會報錯,但即便程序真的不須要 default 處理,也應該保留語句,這樣作並不是多此一舉,能夠避免讓人誤覺得你忘了 default 處理。 要把 default 子句用於檢查真正的默認狀況。
稍微有點暈?不要緊,讓咱們用一個更完整的例子來加深對 switch 語句的理解:
假設你到了一個飯店,服務員給你看當日菜單:
=== 菜單 ===
- 北京烤鴨
- 鍋包肉
- 地三鮮
- 梅菜扣肉
您的選擇是?
而後根據你的選擇作出不一樣反應。應該怎麼寫呢?但願不要看答案,先本身寫代碼試試。
下面給出完整的示例程序:
#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("您沒有選擇餐單上的數字,難道您要餓肚子嗎 ?");
break;
}
printf("\n");
return 0;
}
複製代碼
以上代碼能夠根據用戶輸入的不一樣數字作出相應的回答。
除了 if...else 語句和 switch 語句,還有第三種條件語句,比 switch 更少用。
咱們稱其爲 三元表達式。
更確切地說,其實它就是一個 if...else 的變體,只不過咱們把它寫在一行裏了。
由於實例總比長篇的解釋來得更清晰易懂,因此咱們用兩個例子來講明。
這兩個例子的功能相同,只不過第一個使用 if...else 語句,第二個使用三元表達式。
假設咱們有一個布爾類型的變量 adult,當「成年」時它的值爲真(1),當「未成年」時它的值爲假(0)。
咱們還有一個 int 型變量 age,要根據 adult 的值來改變 age 變量的值,下面先給出 if...else 的實現:
if (adult)
age = 18;
else
age = 17;
複製代碼
注意:上例中我把 if 和 else 對應的大括號給去掉了。在只有一句執行語句的時候,去掉大括號是能夠的,兩句或以上就需要加上大括號了。 不過其實按照良好的代碼習慣,應該不管如何都加上大括號。
上例用三元表達式實現則是這樣:
age = (adult) ? 18 : 17;
複製代碼
三元表達式使咱們能夠只用一行代碼來根據條件改變變量的值。
問號表示首先判斷 adult 是否是真值,若是是真,則取問號後面的 18,將 18 賦給 age;若是爲假,取冒號後面的 17,將 17 賦給 age。
這裏的問號就有點像 if 的條件判斷,冒號就像 else。
事實上,三元表達式並非那麼經常使用,由於它會使代碼變得難讀,特別是當判斷條件多且複雜的時候。
條件表達式是全部編程語言的基礎內容,使電腦可以根據變量的值作出相應決定。
關鍵字 if,else...if,else 意味着「假如」,「又假如」,「不然」,咱們能夠寫多個 else...if 。
布爾變量是一種特殊的變量,它只有兩種狀態:真(1)和假(0)(實際上,全部非零的整數值都被看做真),咱們用整數類型 int 來儲存布爾變量的值,由於 C語言其實沒有定義布爾變量這種類型,而是用整數值來表明。Java、C++、C# 等語言就定義了布爾類型。
switch 語句是 if...else 語句的一個可用替換。在有多個 else...if 的狀況下,可使用 switch 代替 if...else 語句,能使代碼更易閱讀。
三元表達式(xx ? xx : xx)是精簡的條件語句,可是咱們要謹慎使用,由於它會讓代碼不那麼易讀。
今天的課就到這裏,一塊兒加油吧!
我是 謝恩銘,公衆號「程序員聯盟」運營者,慕課網精英講師 Oscar 老師,終生學習者。 熱愛生活,喜歡游泳,略懂烹飪。 人生格言:「向着標杆直跑」