chapter 3 循環結構


C語言程序設計

chapter 3 循環結構

1. for

for( 預定義條件; 判斷條件; 條件增量 ){
    循環體
}

程序執行的時候會先執行初始化條件,再判斷條件是否成立;
如果條件成立就執行 {}中的循環體,如果條件不成立就退出循環;
{}執行完后再執行條件增量;
條件增量執行完后,再判斷條件是否成立,如果成立繼續循環執行{}中的語句,直到條件不成立退出。

總結就是其執行順序為:
for( 1; 2; 4){
    3
}
這里其實我們已經發現:初始條件(1)僅執行了一次,之后都是在 (2,3,4)中循環執行。

其實對於 for(1;2;4)中的 (1,2,4)三部分可以部分或者全部省略,
這樣也不會有語法上面的問題,但是 ';' 不可省略。

//預定義條件, 判斷條件,條件增量都可以不寫,如下
for( ; ; ){
    // 循環體
}

但是這樣就是一個死循環(一直循環,沒有結束)

所以我們需要另外使用一個退出:break

break 是指退出當前一層循環,比如

for(int i=1; i<=10; i++){
    if(i==5) break;
    printf("%d ", i);
}

當 i==5 的時候,就break(退出),這樣輸出的結果就是:1 2 3 4
后面的就不會輸出了。

continue  退出本次循環,繼續下次循環

for(int i=1; i<=10; i++){
    if(i==5) continue;
    printf("%d ", i);
}

當 i==5 的時候,就 continue(退出本次循環,繼續下次循環),
這樣輸出的結果就是:1 2 3 4 6 7 8 9 10

會發現只有 5 沒有輸出,其余元素都輸出了。

這就是 break 和 continue 的作用和不同。

注明:細心的讀者已經發現問題了,沒錯,對於程序的寫法我並未完全按照 C 標准的格式
比如:在 C 語言中使用 for 循環的寫法應當是:

int i;
for(i=1; i<=10; i++){
    //...
}

當然,如果我們使用 Dev-C++ 編譯運行程序時會默認保存為 .cpp 格式,也就是 C++ 格式,那么這時候時不會報錯的,但是一旦使用 .c 就會出現問題了,在后文中,為了節省這一點點篇幅,我還是會使用C++的寫法 for(int i=1; i<=10; i++){...},但是讀者應當明白這樣會導致的問題,以及如何解決。

2. for循環案例練習

【題目描述】輸入n,輸出1~n。
輸入樣例:10
輸出樣例:1 2 3 4 5 6 7 8 9 10

#include<stdio.h>
int main(){
    int n; scanf("%d", &n);
    for(int i=1; i<=n; i++){//循環 1-n,次數:n
        printf("%d ", i);
    }
    return 0;
}

【題目描述】輸入n,輸出1~n的所有偶數。

#include<stdio.h>
int main(){
    int n; scanf("%d", &n);
    for(int i=1; i<=n; i++){
        if(i%2==0) printf("%d ", i);
    }
    return 0;
}

#include<stdio.h>
int main(){
    int n; scanf("%d", &n);
    for(int i=2; i<=n; i+=2){
        printf("%d ", i);
    }
    return 0;
}

【題目描述】輸入n,輸出1~n的所有奇數之和與偶數之和。

#include<stdio.h>
int main(){
    int sum1=0, sum2=0; //初始化為0,否則會隨機化一個值
    int n; scanf("%d", &n);
    for(int i=1; i<=n; i++){ //1 2 3  ...
        if(i%2==0) sum2=sum2+i;
        else sum1=sum1+i;
    }
    printf("奇數和:%d 偶數和:%d", sum1, sum2);
    return 0;
}

【題目描述】輸入n,以及n個人的身高值,求出其中的最大值。

#include<stdio.h>
int main() {
    int n, max = -1; scanf("%d", &n);
    for(int i=1; i<=n; i++) {
        int a;    scanf("%d", &a);
        if(max<a) max=a;
    }
    printf("%d", max);
    return 0;
}

【題目描述】斐波那契數列 Fibonacci(又稱為黃金數列)指的是這樣一個數列:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,……

請你輸出斐波那契數列的前 40 項。

#include<stdio.h>
int main(){
    int i,a=1,b=1,c;
    printf("第1項:%d",a);
    printf("第2項:%d",b);
    for(i=3; i<=40;i++){
        c=a+b;
        printf("第%d項:%d",i,c);
        a=b;
        b=c;
    }
    return 0;
}

3. while

while 循環分為兩種直到型循環 和 當型循環

//當型循環:先判斷滿足條件,再執行循環體
while( 循環條件 ){
    循環體
}

 舉例:輸出 1~n
 int i=1;
 while( i<=n ){
    printf("%d ", i);
    i++;
 }

  當然它的寫法有很多種,比如下面這樣的:
  int i=1;
  while( 1 ){ //這樣貌似好像是死循環了呢!那么怎么退出呢?
    if(i>n) break;//退出當前一層循環
    printf("%d ", i);
    i++;
  }

//直到型循環:先執行一次循環體,再判斷是否滿足條件,滿足就繼續執行,否則退出。
do{
    循環體
}while(flag);

4. while循環案例練習

【題目描述】輸入n,輸出1~n。

【題目描述】輸入n,輸出1~n的所有偶數。

【題目描述】輸入n,輸出1~n的所有奇數之和與偶數之和。

【題目描述】輸入n,以及n個人的身高值,求出其中的最大值。

【題目描述】斐波那契數列 Fibonacci(又稱為黃金數列)指的是這樣一個數列:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,……

請你輸出斐波那契數列的前 40 項。

哈哈,你沒看錯,這就是上面for循環的那幾個題,只是讓你用 while 循環來實現一下。

但是我們又要思考,為什么有了 for循環,還有 while 循環呢?

其實你會發現,對於已經知道循環次數的題目,用 for 更方便一點;
但是如果不知道循環次數,但是知道結束條件,那么用 while 會更好一點。

5. 單層循環實例練習

洛谷傳送

需要給解析嗎?貌似不需要......,思考了一下,還是給一點吧!

B2057 最高的分數
解析:數據抽象為在多個數據中尋找最大值,沒說的。

#include<stdio.h>
int main(){
    int n,maxn=0; scanf("%d", &n);
    for(int i=1; i<=n; i++){//循環次數 n
        int x; scanf("%d", &x);
        if(maxn<x) maxn=x;
    }
    printf("%d", maxn);
    return 0;
}

B2072 分蘋果
解析:主要想到如何才能最少,那不就是從小到大遞增嘛,所以對 1~n 累加即可。

#include<stdio.h>
int main(){
    int n;  scanf("%d", &n);
    int sum=0;
    for(int i=1; i<=n; i++){
        sum += i;// sum = sum+i;
    }
    printf("%d", sum);
    return 0;
}

B2060 滿足條件的數累加
解析:給了左右邊界,枚舉一下,再判斷所枚舉的數據是否滿足累加條件即可。

#include<stdio.h>
int main(){
    int m,n; scanf("%d%d", &m, &n);
    int sum=0;
    for(int i=m; i<=n; i++){
        if(i%17==0){
            sum += i;
        }
    }
    printf("%d", sum);
    return 0;
}

B2055 均值
解析:就是求平均數,那么將數據累加后, ans=sum/n;

#include<stdio.h>
int main(){
    int n; scanf("%d", &n);
    double sum=0;
    for(int i=0; i<n; i++){
        double x; scanf("%lf", &x);
        sum += x;
    }
    printf("%.4lf", sum/n);
    return 0;
}

U169811 水仙花數
解析:水仙花數是一個三位數,那么枚舉 [100, 999],再按照 水仙花數的特點進行判斷是不是滿足條件即可。

#include<stdio.h>
int main(){
    for(int i=100; i<1000; i++){
        int a = i/100;
        int b = i/10%10;
        int c = i%10;
        if(i==a*a*a+b*b*b+c*c*c){
            printf("%d\n", i);
        }
    }
    return 0;
}

P1151 子數整數
解析:說了是一個五位數,那么枚舉 [10000, 99999] ,並按照題目分割得到子數,最后判斷子數是不是滿足條件即可。

#include<stdio.h>
int main(){
    int k,cnt=0; scanf("%d", &k);
    for(int i=10000; i<=30000; i++){
        int a = i/100;
        int b = i/10%1000;
        int c = i%1000;
        if(a%k==0 && b%k==0 && c%k==0){
            printf("%d\n", i); cnt=1;
        }
    }
    if(cnt==0)  printf("No\n");
    return 0;
}

P1424 小魚的航程(改進版)
解析:就是將整個過程模擬一遍就行,要注意就是:周天之后是周一。
模擬過程:天數 <=n, 就一直執行:周 x 遞增,天數遞增;
如果 周 x>7,則 x=1;
如果 周 x 屬於 1~5,則小魚泳一次 ans += 250;
最后輸出結果 ans 即可。

#include<stdio.h>
int main(){
    int x, n; scanf("%d%d", &x, &n);
    int i=1, ans=0;
    while(i<=n){
        if(x>7) x=1;
        if(x>=1 && x<=5) ans+=250;
        i++; x++;
    }
    printf("%d", ans);
    return 0;
}

6. 嵌套循環

所謂嵌套,就是一層套一層,類似套娃游戲;

#include<stdio.h>
int main(){
    int n=5;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            printf("%d:%d \t",i,j);
        }
        printf("\n");
    }
    return 0;;
}

輸出結果:
1:1     1:2     1:3     1:4     1:5
2:1     2:2     2:3     2:4     2:5
3:1     3:2     3:3     3:4     3:5
4:1     4:2     4:3     4:4     4:5
5:1     5:2     5:3     5:4     5:5

對於雙重循環,我們一般使用外層循環 i 來控制行數,內層循環 j 來控制列數。

除了上述 for-for的嵌套,還有 for-while, while-for, ..., for-for-for, ..., 很多格式都是可以的。

本質上循環的主要目的是控制執行次數,所以我們也可以將循環次數 與 問題本身相分割,但是習慣上,還是會將循環條件作為問題中的某些因素來使用, 如 for循環時的 i ,可以用來作為數組下標,奇偶次數判斷等。

【題目描述】輸出九九乘法表,樣例如下:

1*1=1
2*1=2	2*2=4
3*1=3	3*2=6	3*3=9
4*1=4	4*2=8	4*3=12	4*4=16
5*1=5	5*2=10	5*3=15	5*4=20	5*5=25
6*1=6	6*2=12	6*3=18	6*4=24	6*5=30	6*6=36
7*1=7	7*2=14	7*3=21	7*4=28	7*5=35	7*6=42	7*7=49
8*1=8	8*2=16	8*3=24	8*4=32	8*5=40	8*6=48	8*7=56	8*8=64
9*1=9	9*2=18	9*3=27	9*4=36	9*5=45	9*6=54	9*7=63	9*8=72	9*9=81

解析:開始直接輸出矩陣形態的樣例,最后對樣例尋找行列特性,發現 i>=j 才輸出,否則不輸出。

#include<stdio.h>
int main(){
    int n=9;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            if(i>=j) printf("%d*%d=%d\t", i,j,i*j);
        }
        printf("\n");
    }
    return 0;
}

7. 嵌套循環案例鞏固

提升鞏固解析

#include<stdio.h>
/*B2083 畫矩形
1. 題目數據有問題,要求能過樣例即可
2. 直接輸出實心80score
3. 測試發現f需要初始為0,方可ac,懷疑數據最后的f=0賦值失敗 */
int main(){
    int a,b,f=0;   char c;
    scanf("%d%d %c%d", &a, &b, &c, &f);
    for(int i=1; i<=a; i++){
        for(int j=1; j<=b; j++){
            if(i==1 || i==a) printf("%c", c);
            else if(j==1||j==b) printf("%c", c);
            else if(f==0) printf(" ");
            else printf("%c",c);
        }
        printf("\n");
    }
    return 0;
}
  • B2101 計算矩陣邊緣元素之和
    和上一個題目一樣,設定行列的表示變量,如果是首尾行首尾列那么累加即可。
    注意:這里很多同學在思考會不會重復累加的情況,其實不會的!因為我們只對每個數遍歷一次,那么要么加,要么不加,不會出現第二次選擇的機會。
#include<stdio.h>
int main(){
    int m, n, sum=0; scanf("%d%d", &m, &n);
    for(int i=1; i<=m; i++){
        for(int j=1; j<=n; j++){
            int x; scanf("%d", &x);
            if(i==1||i==m || j==1 || j==n) sum+=x;
        }
    }
    printf("%d", sum);
    return 0;
}
  • B2100 同行列對角線的格
    讀懂題目是關鍵,實現還需要找到一些規律,這里具體規律在程序中已經體現了。
    另外本題較為隱秘的一個點:空格,需要多看樣例,雖然題目也有說明,但是還是很容易犯錯。
#include<stdio.h>
int main() {
    int n,x,y; scanf("%d%d%d", &n, &x, &y);

    for(int j=1; j<=n; j++){
        printf("(%d,%d) ", x,j);//同行
    }printf("\n");

    for(int i=1; i<=n; i++){
        printf("(%d,%d) ", i,y);//同列
    }printf("\n");

    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            if(j-i==y-x){
                printf("(%d,%d) ", i,j);//左上到右下
            }
        }
    }printf("\n");

    for(int i=n; i>=1; i--){
        for(int j=1; j<=n; j++){
            if(i+j==x+y){
                printf("(%d,%d) ", i,j);//左下到右上
            }
        }
    }printf("\n");
    return 0;
}
#include<stdio.h>
int main(){
    int n,cnt=0; scanf("%d",&n);
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n-i+1; j++){
            printf("%02d", ++cnt);
        }printf("\n");
    }
    return 0;
}
  • P1980 [NOIP2013 普及組] 計數問題
    如何循環提取一個數據中的某些數,但是對於原數不能改變,故而我們定義了一個臨時變量temp, 檢查一位刪除一位,排好隊一個一個來。
#include<stdio.h>
int main() {
    int n,x; scanf("%d%d",&n,&x);
    int cnt=0;
    for(int i=1; i<=n; i++) {
        int temp=i;
        while(temp!=0) {
            if(temp%10==x) cnt++;
            temp=temp/10;
        }
    }
    printf("%d",cnt);
    return 0;
}
#include<stdio.h>
int main(){
    int k; scanf("%d", &k);
    int day=1,cnt=1, sum=0;//day表示天數,cnt表示每天發放金幣數量 
    while(day<=k){
        for(int i=1; i<=cnt && day<=k; i++){
            sum += cnt; day++;
        }
        cnt++;
    }
    printf("%d", sum);
    return 0;
}
#include<stdio.h>
int main(){
    int n, cnt=0; scanf("%d", &n);
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            printf("%02d", ++cnt);
        }printf("\n");
    }printf("\n");

    cnt=0;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n-i; j++) printf("  ");
        for(int j=1; j<=i; j++) printf("%02d",++cnt);
        printf("\n");
    }
    return 0;
}
#include<stdio.h>
int main_1(){
    int k, n=0; scanf("%d", &k);
    double sum=0;
    while(sum<=k){
        n++;
        sum += 1.0/n;
    }
    printf("%d", n);
    return 0;
}

int main(){
    int k, n=0; scanf("%d", &k);
    double sum=0;
    while(1){
        n++;
        sum += 1.0/n;
        if(sum>k) break;
    }
    printf("%d", n);
    return 0;
}
#include<stdio.h>
int main(){
    int l, cnt=0; scanf("%d", &l);
    for(int i=2; l>i; i++){
        int flag=1;//1表示 i是質數,0表示不是質數
        for(int j=2; j*j<=i; j++){
            if(i%j==0) {
                flag=0; break;
            }
        }
        if(flag && l>=i){
            l -= i; cnt++;
            printf("%d\n", i);
        }
    }
    printf("%d\n", cnt);
    return 0;
}
#include<stdio.h>
int main(){
    int n; scanf("%d", &n);
    if(n<0) {
        printf("-");
        n = -n;
    }
    int ans=0;
    while(n){
        ans = ans*10+n%10;
        n /= 10;
    }
    printf("%d", ans);
    return 0;
}
  • P1423 小玉在游泳
    也就是一個模擬題目,理清游戲規則,梳理流程,一步一步實現即可。
    注意輸出結果為整數,如果定義為浮點數,記得強制轉換
#include<stdio.h>
int main(){
    double x, cnt=0, step=2, sum=0; 
    scanf("%lf", &x);
    while(sum<x){
        sum += step;
        cnt++;
        step = step*0.98;
    }
    printf("%d", (int)cnt);
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM