循環
需要多次重複執行一個或多個任務的問題考慮使用循環來解決。
三大循環樣式不一樣,但是本質是一樣的。
循環三要素
死循環
#include <stdio.h>
#include <windows.h>
int main()
{
while (1)
{
printf("xxxxxxxxxxxxx\n");
Sleep(1000);
}
return 0;
}
運行結果爲:
可控循環
#include <stdio.h>
#include <windows.h>
int main()
{
int i = 10; //循環變量初始化
while (i > 0) //循環終止條件
{
printf("xxxxxxxxxx\n");
Sleep(1000);
i--; //有使循環趨於結束的語句
}
return 0;
}
運行結果爲:
打印十次之後就會跳出循環。
可控循環的三要素
循環三要素:
循環變量初始化, 循環變量的變化(趨向終止條件), 循環終止條件。
要做到可控三個條件缺一不可。
while “當”型循環
只有條件爲真,纔可能向下執行。有可能一次都不執行
語法結構及流程
while (表達式)
{
語句;
}
解析
計算表達式的值,當值爲真(非 0)時,執行循環體語句,一旦條件爲假,就停止執行循環體。如果條件在開始時就爲假,那麼不執行循環體語句直接退出循環。
代碼演示
用 while 語句求 1~100 所有整數的和。
#include <stdio.h>
int main(void)
{
int i; int sum = 0;
i = 0;
while (i <= 100)
{
sum += i;
i++;
}
printf(“sum = %d\n”, sum);
return 0;
}
運行結果爲:
do while“直到”型循環
直到條件爲假,才終止循環。
do while循環至少執行一次。
語法及流程
do
{
語句;
} while (表達式) ;
解析
它先執行循環體中的語句,然後再判斷條件是否爲真,如果爲真則繼續循環;如果爲假,則終止循環。
代碼演示
用 do-while 語句求 1~100 所有整數的和。
#include <stdio.h>
int main(void)
{
int i; int sum = 0;
i = 0;
do
{
sum += i;
i++;
} while (i <= 100);
printf("sum = %d\n", sum);
return 0;
}
運行結果爲:
while/do while 綜合案例
while 與 dowhile 的區別
如下代碼,表示求和,求輸入 1 和 11 的比較。
do while 代碼演示
#include <stdio.h>
int main()
{
int sum = 0;
int i;
scanf_s("%d", &i);
do
{
sum += i;
i++;
} while (i <= 10);
printf("sum= %d\n", sum);
return 0;
}
運行結果爲:
while 代碼演示
#include <stdio.h>
int main()
{
int sum = 0;
int i;
scanf_s("%d", &i);
while (i <= 10)
{
sum += i;
i++;
}
printf("sum= %d\n", sum);
return 0;
}
運行結果爲:
結論是,當輸入 1 時兩個運算的求和,是相等的,但是當輸入 11 是,while 版本輸出的 sum = 0。而 do while 版本輸出的則是 11。
所以,do while 至少執行一次,而 while 可能一次都不執行。
do while 的爭議
do while 特點是,循環體至少執行一次,這個是比較可怕的。在沒有收到任何限制條件的情況下,就開始執行循環體。很可能會帶來不可挽回的後果。比如,先格式化了你的 c 盤,然後再來問要不要格式化。
do while 曾一度提議廢除,但是他在輸入性檢查方面還是有點用的。比如,輸入 Y/y 設置標誌位,退出,執行標誌位操作,輸入 N/n 直接退出,輸入其它,循環輸入。
代碼演示:
#include <stdio.h>
int main(void)
{
char select;
do
{
printf("同意協議請輸入 y/Y,不同意請輸入n/N\n");
scanf_s("%c", &select);
getchar();
if (select == 'n' || select == 'N')
exit(-1);
} while (!(select == 'y' || select == 'Y'));
printf("next\n");
return 0;
}
運行結果爲:
只有輸入y/Y,n/N才向下執行,否則繼續循環
#include <stdio.h>
int main()
{
int name;
int passwd;
do
{
printf("name:");
scanf_s("%d", &name);
printf("passwd:");
scanf_s("%d", &passwd);
} while (!(name == 10 && passwd == 20));
printf("wellcome\n");
return 0;
}
運行結果爲:
直到輸入合適的用戶名和密碼才能夠進行下一步操作。
for “列表”型循環
語法結構及流程
for( 表達式 1 ; 表達式 2 ; 表達式 3 )
{
語句;
}
解析
1 、計算表達式 1 的值,通常爲循環變量賦初值。
2 、計算表達式 2 ,的值,即判斷循環條件是否爲真,若值爲真則執行循環體一次,
否則跳出循環。
3 、計算表達式 3 的值,這裏通常寫更新循環變量的賦值表達式,然後轉回第 2步重複執行。
代碼演示
用for循環求 1~100 所有整數的和。
#include <stdio.h>
int main(void)
{
int i; int sum = 0;
for (int i = 0; i <= 100; i++)
{
sum += i;
}
printf("sum = %d\n", sum);
return 0;
}
運行結果爲:
for(;;)是 for 嗎?
上面for循環仍然成立,等價於while(1)。
代碼演示:
#include <stdio.h>
int main(void)
{
for (;;)
printf("xxxxxxxxxx\n");
return 0;
}
運行結果爲:
for 與逗號表達式
打印 10 的所有加法組和,格式如下:
10 = 1 + 9;
10 = 2 + 8;
10 = 3 + 7;
10 = 4 + 6;
10 = 5 + 5;
10 = 6 + 4;
10 = 7 + 3;
10 = 8 + 2;
10 = 9 + 1;
代碼演示:
#include <stdio.h>
int main(void)
{
int i; int j;
for (i = 1, j = 10 - i; i < 10 && j>0; i++, j--)
{
printf(" 10 = %d + %d\n", i, j);
}
return 0;
}
運行結果爲:
循環的嵌套
一重循環解決線性的問題,而二重循環和三重循環就可以解決平面和立體的問題了。比如打印如下的圖形:
******
******
******
******
*
**
***
****
嵌套的語法格式
三種語法格式,是一種 嵌套的結構, 不可以交叉。三者都可以實現上述的功能,但是比較傾向於使用第三種,爲什麼呢,因爲第三種,循環的初始化不在循環體外,循環變量的改變不在循環體內。整體呈現會更清晰簡潔。
循環嵌套while 版
#include <stdio.h>
int main(void)
{
int i = 0;
while (i < 4)
{
int j = 0;
while (j < 6)
{
printf("*");
j++;
}
putchar(10);
i++;
}
return 0;
}
運行結果爲:
循環嵌套do while 版
#include <stdio.h>
int main(void)
{
int i = 0;
do {
int j = 0;
do
{
printf("*");
j++;
} while (j < 6);
i++;
putchar(10);
} while (i < 4);
return 0;
}
運行結果爲:
循環嵌套for 版
#include <stdio.h>
int main(void)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 6; j++)
{
printf("*");
}
putchar(10);
}
return 0;
}
運行結果爲:
循環建議
先外後內的循環嵌套寫法
循環的嵌套,先寫外重循環,外重循環的循環變量,可能作爲內重循環的循環終止條件。
半開半閉區間寫法
建議 for 語句的循環控制變量的取值採用“半開半閉區間”寫法。 這樣的作法,跟後面的數組下標,是完全吻合的。但,這並非絕對。
循環變量屬於半開半閉區間
for ( x=0; x<N; x++)
{
}
循環變量屬於閉區間
for ( x=1; x<=N; x++)
{
}
嵌套的優化
在多重循環中,如果有可能,應當將最長的循環放在最內層,最短的循環放在最外層,以減少 CPU 跨切循環層的次數。
低效率:長循環在最外層
for (row=0; row<100; row++)
{
for ( col=0; col<5; col++ )
{
sum = sum + a[row][col];
}
}
高效率:長循環在最內層
for (col=0; col<5; col++ )
{
for (row=0; row<100; row++)
{
sum = sum + a[row][col];
}
}
循環小結
一種循環可以解決的問題,使用另外兩種同樣可行,只是方便程度不同。
while 循環一般用於循環次數不定的情況,for 循環一般用於循環次數確定的情況
(也可以用於循環次數不定的情況),do-while 循環一般用於至少需要執行一次的
情況。
for 循環和 while 循環是先判斷條件是否爲真,再執行循環體,因此,可出現循
環一次也不執行的情況;do-while 循環是先執行循環體,再判斷條件是否爲真,
因此,循環體至少執行一次。