5.1 為什麼需要迴圈控制 前面介紹了程式中常用到的順序結構和選擇結構,但是只有這兩種結構是不夠的,還需要用到迴圈結構(或稱重覆結構)。因為在程式所處理的問題中常常遇到需要重覆處理的問題。 迴圈結構和順序結構、選擇結構是結構化程式設計的3中基本結構。 5.2 用while語句實現迴圈 while語句 ...
5.1 為什麼需要迴圈控制
前面介紹了程式中常用到的順序結構和選擇結構,但是只有這兩種結構是不夠的,還需要用到迴圈結構(或稱重覆結構)。因為在程式所處理的問題中常常遇到需要重覆處理的問題。
迴圈結構和順序結構、選擇結構是結構化程式設計的3中基本結構。
5.2 用while語句實現迴圈
while語句先判斷是否符合條件,若符合,則執行while後面的語句(稱為迴圈體)。
while語句的一般形式如下:
while(表達式)語句
其中的“語句”就是迴圈體。迴圈體可以是一句語句,也能是複合語句(用花括弧括起來的若幹條語句)。執行迴圈體的次數是由迴圈條件控制的,這個村換條件就是上面一般形式的”表達式”,它稱為迴圈條件表達式,當表達式的值為“true”(以非0值表示),就執行迴圈體語句,為“false”(以0表示),就不執行迴圈體結構。
while語句可簡單地記為:只要當迴圈條件表達式為真(即給定的條件成立),就執行迴圈體語句。
註意:while迴圈的特點是:先判斷條件表達式,後執行迴圈體語句。
例:求1+2+3+……+100
編寫程式:
1 #include <stdio.h> 2 int main() 3 { 4 int I = 1, sum = 0; 5 while(i<=100) 6 { 7 sum += i; 8 i++; 9 } 10 printf(“sum=%d\n”,sum); 11 return 0; 12 }View Code
1 運行結果:sum=5050code result
迴圈分析:
(1)迴圈體如果包含一個以上的語句,應該用花括弧括起來,作為複合語句出現。如果不加花括弧,則while語句的範圍只到while後面的第1個分號處。如,本例中while語句中如霧化括弧啊,則while語句範圍只到“sum += I;”編程死迴圈
(2)不要忽略給i和sum賦賦值(這是未進行累加前的初始情況),否則它們的值是不可預測的,結果顯然不正確。可上機測試看看
(3)在迴圈體中應有使迴圈趨向於結束的語句。如,本例中使用i++;語句來達到此目的。
5.3 用do……while語句實現迴圈
除了while語句以外,C語言還提供了do……while語句來實現迴圈結構。如:
int I = 1;
do{
printf(“%d”,i++);
}while(i<=100);
它的作用是:執行(do表示“做”)printf語句,然後檢查i的值,當i小於或等於100時,就返回執行迴圈體(printf語句),直至i大於100為止。也可寫成
do
printf(“%d”,i++);
while(i<=100);
為了使程式清晰、易讀,簡易把迴圈體用花括弧括起來。
do……while語句的執行過程是:先執行迴圈體,然後再檢查條件是否成立,若成立,再執行迴圈體。這是和while語句是不同的。
註意:do……while語句的特點是:先無條件地執行迴圈體,然後判斷迴圈條件是否成立。
do……while語句的一般形式為
do
語句
while(表達式);
其中的“語句”就是迴圈體。
過程:先執行一次迴圈體語句,然後再判別表達式,當表達式的值為“true”(以非0值表示),就執行迴圈體語句,為“false”(以0表示),就不執行迴圈體結構。
例:while和do……while迴圈的比較
(1)用while迴圈
1 #include <stdio.h> 2 int main() 3 { 4 int i , sum = 0; 5 printf(“please enter i=\n”); 6 scanf("%d",&i); 7 printf(“%d\n”,i); 8 while(i<=100) 9 { 10 sum += i; 11 i++; 12 } 13 printf(“sum=%d\n”,sum); 14 return 0; 15 }while
運行的結果為:please enter i=100
sum = 100
(2)用do……while迴圈
1 #include <stdio.h> 2 int main() 3 { 4 int i , sum = 0; 5 printf(“please enter i=”); 6 scanf("%d",&i); 7 printf(“%d\n”,i); 8 do 9 { 10 sum += i; 11 i++; 12 }while(i<=100) 13 printf(“sum=%d\n”,sum); 14 return 0; 15 }do…while
運行的結果為:please enter i=100
sum = 201
兩者的區別:對while迴圈來說,一次也不執行迴圈體(表達式“i<=10”的值為假),而對do……while迴圈語句來說則至少要執行一次迴圈體。結論:當while後面的表達式的第1次的值為“真”時,兩種迴圈得到的結果相同;否則,二者結果不相同(指二者具有相同的迴圈體的情況)。
5.4 用for語句實現迴圈
for(表達式1;表達式2;表達式3)
語句
3個表達式的主要作用是:
表達式1:設置初始條件,只執行一次。可以為零個、一個或多個變數設置初值。
表達式2:是迴圈條件表達式,用來判斷是否繼續迴圈。在每次執行迴圈體前先執行此表達式,決定是否繼續執行迴圈。
表達式3:作為迴圈的調整,例如使迴圈變數增值,它是在執行完迴圈體後才進行的。
這樣,for語句就可以理解為
for(迴圈變數賦初值;迴圈條件;迴圈變數增值)
語句
例:
for(i = 1;i<=100;i++)
sum += I;
for語句執行的過程如下:
(1)先求解表達式1.把整數1賦給變數i
(2)求解表達式2,若此條件表達式的值為真(非0),則執行for語句中迴圈體,然後執行第(3)步。若為假,轉到第5步
(3)求解表達式3.
(4)轉回步驟(2)繼續執行
(5)迴圈結束,執行for語句下麵的一個語句
for執行過程與下麵一致
i = 1;
while(i<=100)
{
sum = sum+i;
i++;
}
顯然,用for語句簡單、方便
說明:
(1)for語句的一般形式
for(表達式1;表達式2;表達式3)語句
可以改寫成while迴圈的形式:
表達式1;
while (表達式2)
{
語句
表達式3
}
二者無條件等價。
(2)“表達式1”可以省略,即不設置初值,但“表達式1”後的分號不能省略。如:
for(;i<=100;i++) sum = sum +i;
註意:由於省略了“表達式1”,沒有對迴圈變數賦初值;因此,為了能正常執行迴圈,應該在for語句之前給迴圈變數賦以初值。
(3)“表達式2”也可以省略,即不用“表達式2”來作為迴圈條件表達式,不設置和檢查迴圈的條件。如:
for(i=1;;i++) sum = sum +i;
此時迴圈無終止地執行下去,相當於
i = 1;
while(1)
{
sum = sum+I;
i++;
}
(4)表達式3可以省略,但此時程式設計者應另外設法保證迴圈能正常結束。
for(i=1;i<=100;)
{
sum = sum +i;
i++;
}
(5)如果表達式1和表達式3都沒有,只有表達式2,即只給迴圈條件,情況會怎麼樣?如:
for(;i<=100;)
{
sum = sum +i;
i++;
}
應當在for語句前給迴圈變數賦初值,否則迴圈無法正常進行;即
i = 1;
for(;i<=100;)
{
sum = sum +i;
i++;
}
相當於:
i = 1;
while(i<=100)
{
sum = sum + i;
i++;
}
(6)甚至可以將3個表達式都可省略,如:
for(;;)
{
sum = sum +i;
i++;
}
相當於
while(1)
{
sum = sum + i;
i++;
}
當然,這是沒有實用價值的,只是用於學習這種寫法也是可以的。
(7)表達式1可以設置迴圈變數初值的賦值表達式,也可以是與迴圈變數無關的其他表達式。如:
for(sum=0;i<=100;i++) sum = sum + i;
(8)表達式1和表達式3可以是一個簡單的表達式,也可是逗號表達式,即包含一個以上的簡單表達式,中間用逗號間隔。
for(sum=0,i=1 ; i<=100 ; i++) sum = sum + i;
或
for(i=0, j=100;i<=100;i++,j--) k = i+j;
在逗號表達式內按自左向右順序求解,整個逗號表達式的值為最後邊的表達式的值。如:
for(i=1;i<=100;i++,i++) sum = sum + i;
等價於
for(i=1;i<=100;i=i+2) sum = sum +i;
(9)表達式2一般是關係表達式(如i<=100)或邏輯表達式(如a<b&&x<y),但也可是數值表達式或字元表達式,只要其值為非零,就執行迴圈體。如:
for(i = 0; (c = getchar())!=’\n’;i+=c);
註意:此for語句的迴圈體為空語句,把本來要在迴圈體內處理的內容放在表達式3中,作用是一樣的。
(10)C99允許在for語句的“表達式1”中定義標量並賦初值,如:
for(int i=1;i<=100;i++) sum = sum + i;
5.5 迴圈的嵌套
一個迴圈體內又包含另一個完整的迴圈結構,稱為迴圈的嵌套。內嵌的迴圈中還可以嵌套迴圈,這就是多層迴圈。
3種迴圈(while迴圈、fo…while迴圈、for迴圈)可以相互嵌套。下麵是合法的格式:
(1)
while ()
{ ……
while()//內層迴圈
{……}
}
(2)
do
{
……
do
{
……
}while ();//內層迴圈
}while ();
(3)
for(;;)
{
for(;;)//內層迴圈
{……}
}
(4)
while()
{
……
do
{
……
}while ();//內層迴圈
……
}
(5)
for(;;)
{
……
while()//內層迴圈
{
……
}
……
}
(6)
do
{
……
for(;;)//內層迴圈
{……}
}while ();
5.6幾種迴圈的比較
(1)3中迴圈都可以用來處理同一問題,一般情況下它們可以相互代替。
(2)在while迴圈和do…while迴圈中,只在while後面的括弧內指定迴圈條件,因此為了使迴圈能正常結束,應在迴圈體中包含使迴圈趨於結束的語句(如i++或i+=1等)
for迴圈可以在表達式3中包含使迴圈趨於結束的操作,甚至可以將迴圈體中的操作全部放到表達式3中。因此for迴圈的功能更強,凡是用while迴圈能完成的,for迴圈也能勝任。
(3)用while和do…while迴圈時,迴圈變數初始化的操作應在while和do…while語句之前完成。而for語句可以在表達式1實現迴圈變數的初始化。
(4)while迴圈、do…while迴圈、for迴圈,都可以用break語句跳出迴圈,用continue語句結束本次迴圈(break語句和continue語句見後面)
5.7 改變迴圈執行的狀態
5.7.1 用break語句提前結束迴圈。
例:當sum大於或等於1000時迴圈結束
1 //break語句的使用 2 #include <stdio.h> 3 int main() 4 { 5 int sum = 0; 6 int i = 0; 7 for(;i<=100;i++) 8 { 9 if(sum>=1000) //如果sum>1000提前結束迴圈 10 break; 11 sum += i; 12 } 13 printf("迴圈的次數為:%d,sum的值為:%d\n",i,sum); 14 return 0; 15 }break Code
break語句的一般形式:
break
其作用是使流程跳到迴圈體之外,接著執行迴圈體下麵的語句。
註意:break語句只能用於迴圈語句和switch語句之中,而不能單獨使用。
5.7.2 用continue語句提前結束本次迴圈
有時並不希望終止整個迴圈的操作,而只希望提前結束本次迴圈,而接著執行下次迴圈。這種情況可以使用continue語句
例:要求輸出1~100能被3和5同時整除的數
1 #include <stdio.h> 2 int main() 3 { 4 int i=1; 5 int j=0; //用®?於®¨²換?行D 6 for(;i<=100;i++) 7 { 8 if(i%3==0&&i%5==0) 9 { 10 j++; 11 printf("%d\t",i); 12 if(j%5==0) 13 printf("\n"); 14 } 15 } 16 printf("\n"); 17 return 0; 18 }continue Code
continue語句的一般形式為
continue;
其作用為結束本次迴圈,即跳過迴圈體中下麵尚未執行的語句,轉到執行體結束點之前,接著執行for語句中的“表達式3”,然後進行下一次是否執行迴圈的判斷。
5.7.3 break語句和continue語句的區別
continue語句只結束本次迴圈,而不是終止整個迴圈的執行。而break語句則是結束整個迴圈過程,不在判斷執行迴圈的條件是否成立。如,下列兩種迴圈結構:
(1)while(表達式1)
{
……
if(表達式2) break;
……
}
(2)while(表達式1)
{
……
if(表達式2) continue;
……
}
例:通過下列對照,比較break語句和continue的區別
1 #include <stdio.h> 2 int main() 3 { 4 int i,j,n=0; 5 for(i=1;i<=4;i++) 6 { 7 for(j=1;j<=5;j++,n++) 8 { 9 if(n%5==0) 10 printf("\n"); 11 if(i==3&&j==1)break; 12 printf("%d\t",i*j); 13 } 14 } 15 printf("\n"); 16 printf("\n"); 17 printf("\n"); 18 for(i=1;i<=4;i++) 19 { 20 for(j=1;j<=5;j++,n++) 21 { 22 if(n%5==0) 23 printf("\n"); 24 if(i==3&&j==1)continue; 25 printf("%d\t",i*j); 26 } 27 } 28 return 0; 29 }break And continue
5.8迴圈程式的舉例
例:fibonacci數列的前40個數。這個數列有如下特點:第1,2兩個數為1,1,從第3個數開始,該數是其前面兩個數之和。即:
F1 = 1 (n=1)
F2 = 1 (n=2)
Fn = Fn-1 +Fn-2 (n>=3)
當然,這個數列有另一個故事,那就是兔子繁殖的問題;有一堆兔子,有1對兔子,從出生後第三個月起每個月都生1對兔子 ,小兔子長到第三個月後每個月又生1對兔子,假如兔子都不死 ,問每個月的兔子總數為多少?
解題思路:最簡單易懂的方法就是,根據題意,從前2個月的兔子數可以推出第3個月的兔子數。設第1個月的兔子數為f1 = 1,第2個月的兔子數f2 = 1,則第3個月的兔子數f3 = f1+f2.然後第4個月就是 f4 = f3 +f2.當然,我們不是手動去寫出相加40項,用迴圈即可。
編寫程式:
1 //求Fibonacci數列前40項 2 #include <stdio.h> 3 int main(){ 4 long int f1,f2; 5 int i; 6 f1 = 1; f2 = 1; //賦初始值 7 for(i = 1;i<=20;i++){//迴圈20次,一次兩個,結果為前40項 8 printf("%12d%12d",f1,f2);//輸出 兩項 9 f1=f1+f2;f2=f2+f1;//計算下麵兩項 10 if(i % 2 == 0) //一行四個 好看用 11 printf("\n"); 12 } 13 return 0; 14 }View Code
程式分析:程式共應輸出40個月的兔子數。為了能更好的容納兔子數量,所以應該定義為long int型。我們在迴圈體中一次求出下兩個月的兔子數。且用f1和f2兩個變數即可。