前言
循環結構是C語言三大基本結構之一,是結構化程序設計中最重要的結構。循環結構程序主要使用循環語句實現(循環語句是專門用於循環程序執行流程的語句)。在C語言中,主要有for循環語句,while語句,do-while語句,和goto語句(由於過多的goto語句會破壞程序完整的邏輯性,這里我們不做重點介紹)。
循環結構即在給定條件成立的條件下,反復執行某語句段,直到條件不成立為止,我們將給定的條件成為循環條件,反復執行的語句稱為循環體。
根據循環條件和循環體執行次序,可以分為當型循環、直到型循環。在WHILE(當型)語句中,是當條件滿足時執行循環體;而在UNTIL(直到型)語句中,是當條件不滿足時執行循環體。
- 當型循環
當計算機遇到WHILE語句時,先判斷條件的真假,如果條件符合,就執行WHILE與WEND之間的循環體;然后再檢查上述條件,如果條件仍符合,再次執行循環體,這個過程反復進行,直到某一次條件不符合為止。
這時,計算機將不執行循環體,直接跳到WEND語句后,接着執行WEND之后的語句。因此,當型循環有時也稱為“前測試型”循環。
- 直到型循環
直到型循環又稱為“后測試型”循環,從UNTIL型循環結構分析,計算機執行該語句時,先執行一次循環體,然后進行條件的判斷,如果條件不滿足,繼續返回執行循環體,然后再進行條件的判斷。
這個過程反復進行,直到某一次條件滿足時,不再執行循環體,跳到LOOP UNTIL語句后執行其他語句,是先執行循環體后進行條件判斷的循環語句。
For循環語句
for語句屬於直到型循環,使用非常廣泛。
For語句定義
for語句由初始表達式,循環控制表達式,循環置位表達式和循環體構成。其一般形式為:
for(表達式1;表達式2;表達式3)
{
語句段
}
//注釋
表達式1稱為初始表達式,作為for語句初始條件,常常用來給循環變量賦初值,一般為賦值表達式
表達式2稱為循環控制表達式,通常作為循環條件,一般為邏輯表達式
表達式3稱為循環置位表達式,即迭代表達式,用來修改循環變量的值
上述表達式既可以是單個語句,也可以是由多個表達式構成的逗號表達式
為了更好地理解定義,我們給出一個具有趣味性的例子:
for(time=now;time<=forever;time++)
{
love++;
happiness++;
}
//注釋
結合程序猿的三行情詩,我們可以更好地理解for語句。
time=now即為表達式1,為初始表達式,意思是從現在開始
time<=forever即為表達式2,為循環控制表達式,意思是直到永遠
time++即為表達式3,為循環置位表達式,意思是隨着時間流逝
love++;happiness++;為語句段,意思是每天多愛你一點點,每天幸福一點點
所有結合起來的意思,不用我多說了吧。
需要注意的有,三個表達式僅僅作為執行某項功能存在,如果存在其他語句代替某一個表達式的功能,則在括號中該語句可以省略。(也就意味着不是每一個循環語句都具有完整的三個表達式),但分號不能省略。
關鍵字for與括號之間沒有空格,也可以加上一個空格來使代碼美觀整齊。
for語句的執行過程
for語句按照從左到右,從上到下,自兩邊到中間的執行順序執行,具體執行步驟為:
-
先執行“表達式1”。
-
再執行“表達式2”,如果它的值為真(非0),則執行循環體,否則結束循環。
-
執行完循環體后再執行“表達式3”。
-
重復執行步驟 2) 和 3),直到“表達式2”的值為假,就結束循環。
上面的步驟中,2) 和 3) 是一次循環,會重復執行,for 語句的主要作用就是不斷執行步驟 2) 和 3)。
在整個for循環執行過程中,表達式2是for循環的控制表達式,對循環語句執行起主要的控制作用。
畫出執行流程圖,如下所示:
在源代碼中執行順序為:
for語句應用實例
//從1一直加到100
#include <stdio.h>
int main(){
int i, sum=0;
for(i=1; i<=100; i++){
sum+=i;
}
printf("%d\n",sum);
return 0;
}
運行結果:
5050
執行流程為:
-
執行到 for 語句時,先給 i 賦初值1,判斷 i<=100 是否成立;因為此時 i=1,i<=100 成立,所以執行循環體。循環體執行結束后(sum的值為1),再計算 i++。
-
第二次循環時,i 的值為2,i<=100 成立,繼續執行循環體。循環體執行結束后(sum的值為3),再計算 i++。
-
重復執行步驟 2),直到第101次循環,此時 i 的值為101,i<=100 不成立,所以結束循環。
for語句的三個表達式具體分析
for循環中的“表達式1(初始化條件)”、“表達式2(循環條件)”和“表達式3(自增或自減)”都是可選項,都可以省略(但分號;必須保留)
我們以上面的程序為例,進行分析:
- 省略表達式1(初始化條件)
int i = 1;
for( ; i<=100; i++)
{
sum+=i;
}
- 省略表達式2(循環控制表達式)
for(i=1; ; i++)
sum=sum+i;
如果不做其它處理就會成為死循環(循環條件永遠成立,循環會一直進行下去,永不結束)
- 省略表達式3(循環置位表達式)
for( i=1; i<=100; )
{
sum=sum+i;
i++;
}
省略了“表達式3(自增或自減)”,就不會修改“表達式2(循環條件)”中的變量,這時可在循環體中加入修改變量的語句
- 補充兩個經常使用的特殊for語句
無限循環語句
for( ; ; )
{
語句段;
}
重復讀取語句
for( ; (c=getchar())!='\n' ; )
printf("%c",c);
for語句的嵌套使用
嵌套規則很簡單,我們給出一般形式,然后用實例進行學習
- for語句嵌套定義
一般形式為:
for(表達式01;表達式02;表達式03)
for(表達式11,;表達式12,;表達式13)
…………
for(表達式n1;表達式n2;表達式n3)
{
語句段;
}
//一般情況下n<=3;
- 實例分析:打印九九乘法表
這里我們需要用雙重循環完成打印九九乘法表的任務,這里我們給出代碼和分析:
#include<stdio.h>
int main()
{
int i=0,j=0;
int mult=0;
for(i=1;i<=9;i++)//打印控制行
{
for(j=1;j<=i;j++)
{
printf("%d*%d=%-3d",j,i,i*j);
}
printf("\n");
}
return 0;
}
執行結果:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
分析:
程序將i作為內層循環的控制變量,控制列輸出總是小於等於行輸出數,程序輸出結果為i*j=k格式的等式,實現了九九乘法表的效果,使用%3d格式輸出乘積,實現對齊效果。
While語句與do-while語句
while語句和for語句一樣屬於直到型語句,do-while語句屬於當型語句。
while語句定義及應用
while循環的一般形式為:
while(表達式){
語句塊
}
即先計算“表達式”的值,當值為真(非0)時, 執行“語句塊”;執行完“語句塊”,再次計算表達式的值,如果為真,繼續執行“語句塊”……這個過程會一直重復,直到表達式的值為假(0),就退出循環,執行 while 后面的代碼。
通常將“表達式”稱為循環條件,把“語句塊”稱為循環體,整個循環的過程就是不停判斷循環條件、並執行循環體代碼的過程。
實例:
//計算1加到100的值
#include <stdio.h>
int main(){
int i=1, sum=0;
while(i<=100)
{
sum+=i;
i++;
}
printf("%d\n",sum);
return 0;
}
運行結果:
5050
執行過程:
-
程序運行到 while 時,因為 i=1,i<=100 成立,所以會執行循環體;執行結束后 i 的值變為 2,sum 的值變為 1。
-
接下來會繼續判斷 i<=100是否成立,因為此時 i=2,i<=100 成立,所以繼續執行循環體;執行結束后 i 的值變為 3,sum 的值變為3。
-
重復執行步驟 2)。
-
當循環進行到第100次,i 的值變為 101,sum 的值變為5050;因為此時 i<=100 不再成立,所以就退出循環,不再執行循環體,轉而執行while循環后面的代碼。
由此,我們可以得到while 循環的思路:
- 設置一個帶有變量的循環條件,也即一個帶有變量的表達式;
- 在循環體中額外添加一條語句,讓它能夠改變循環條件中變量的值。
- 隨着循環的不斷執行,循環條件中變量的值也會不斷變化,當循環條件不再成立,循環結束
當循環條件中沒有變量時,可以分為兩種情況:
- while(1)
#include <stdio.h>
int main()
{
while(1)
{
printf("666");
}
return 0;
}
運行結果:
66666666…………
while 循環會一直執行下去,永不結束,成為“死循環”
- while(0)
#include <stdio.h>
int main()
{
while(0)
{
printf("6");
}
return 0;
}
運行結果:
運行結果為空,神木都不輸出.
while語句嵌套使用
- 嵌套規則如下:
while(表達式1)
while(表達式2)
while(表達式3)
…………
while(表達式n)
{
語句段;
}
- 實例:打印五行數字1-5
#include<stdio.h>
int main()
{
int i=1,j=1;
while(i<=5)
{
while(j<=5)
{
printf("%d ",j);
j++;
}
printf("\n");
i++;
}
return 0;
}
執行結果:
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
do-while語句的定義及應用
do-while語句和while語句執行規則相同,但do-while語句會首先執行循環體一次,然后判斷表達式,這也是和直到型語句的差別。
do-while循環的一般形式為:
do{
語句塊
}while(表達式);
//補充
do-while循環與while循環的不同在於:它會先執行“語句塊”,然后再判斷表達式是否為真,
如果為真則繼續循環;如果為假,則終止循環。因此,do-while 循環至少要執行一次“語句塊”。
執行規則:
do-while語句首先執行循環體,然后判斷表達式是否為真(非0),若表達式為真,則繼續返回執行循環體,否則退出循環。
尤其需要注意的是:while(表達式);最后的分號;不能省略。
實例:
#include <stdio.h>
int main()
{
int i=1, sum=0;
do
{
sum+=i;
i++;
}while(i<=100);
printf("%d\n", sum);
return 0;
}
執行結果:
5050
和while語句類似的,我們對do-while中while中的表達式進行限制,分為兩種情況:
- do-while(1)
#include <stdio.h>
int main()
{
do
{
printf("6");
}while(1);
return 0;
}
運行結果:
66666666…………
do-while 循環會一直執行下去,永不結束,成為“死循環”
- do-while(0)
#include <stdio.h>
int main()
{
do
{
printf("6");
}while(0);
return 0;
}
運行結果:
6
從這里我們可以更明顯的感受到while語句,與do-while語句存在的差異。
do-while循環嵌套:
- 一般格式為:
do
{
do
{
do
{
循環體3;
…………
}while(表達式3)
循環體2;
} while (表達式2);
循環體1;
} while (表達式1);
- 實例:打印數字三角形
#include <stdio.h>
int main()
{
int i=1,j;
do
{
j=1;
do
{
printf("%d ",j);
j++;
}while( j<=i );
printf("\n");
i++;
}while( i<=5 );
return 0;
}
執行結果:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
for語句與while語句的相互轉化
一般情況下,我們看到while與for具有類似的性質,都可以實現相同的循環功能,那while與for是不是可以相互轉化呢?答案是顯然的。
轉換規則如下:
初始化
while(條件表達式)
{
循環體
標志變量修改
}
-------等價轉換線---------
for(初始化;條件;標志變量修改)
{
循環體
}
我們舉一個栗子就可以理解這個轉換過程,我們不做過多解釋。
實現1-100的加法
- while型
#include <stdio.h>
int main()
{
int i, sum=0;
i = 1; //語句①
while(i<=100 /*語句②*/ )
{
sum+=i;
i++; //語句③
}
printf("%d\n",sum);
return 0;
}
語句①②③被放到了不同的地方,代碼結構較為松散,轉換為for后:
- for型
#include <stdio.h>
int main()
{
int i, sum=0;
for(i=1/*語句①*/; i<=100/*語句②*/; i++/*語句③*/)
{
sum+=i;
}
printf("%d\n",sum);
return 0;
}
for 循環中,語句①②③被集中到了一起,代碼結構更加清晰;
幾種循環的比較:
- for和while以及do while這3種循環都可以用來處理同一問題,一般情況下它們可以互相代替。
- while和do-while循環,是在while后面指定循環條件的,在循環體中應包含使循環趨於結束的語句(如i++,或i=i+1等)。
for循環可以在表達式3中包含使循環趨於結束的操作,甚至可以將循環體中的操作全部放到表達式3中。因此for語句的功能更強,凡用while循環能完成的,用for循環都能實現。
- 用while和do-while循環時,循環變量初始化的操作應在while和do-while語句之前完成。而for語句可以在表達式1中實現循環變量的初始化。
循環控制語句:break,continue
使用方法:
break;
continue;
后面沒有任何參數,且都有分號,不可省略.
break 語句,它不僅可以跳出“循環體”,還可以跳出 switch,break 也只能用於這兩種情況。
需要注意的有:
break 語句不能用於循環語句和 switch 語句之外的任何其他語句中。
循環的三種形式都可以用 break 跳出來,但 break 只能跳出一層循環。
當有多層循環嵌套的時候,break只能跳出“包裹”它的最里面的那一層循環,無法一次跳出所有循環。
在多層 switch 嵌套的程序中,break 也只能跳出其所在的距離它最近的 switch。但多層 switch 嵌套實在是少見。
而continue 的用法十分簡單,其作用為結束本次循環,即跳過循環體中下面尚未執行的語句,然后進行下一次是否執行循環的判定。
區別
continue 語句和 break 語句的區別為:
- continue 語句只結束本次循環,而不是終止整個循環。
- break 語句則是結束整個循環過程,不再判斷執行循環的條件是否成立。
此外,continue 只能在循環語句中使用,即只能在 for、while 和 do…while 中使用,除此之外 continue 不能在任何語句中使用。
所以,continue 不能在 switch 中使用,除非 switch 在循環體中。
此時 continue 表示的也是結束循環體的本次循環,跟 switch 也沒有關系。
參考文獻:
①《C語言從入門到精通》
②for,while,do-while循環流程圖的的畫法總結