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