C语言学习day07--08

循环结构

什么是循环

代码的重复执行,就叫做循环。

循环的分类

无限循环:

程序设计中尽量避免无限循环。(程序中的无限循环必须可控)

有限循环

循环限定循环次数或者循环的条件。

循环的构成

循环体
循环条件

当型循环的实现

while

语法:

while(循环条件)
{
    循环语句;
}

说明:

1. 循环条件的返回值必须是布尔类型,在C语言中,布尔类型为真使用非0来表示,布尔类型为假使
用0表示。
2. {}包起来的内容整体称之为为循环体。
3. 我们要在循环体中控制循环条件的变化,否则会产生死循环。

执行过程:

特点:

先判断,后执行,循环体语句有可能一次都不执行。

案例:

1/*
2   需求:while循环案例:如何编程来计算1 + 2 + 3 + … + 100?
3 */
4#include <stdio.h>
5 
6int main()
7{
8    // 定义一个变量,保存累加和
9    int sum = 0;
10    // 定义一个循环变量
11    int i = 1;
12 
13    while(i <= 100) // 循环条件,这里可以有关系表达式、逻辑表达式,表达式运算结果是boolean(1,0)
14    {
15        // 累加计算
16        // sum = sum + i;
17        sum += i;
18        // 给循环变量赋值,用来影响循环条件
19        i++;
20    }
21 
22    printf("1~100的累加和是:%d\n",sum);
23 
24    return 0;
25}

案例:

1/*
2   需求:while循环案例-计算1~100之间的偶数和,也就是2+4+6+8+..+100的累加和
3 */
4#include <stdio.h>
5 
6int main()
7{
8 
9    // 创建一个变量,用来存放累加和
10    int sum = 0;
11    // 创建循环变量,初始值2
12    int i = 2;
13 
14    while(i <= 100)
15    {
16        // 排除奇数
17        if( i % 2 == 0) // 表示能被2整除,说名这个数是偶数  
18        {
19            sum += i;
20        }
21 
22        i++;// 改变循环变量的值,此时一定要注意这句代码的位置
23    }
24    
25    printf("1~100之间的偶数的累加和是:%d\n",sum);    
26 
27    return 0;
28}

死循环:
while(1) // 我们会在死循环进行必要的限制

for

语法:

1 for(①表达式1;②表达式2;③表达式3) 
2 {
3     ④循环体语句;
4 }

说明:

1. ()中可以只保留两个分号,举例:(;;)
2. ① 是循环变量,我们需要赋初值,循环变量可以是列表,多个循环变量使用逗号分隔,举例:in
t i=0,j=0
3. ② 是循环条件,用来限制循环的次数,循环条件支持关系表达式,如果加入逻辑表达式,会变成
复合表达式,举例:i < 10 && j < 10
4. ③ 改变循环条件,支持列表,这里可以使用赋值表达式,举例:i++,j++
5. 执行顺序:①②④③ --> ②④③ --> ②④③ ...  --> ②,这里①只执行1次。

执行过程:

特点:

 先判断,后执行,循环体语句有可能一次都不执行。

案例:

1/**
2 * 需求:for循环案例-求1~100之间的偶数和
3 */
4#include <stdio.h>
5 
6// while实现
7void while_test()
8{
9    int sum = 0;
10    int i = 1;
11 
12    while(i <= 100)
13    {
14        if(i % 2 == 0)
15        {
16            sum += i;
17        }
18        
19        i++;
20    }
21 
22    printf("while实现:1~100之间的偶数和:%d\n",sum);
23}
24 
25// for实现
26void for_test()
27{
28    
29    int sum = 0;
30 
31    for(int i = 1;i <= 100;i++)  // 死循环表示:while(1)、for(;;)
32    {
33        if(i % 2 == 0)
34        {
35            sum += i;
36        }
37    }
38 
39    printf("for实现:1~100之间的偶数和:%d\n",sum);
40}
41 
42 
43int main()
44{
45    while_test();
46    for_test();
47 
48    return 0;
49}
50 

案例:

1/*
2   需求:for案例-用户可通过键盘录入一个整数n,用来作为阶乘的最高位数
3 */
4#include <stdio.h>
5#include <math.h>
6 
7int main()
8{
9    int n = 1;// 接受控制台输入,作为阶乘最高位
10    int r = 1;// 用来接收计算结果
11 
12    printf("请输入一个整数:\n");
13    scanf("%d",&n);
14 
15    // 循环实现阶乘
16    for(int i = 1;i <= fabs(n);i++)
17    {
18        r *= i;
19    }
20 
21    printf("1~%d之间的阶乘的结果是:%d\n",n,r);
22 
23    return 0;
24}
25 

总结:
for语句使用语法规则上,降低/避免因为忘记循环条件更新操作,而引起的产生无限循环的几率。
应用场合:for语句往往应用于循环次数事先可以确定的场景。

死循环:

1 for(表达式1;;表达式3);
2     
3 for(;;);

循环实现的三要素

循环变量初始化
循环条件
循环变量更新

案例:

1/*
2  需求:for案例-求Fibonacci数列前20个数。
3 */
4#include <stdio.h>
5 
6int main()
7{
8    int f1 = 1;// 前一个数,默认是1,因为第1个是1 
9    int f2 = 1;// 后一个数,默认是1,因为第2个是1
10    
11    int i = 1;// 循环变量
12    
13    for(;i <= 20;i++)
14    {
15        printf("%12d%12d",f1,f2);
16 
17        // 一行显示两个数,每两个换一行
18        if(i % 2 == 0)
19        {
20            printf("\n");
21        }
22        
23        f1 = f1 + f2; // f1 = 2 = 1+1
24        f2 = f2 + f1; // f2 = 3 = 1+2
25    }
26    
27    return 0;
28}
29 

直到型循环的实现

do...while

语法:

1 do
2 {
3    循环体; 
4 } while(循环条件);

说明:
1. 循环条件的返回值必须是布尔类型,在C语言中,布尔类型为真使用非0来表示,布尔类型为假使
用0表示。
2. {}包起来的内容整体称之为为循环体。
3. 我们要在循环体中控制循环条件的变化,否则会产生死循环。

执行过程:

特点:
          先执行,后判断,循环体语句至少执行一次。

案例:

1/*
2  需求:do..while案例:求1~100之间奇数的累加和
3 */
4#include <stdio.h>
5 
6int main()
7{
8    // 创建一个变量,用来存储累加和
9    int sum = 0;
10    // 创建循环变量,默认值1
11    int i = 1;
12 
13    do
14    {
15        // 判断i是否是奇数
16        if(i % 2 != 0)
17        {
18            sum += i;
19        }
20 
21        i++;// 改变循环变量的值
22 
23    }while(i <= 100);
24 
25    printf("1~100之间奇数的累加和是:%d\n",sum);
26 
27    return 0;
28}
29 
goto

语法:

goto 标签(label);

标签:标明目标代码的位置,是一个不加""的字符串。

案例:

1// 需求:求1~100之内的累加和
2int main()
3{
4    int sum = 0;
5    int i = 1;
6loop: // 自己定义的 标签
7    sum += i;
8    i++;
9    if(i <= 100)
10    {
11        goto loop; 
12    }
13   
14    printf("1~100之内的累加和是:%d\n",sum);
15    
16    return 0;
17} 

注意:
goto只能在同一个函数中跳转,goto会破坏掉代码的结构,同时会降低代码可读性。在企业开发中,
不建议使用

循环的嵌套

3种循环(while、do……while、for)可以互相嵌套。在前一个循环结构的内部又存在一个完整的循环
结构,如:

案例:

1/**
2 *  需求:嵌套for循环案例-求100~200之间的所有素数
3 */
4#include <stdio.h>
5 
6int main()
7{
8    int num = 100;// 存放100~200之间的自然数
9    int i = 2;// 循环变量,默认从2开始,因为自然数除以1没有意义  102,100~102, 102%100,102%101
10    int isPrime = 1;// 用来记录1~自身之间能整除的次数  6, 2~5, 6%2,6%3,6%4,6%5
11 
12    // 第1层for循环:生成100~200之间的自然数
13    for(;num <= 200; num++)
14    {
15        // 默认是素数
16        isPrime = 1;
17        
18        // 第2层循环,生成 2~自身-1的自然数,用于和自身校验,是否能够整除,如果有1个能被整除,就说明不
是素数
19        for(i = 2; i < num -1; i++)
20        {
21            if(num % i == 0)
22            {
23                isPrime = 0;// 不是素数
24            }
25        }
26 
27        if(isPrime) // 条件判断:isPrime == 1 缩写 isPrime
28        {
29            printf("%d ",num);
30        }
31    }
32    
33    printf("\n");
34    
35    return 0;
36}
37 

循环结构的典型应用场景

求累和:举例  1+2+3+4+..+100的和
求累乘:举例 1*2*3*4*..*100的积
求均值:举例:(1+2+3+4+..+100) / 100的值
求极值:举例:12,34,55,2,66中的最大值或者最小值
元素遍历:常用于数组元素的遍历,比如:从[1,2,3,4,5]获取每一个元素。数组我们后续课程讲
解。
...

基础算法模型

1. 累加和
定义一个变量(sum),并赋初值为0;
用该变量累加(+=)每一个数据项(i)
当访问完每一个数据项,此时该变量的取值就是累加和的结果。
2. 累乘
定义一个变量,并赋初值为1;
用该变量累乘(*=)每一个数据项;
当访问完每一个数据项,此时该变量的取值就是累乘的结果。
3. 极值【知识点:数组】
定义一个变量,并赋初值为第一个数据项
从第二个数据项开始,一次性与该变量进行比较,如果大于/小于该变量,则将当前数据项的数
据赋值给该变量。
当访问完每一个数据项,此时该变量的取值就是求极值的结果。

break和continue

break

功能:
1. 用在switch中,用来跳出switch的case语句;如果case没有break,可能会产生case穿透。

2. 用在循环中(while、do..while、for..),提前结束循环,也就是跳出整个循环。


说明:

1. break不能用于循环语句和switch语句之外的任何其它语句之中。 
2. break只能终止并跳出最近一层的结构。

案例:

1/**
2 * 需求:break案例-马杰参与一阶段分段考试,如果考试及格,就跳出循环,否则就一直考
3 */
4#include <stdio.h>
5 
6int main()
7{
8    printf("一阶段分段考试\n");
9    
10    // 声明一个变量,用来存放考试成绩
11    int score = 0;
12    do
13    {
14        // int score = 78; // score的作用域只能作用域到{}以内
15        printf("小马哥开始一阶段分段考试...\n");
16        
17        scanf("%d",&score);
18        
19        // 开始合格,结束考试
20        if(score >= 60){
21            break;
22        }       
23    }
24    while(1);
25    
26    printf("恭喜小马哥考试通过!\n");
27    
28    return 0;

案例:

1/**
2 * 需求:break案例-输出1~100以内的偶数,只输出前10个
3 */
4#include <stdio.h>
5 
6int main()
7{
8    for(int i = 1,count = 1;i <= 100;i++)
9    {
10        if(i % 2 == 0)
11        {
12            if(count > 10){
13                break;
14            }
15            count++;// 注意位置:只记录偶数
16            printf("%d\t",i);
17        }
18    }
19    
20    printf("\n");
21 
22    return 0;
23}
24 
continue

功能:continue语句不会结束整个循环,而是跳过本次循环尚未执行的语句,进入下一次循环。
说明:
1. 仅用于循环语句中。 
2. 在嵌套循环的情况下,continue语句只对包含它的最内层的循环体语句起作用。

案例:

1/**
2 * 需求:continue案例-求1~100之内的偶数和
3 */
4#include <stdio.h>
5 
6// 不使用continue
7void fun01()
8{
9    int sum = 0;
10    for(int i = 1; i <= 100; i++)
11    {
12        //  判断偶数
13        if(i % 2 == 0)
14        {
15            sum += i;
16        }
17    }
18    printf("1~100之内的偶数和是:%d\n",sum);
19}
20 
21// 使用continue
22void fun02()
23{
24    int sum = 0;
25    for(int i = 1; i <= 100; i++)
26    {
27        // 判断奇数
28        if(i % 2 != 0)
29        {
30            continue;// 跳出所有的奇数
31        }
32        
33        sum += i;
34    }
35    printf("1~100之内的偶数和是:%d\n",sum);    
36}
37 
38int main()
39{
40    fun01();
41    fun02();
42}
43 
跳出多层循环

跳出多层循环是不能使用break和continue的,因为他们只能跳出单层循环,跳出多层循环,需要
我们自己定义标志位进行跳出。

案例:

1// 定义一个标志位
2int isFlag = 1;// 默认循环成立
3char fu;
4while(isFlag)
5{
6    printf("第一层循环执行的内容...\n");
7    
8    while(isFlag)
9    {
10        printf("第二层循环执行的内容...\n");
11        
12        printf("是否跳出循环?(y/n)");
13        scanf("%c",&fu);
14        if(fu == 'Y' || fu == 'y')
15        {
16            isFlag = 0;
17        }
18    }
19}

注意:如果是多层循环,进的时候是从外到内,跳出的时候是从内到外。

案例-猜拳游戏

1/*
2   需求:猜拳游戏
3   步骤:
4        1. 选择对手
5        2. 自己出拳
6        3. 对手出拳
7        4. 双方比较
8 */
9#include <stdio.h>
10#include <string.h>
11#include <time.h>
12#include <stdlib.h>
13 
14int main()
15{
16    // 管理变量
17    int isStop = 1;// 退出状态,默认是连续
18    char stop;// 退出游戏
19    int computer_no; // 玩家编号
20    char computer_name[6];// 玩家姓名 c语言不支持 char[6] computer_name 样的写法
21    int is_select_ct = 1;// 默认,选择对手操作是不重复的   
22    int is_select_own = 1;// 默认,自己出拳操作是不重复的
23    int own_no; // 自己出拳的序号
24    char own_name[6];// 自己出拳的名称
25    int player_no;// 对手出拳的序号
26    char player_name[6];// 对手出拳的名称
27 
28    // 游戏头部
29    printf("*******************************************\n");
30    printf("************ 猜拳游戏 v1.0版 **************\n");
31    printf("*******************************************\n");
32 
33    while(isStop)
34    {
35       // 选择对手
36       while(is_select_ct)
37       {
38             printf("请选择您的对战玩家:\n[1].李白 [2].唐三 [3].萧炎\n");
39             scanf("%d",&computer_no);       
40             switch(computer_no)
41             {
42                 case 1:
43                    // c语言中,对char数组直接赋值
44                    strcpy(computer_name,"李白");
45                    is_select_ct = 0;
46                    break;
47                 case 2:
48                    strcpy(computer_name,"唐三");
49                    is_select_ct = 0;
50                    break;
51                 case 3:
52                    strcpy(computer_name,"萧炎");
53                    is_select_ct = 0;
54                    break;
55                 default:
56                    strcpy(computer_name,"无效玩家");
57                    is_select_ct = 1;
58             }   
59             printf("您选择的对手是:%s\n",computer_name);    
60       }   
61 
62       // 自己出拳
63       while(is_select_own)
64       {
65             printf("\n请选择您出拳方式:\n[1].石头 [2].剪刀 [3].布\n");
66             scanf("%d",&own_no);       
67             switch(own_no)
68             {
69                 case 1:
70                    // c语言中,对char数组直接赋值
71                    strcpy(own_name,"石头");
72                    is_select_own = 0;
73                    break;
74                 case 2:
75                    strcpy(own_name,"剪刀");
76                    is_select_own = 0;
77                    break;
78                 case 3:
79                    strcpy(own_name,"布");
80                    is_select_own = 0;
81                    break;
82                 default:
83                    strcpy(own_name,"无效的出拳");
84                    is_select_own = 1;
85             }   
86             printf("您的出拳方式是:%s\n",own_name);    
87       }   
88 
90       // 对手出拳(随机生成0~2)
91       srand((unsigned)time(NULL));// 以时间作为随机种子
92       // 随机生成对手出拳的序号(0~2)
93       player_no = rand()%3+1;
94       switch(player_no)
95       {
96           case 1:
97              // c语言中,对char数组直接赋值
98              strcpy(player_name,"石头");
99              break;
100           case 2:
101              strcpy(player_name,"剪刀");
102              break;
103           case 3:
104              strcpy(player_name,"布");
105              break;              
106       }   
107       printf("\n%s的出拳方式是:%s\n",computer_name,player_name);    
108 
109 
110       // 双方比较
111       if((own_no == 1 && player_no == 2)||(own_no == 2 && player_no == 3)||(own_no == 3 && 
player_no == 1))
112       {
113           printf("\n恭喜,您获胜!\n");
114       }
115       else if(own_no == player_no){
116           printf("\n平局!\n");
117       }
118       else
119       {
120           printf("\n很遗憾,您输了!\n");
121       }
122 
123       // 退出游戏
124       printf("\n是否退出游戏?[Y/N]\n");
125       getchar();// 消除回车
126       scanf("%c",&stop);
127 
128       if(stop == 'Y' || stop == 'y')
129       {
130           is_select_ct = 0;// 默认,选择对手操作是不重复的   
131           is_select_own = 0;// 默认,自己出拳操作是不重复的
132           isStop = 0;
133           printf("\n游戏结束!\n");
134       }
135       else
136       {
137           // 还原状态
138           is_select_ct = 1;// 默认,选择对手操作是不重复的   
139           is_select_own = 1;// 默认,自己出拳操作是不重复的
140           isStop = 1;
141       }
142    }
143    
144    return 0;
145}
146 

  • 26
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值