【C語言】"for" "while" "do……while"
在C語言中有三種迴圈語句:for語句,while語句以及do……while語句。
首先,我們來看相比其他兩種更為靈活的for語句。
*for語句*
一般形式:for(表示式1;表示式2;表示式3)
迴圈語句
其中三個表示式,作用不盡相同:
表示式1:設定初始條件,只執行一次。可以為一個或多個變數設定初值(可以是與迴圈變數無關的其他表示式)。
表示式2:迴圈條件表示式,用以判斷迴圈是否繼續。在每次執行迴圈體前先執行該表示式,決定是否繼續執行迴圈。
表示式3:用於迴圈條件的調整,例如使迴圈變數增值(也可以是與迴圈變數無關的其他表示式)。它是在執行完迴圈體後執行的。
則可得到:for(迴圈變數賦初值;迴圈條件;迴圈變數增值)
迴圈語句
舉個簡單例子:在螢幕上輸出數字1~10。
程式碼如下:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
printf("%d ", i);
}
system("pause");
return 0;
}
輸出結果:
注意:
⑴不可在for 迴圈體內修改迴圈變數,以防止 for 迴圈失去控制。
⑵建議在for語句的迴圈控制變數的取值採用“半開半閉區間”寫法。如下:
int i = 0;
for (i = 0; i<10; i++)
{}
for迴圈語句的執行過程如下:
其中,break和continue語句用以實現提前結束迴圈。
break
作用:使流程跳到迴圈體外,接著執行迴圈體下面的語句。
但是break語句只能用於迴圈語句和switch語句之中,而不能單獨使用。
程式舉例:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5 )
break;
printf("%d ", i);
}
system("pause");
return 0;
}
輸出結果:
分析:進入for迴圈,i=1,表示式2結果為真,進入迴圈體進行判斷:如果i等於5,則執行break語句,否則輸出i。此後,i每次自增1,直到i等於5時,if語句中的表示式為真,則執行break語句,直接跳出for迴圈(此時不再輸出i)。
continue
作用:只結束本次迴圈,即跳過迴圈體中下面尚未執行的語句,轉到迴圈體結束點之前,接著執行for語句中的表示式3,然後進行下一次是否執行迴圈的判定。
還是上面的例子,如果把其中的break換成continue:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
continue;
printf("%d ", i);
}
system("pause");
return 0;
}
輸出結果:
我們可以看到,輸出結果中只有5沒輸出。
分析:進入for迴圈,i=1,表示式2結果為真,進入迴圈體進行判斷:如果i等於5,則執行continue語句,否則輸出i(前4次迴圈輸出1~4)。當i等於5時,執行continue語句,從而跳出此次迴圈(不輸出5),進入下一次迴圈,此後i均不等於5,所以輸出6~10。
我們說過,for語句的較其他迴圈語句更為靈活,且功能強大:
⑴for語句中表達式1可以省略,即不對迴圈變數設初值(但是為了使迴圈可以正常執行,在for語句之前應給迴圈變數賦初值),但其後的分號(;)不能省略。如:
int i = 0;
for (; i<10; i++)
⑵for語句中表達式2也可以省略,即不設定和檢查迴圈的條件。但是這樣,迴圈會無終止地進行下去,迴圈變數的值不斷增大。
⑶for語句中表達式3也可以省略,但程式設計者應在迴圈體內使迴圈變數增值以保證迴圈可以正常結束。如:
for (i = 0; i < 10; i++)
{
//…
i++;
//…
}
⑷當然,for語句中的三個表示式可以同時省略,即不設初值,不判斷條件,迴圈變數不增值。如:
for (; ;)
printf("%d ", i);
這樣的迴圈會無終止地進行下去,顯然沒有什麼實用價值。
⑸表示式1和表示式3可以是一個簡單表示式,也可以是逗號表示式,如:
for (i = 1, j = 10; i <= j;i++,j--)
其中:表示式1為“i = 1, j = 10”,表示式3為“i++,j–”。在逗號表示式中應按自左至右的順序依次求解每個表示式,整個逗號表示式的值為最右邊的表示式的值。
⑹表示式2一半為關係表示式或邏輯表示式,也可以是數值表示式或字元表示式,只要其值為真(非0)就執行迴圈體。
⑺for語句的迴圈體可以為空,把原本在迴圈體內執行的語句放在表示式3中,且作用是一樣的。
⑻C99允許在表示式1中定義變數並賦初值。如:
for (int i = 1; i <= 10; i++)
但要特別注意的是:表示式1中定義的變數只能在for語句的迴圈體內使用,不可在迴圈外使用。
--------------------------------
*while語句*
一般形式: while(表示式)
迴圈語句
說明:
⑴表示式稱為迴圈條件表示式,當此表示式的值為真,就執行迴圈語句,否則不執行。
⑵語句即為迴圈體,迴圈體只能是一個語句,可以是一個簡單的語句,也可以是用花括號括起來的複合語句。
同樣的例子,也可以用while迴圈來實現:在螢幕上輸出數字1~10,程式碼如下:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i = 1;
while (i <= 10)
{
printf("%d ", i);
i+=1;
}
system("pause");
return 0;
}
輸出結果:
注意:while迴圈的特點是:先判斷條件表示式,後執行迴圈體語句。
while迴圈語句的執行過程如下:
在while迴圈中也可以使用break和continue語句來達到提前結束迴圈的目的,而且和在for迴圈中的意義是一樣的,但是還是存在一些差異。
break
作用:在while迴圈中,只要遇到break,就停止後期的所有的迴圈。所以,while迴圈中的break是用於永久終止迴圈的。
程式舉例:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
break;
printf("%d ", i);
i = i + 1;
}
system("pause");
return 0;
}
輸出結果:
分析:i=1,進入while迴圈,表示式結果為真,進入迴圈體進行判斷:如果i等於5,則執行break語句,否則輸出i,並且讓i自增1,然後進入第二次迴圈……當i等於4時,if語句中的表示式為假,則輸出4,然後i自增至5,此時if語句中的表示式為真,則執行break語句,直接終止while迴圈(此時不再輸出i)。
continue
作用:while迴圈中,continue是用於終止本次迴圈的,也就是在本次迴圈中continue後邊的程式碼不會再執行,而直接跳轉到while語句的判斷部分,進行下一次迴圈的入口判斷。
程式舉例1:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
continue;
printf("%d ", i);
i = i + 1;
}
system("pause");
return 0;
}
輸出結果:
可以發現,在4的後面沒有出現“請按任意鍵繼續…”。
分析:i=1,進入while迴圈,表示式結果為真,進入迴圈體進行判斷:如果i等於5,則執行continue語句,否則輸出i,並且讓i自增1,然後進入第二次迴圈……當i等於4時,if語句中的表示式為假,則輸出4,然後i自增至5,此時if語句中的表示式為真,則執行continue語句,終止本次迴圈,準備進入下一次迴圈。但是此後i一直等於5,if語句的表示式的結果一直為真,不斷執行continue語句……
程式舉例2:下面的程式輸出什麼?
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i = 1;
while (i <= 10)
{
i = i + 1;
if (i == 5)
continue;
printf("%d ", i);
}
system("pause");
return 0;
}
輸出結果:
分析:i=1,while語句的表示式結果為真,i自增1(此時i等於2),if語句的表示式結果為假,輸出2,進入第二次迴圈……當輸出4後,進入下次迴圈,i自增至5,此時if語句的表示式結果為真,執行continue語句,終止本次迴圈(不輸出5),進入下次迴圈,i自增至6……(i不再等於5,則輸出6~11。
從上面的兩個例子可以發現,在while迴圈中continue語句的位置不同,輸出結果差異很大,所以大家應該特別注意continue語句所處的位置,仔細分析程式碼,以免出現錯誤。
再來看一段程式碼:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
putchar(ch);
system("pause");
return 0;
}
執行結果:
其中,getchar()是字元輸入函式,沒有引數,其作用是從終端(或系統隱含指定的輸入裝置)輸入一個字元。相應的putchar()為字元輸出函式,作用是向終端輸出一個字元。
程式碼分析:定義一個整型變數ch,while語句的表示式中變數ch接收一個字元(從鍵盤上輸入),然後判斷是否等於EOF(檔案結束標誌),若不等於,則輸出剛才輸入的字元,直到輸入的字元等於EOF。
EOF:End Of File,C標準函式庫中的檔案結束符,其值通常為-1。在while迴圈中以EOF作為檔案結束標誌,這種以EOF作為檔案結束標誌的檔案,必須為文字檔案,因為在文字檔案中,資料都是以字元的ASCII程式碼值的形式存放的。
--------------------------------
*do……while語句*
一般形式: do
迴圈語句
while(表示式);
還是上面的例子,我們用do……while語句實現一下:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i = 1;
do
{
printf("%d ", i++);
} while (i<=10);
system("pause");
return 0;
}
輸出結果:
do……while語句的執行過程:先無條件地執行迴圈體,然後檢查條件是否成立,若成立,再執行迴圈體……如此反覆,直到表示式的值等於0(“假”),此時迴圈結束。
執行流程圖如下:
也就是說,do……while迴圈語句只少要執行一次迴圈體,使用的場景有限,所以不是經常使用。
--------------------------------
*迴圈語句的效率問題*
建議1:在多層迴圈中,如果有可能,應當將最長的迴圈放在最內層,最短的迴圈放在最外層,以減少 CPU 跨切迴圈層的次數。
如下面的程式碼:
//程式碼1
for (row = 0; row<100; row++)
{
for (col = 0; col<5; col++)
{
sum = sum + a[row][col];
}
}
//程式碼2
for (col = 0; col<5; col++)
{
for (row = 0; row<100; row++)
{
sum = sum + a[row][col];
}
}
程式碼對比分析:顯然程式碼2比程式碼1效率更高一些。
建議2:如果迴圈體記憶體在邏輯判斷,並且迴圈次數很大,宜將邏輯判斷移到迴圈體的外面。
如下面的程式碼:
//程式碼3
for (i = 0; i<N; i++)
{
if (condition)
DoSomething();
else
DoOtherthing();
}
//程式碼4
if (condition)
{
for (i = 0; i<N; i++)
DoSomething();
}
else
{
for (i = 0; i<N; i++)
DoOtherthing();
}
程式碼對比分析:
程式3比程式4多執行了N-1 次邏輯判斷。並且由於前者總要進行邏輯判斷,打斷了迴圈“流水線”作業,使得編譯器不能對迴圈進行優化處理,降低了效率。如果 N 非常大,最好採用程式4的寫法,可以提高效率;如果N 非常小,兩者效率差別並不明顯,採用程式3的寫法比較好,因為程式更加簡潔。
*幾種迴圈的比較:*
⑴以上三種迴圈都可以用來處理同一問題,一般情況下他們可以互相代替。
⑵在while迴圈和do……while迴圈中,只在while後面的括號內指定迴圈條件,因此為了使迴圈能正常結束,應在迴圈體中包含使迴圈趨於結束的語句(如i++等)。
for迴圈可以在表示式3中包含使迴圈趨於結束的操作,甚至可以將迴圈體中的操作全都放在表示式3中。因此for語句的功能更強,凡是用while迴圈能完成的,用for迴圈都能實現。
⑶用while迴圈和do……while迴圈時,迴圈變數初始化的操作應該在while和do……while語句之前完成。而for語句可以在表示式1中實現迴圈變數的初始化。
⑷for迴圈、while迴圈和do……while迴圈,都可以用break語句跳出迴圈,用continue語句結束本次迴圈。
此次對迴圈語句的介紹就到這裡。由於博主水平有限,其中定不乏缺點和不足,熱切期望得到讀者的批評和指正,謝謝!