第 16 講:程序結構(二):循環(huán)結構
如果我們重復執(zhí)行特別多相同或相似的操作,如果使用一句一句代碼來書寫的話,顯然是會使得程序臃腫的,而且還麻煩。于是,循環(huán)結構就誕生了。
C# 里提供了四種循環(huán)結構語句:while
語句、do
-while
語句、for
循環(huán)和 foreach
循環(huán)。下面我們挨個進行介紹。
foreach
循環(huán)我們不在這里介紹。因為它需要用到一個新的東西,叫做數(shù)組(Array)。所以本節(jié)內容我們只講前面三種循環(huán)語句。
Part 1 while
語句
最基礎的語句就是 while
語句。while
語句的格式是這樣的:
if
寫法基本上是一樣的,只是 if
改成了 while
while
和 if
的格式完全就只有關鍵字不一樣,其它地方寫法都是一樣的。它的執(zhí)行邏輯是這樣的:我們首先從 i <= 100
這里開始判斷。由于 i
從 1 開始,所以條件必然是成立的。按照條件要求,大括號里的代碼就會執(zhí)行一遍。因此,sum = sum + i
和 i++
都會執(zhí)行一次。執(zhí)行完畢后,會返回到 while
循環(huán)的條件(i <= 100
)處再次判斷條件。由于 i
此時執(zhí)行了一次 i++
變成了 2,所以和原來的數(shù)據(jù)不一樣了。但是,2 依舊是滿足 i <= 100
sum = sum + i
和 i++
。在反復執(zhí)行到 i
超過 100 的時候,while
循環(huán)就不再執(zhí)行了,直接到第 8 行,輸出 sum
的結果。
如果你是初學編程的話,可能看起來會有點吃力。但是從邏輯上來說,你可以知道一點。循環(huán)體(就是大括號這一坨代碼)里,
i
始終是一個單位一個單位地在增大。那么,從i
最開始的 1 開始,就會在內部反復執(zhí)行到 101 才結束。為什么是 101 呢?因為條件i <= 100
是到 100 都滿足的,因此第一個不滿足的數(shù)值應該是 101 才對。另外,雖然到 101 才是對的,但內部循環(huán)體始終執(zhí)行的次數(shù)是 100 次,即
i
是 1 的時候執(zhí)行一次,是 2 的時候執(zhí)行一次,3 的時候執(zhí)行一次……直到i
是 100 的時候,還會執(zhí)行一次。這一共是 100 次(特別需要注意的是,從 1 到 100 是一百次,不是 99 次)。最后,每一次執(zhí)行,都會執(zhí)行
sum = sum + i
這個規(guī)程,而每次都是記錄了i
當前的最新數(shù)據(jù)(1、2、3、4 等等),因此sum
最終的結果一定是累計從 1 到 100 的總和。所以程序是沒有問題的。
下面我們回頭來看。sum = sum + i
可以改成 sum += i
,而 i++
寫在前面那個語句 sum = sum + i
之后,且這個語句里也用到了 i
,所以我們還可以把 i++
合并到前面那個語句里。所以,循環(huán)體甚至可以簡化成這樣:
當然了。大括號只有這么一個語句的話,按照道理是可以不寫大括號的。所以,第 3、5 行的大括號是可以不要的。
這樣代碼就會少很多。
請說明原因。
Part 2 do
-while
語句
由于有些時候,我們沒有必要讓用戶最開始就判斷數(shù)據(jù)是否需要循環(huán),因此 C# 提供了一種后置條件的循環(huán)語句:do
-while
。它的格式有點別扭:
do
關鍵字就是為了起到一個占位的作用,用來框定循環(huán)體范圍,沒別的用。這種循環(huán)不論如何都會先執(zhí)行一遍。執(zhí)行完畢后,再來看條件是不是成立。注意,這里的條件寫的是 ++i <= 100
,所以注意先執(zhí)行 ++i
,然后才是條件判斷。
可以看出,++i
這個語法格式是比較重要的。如果沒有它的話,我們不論如何都無法做到在循環(huán)體執(zhí)行完畢后立刻先讓 i
增大一個單位,然后才是判斷循環(huán)。不過確實,你也可以把 i++
寫進循環(huán)里,不過邏輯嘛,你就自己理解了。
你可以這么寫。當然,再浪一點的話,你還可以這么寫:
只是一定要注意,do
-while
是一個整體形式的語句。因此在最后需要加分號。在之前的 if
、switch
和 while
do
-while
語句的特殊性,最后一個地方寫的是條件表達式,因此一定要加分號。
Part 3 for
語句
最舒服的語法還得是 for
。前面兩種循環(huán)我們都大概看了一下,應該沒有大問題。不過 for
循環(huán)語句可能難度偏大一些,因為它的寫法很靈活。
3-1 標準格式
如果我們改寫一下從 1 到 100 的和,用 for
循環(huán)的話,我們可以這么寫:
for
后面的小括號里是用分號分隔的每一組數(shù)據(jù)。從語義上理解的話,我們可以認為 for
循環(huán)是一種迭代循環(huán)。所謂的迭代,就是讓一個實體對象作為基礎參考,一直追蹤它自身變化的過程。每次循環(huán)完畢后,這個東西都會變化,然后將變化后的結果繼續(xù)帶入下一次的運算過程。
比如說,我們完全可以只看 i
來找出變化過程。i
是從 1 到 100,一次增大一個單位,因此在小括號里我們寫的是 int i = 1; i <= 100; i++
。最左邊的是初始賦值語句,表示 i
從多少開始;中間這個寫變量應該在什么范圍區(qū)間里不斷循環(huán)。顯然這里我們需要寫的是 i <= 100
,因為這樣才能表示 i
在 100 以內都要反復執(zhí)行循環(huán)。最后一個部分寫的是 i++
,這正好對應了循環(huán)體執(zhí)行完畢后自動增大一個單位的過程。最后,在循環(huán)體里,我們只需要關心 sum
的變化即可。這就是 for
循環(huán)的語義理解方式。
3-2 缺省迭代
在循環(huán)的時候,我們有時候不一定非得要寫一些東西。如果我們需要把初始賦值提出來的話,我們可以這么搞:
如果我們想把增量寫到循環(huán)體里,可以這么搞:
你甚至可以省略兩部分:
你還可以玩騷操作,把循環(huán)體當增量寫進增量里面去:
大括號都沒東西了,干脆改成空語句
空語句就是一個以分號結尾的語句,這個語句里啥都不寫,就寫成一個分號
;
。這種語句本來是毫無意義的寫法,但是為了保證for
for
的執(zhí)行范圍,保證編譯器分析代碼的時候不出問題。
3-3 復合迭代
在迭代的過程之中,for
循環(huán)還允許我們使用多個變量同時迭代。
比如這個例子里,i
和 j
變量同時聲明到循環(huán)的小括號里。這個表示 i
和 j
同時賦初始數(shù)值;而后面的 i++
和 j += 2
是同時充當增量。在執(zhí)行過程之中,i++
先執(zhí)行,然后就是 j += 2
。
從這個角度來說,for
Part 4 死循環(huán)
既然 if
可以寫永真條件,那么 while
這些循環(huán)呢?是的,我們完全可以這么做。
這種條件是 true
的永真式,我們就把這種循環(huán)叫做死循環(huán)(Dead Loop)。死循環(huán)是永遠都不會自動退出的,只要它從上到下執(zhí)行的時候遇到這種死循環(huán)了,就不會主動退出來。
Part 5 特殊循環(huán)控制語句
為了幫助輔助使用循環(huán)語句,我們可以在循環(huán)里插入一些特殊的語句,來靈活控制執(zhí)行過程。
5-1 break
語句
這個單詞是不是很熟悉?是的,就是之前 switch
語句最后跟的那個東西。它還有一個作用就是使得循環(huán)體的代碼不再執(zhí)行,自動跳出循環(huán)。
for
循環(huán)里嵌入了一個 if
語句,這表示每一次循環(huán)體開始執(zhí)行的時候,都執(zhí)行判斷,是否 i % 3 == 0
。由于 i
從 1 到 5,因此會在判斷之后,執(zhí)行輸出語句。一旦遇到 i % 3 == 0
條件成立的時候,就會自動執(zhí)行 break
語句,整個 for
循環(huán)后面的代碼都不再執(zhí)行了,直接跳出整個循環(huán)。
5-2 continue
語句
和 break
語句相反,continue
一旦遇到 continue
語句,就會自動跳轉到循環(huán)的條件判斷,或者是增量處。比如說 while
循環(huán),遇到 continue
語句的時候,就會自動跳轉到 ++i <= 100
;而后者 for
循環(huán),遇到 continue
的時候,就會自動跳轉到 i++
5-3 死循環(huán)里使用循環(huán)控制語句
在完成了前面的內容的學習之后,我們來看看死循環(huán)怎么嵌套這種東西。
這里條件寫的是
true
。實際上for
循環(huán)里的條件是可以不寫的,默認是true
:for (; ; i++)
就等價于for (; true; i++)
,但while
和do
-while
不行。