C语言基础⑥——循环结构

一、循环结构

1、什么是循环

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

2、循环的分类

  • 无限循环:程序设计中尽量避免无限循环;(程序中的无限循环必须可控)
  • 有限循环:循环限定循环次数或者循环的条件。

3、循环的构成

  • 循环体
  • 循环条件

4、当型循环的实现

  • while

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

//可控制的无限循环
int i = 0;
while(i < 100)
{
    printf("hello");
    i++;    
}
特点:

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

举例:计算1-100的累加和
/*
  需求:while循环案例:如何编程来计算1+2+3+...+100?
*/
#include <stdio.h>

int main()
{
    //定义一个变量,保存累加和
    int sum = 0;
    //定义一个循环变量
    int i = 1;

    while(i <= 100)//循环条件,这里可以有关系表达式/逻辑表达式,表达式运算结果是boolean(1,0)
    {
        //累加计算
        //sum = sum + i;
        sum += i;
        //给循环变量赋值,用来影响循环条件
        i++;
    }

    printf("1-100的累加和是:%d\n",sum);
    return 0;
}

举例:计算1-100之间的偶数和
/*
  需求:while循环案例_计算1-100之间的偶数和,也就是2+4+6+8+...+100的累加和
*/
#include <stdio.h>

int main()
{
    //创建一个变量,用来存放累加和
    int sum = 0;
    //创建循环变量,初始值2
    int i = 2;

    while(i <= 100)
    {
        //排除奇数
        if(i % 2 == 0)//表示能被2整除,说明这个数是偶数
        {
            sum += i;
        }
        i++;//改变循环变量的值,此时一定要注意这句代码的位置
    }

    printf("1-100之间的偶数的累加和是:%d\n",sum);
    return 0;
}

注意

r变量计算式的定义要放在scanf函数的后面!

死循环
while(1);//我们会在死循环进行必要的限制
  • for..

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

特点:

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

举例:求阶乘

fabs(num) --> 取绝对值

r、i 声名在外,赋值在for()内;

/*
需求:for案例_用户可通过键盘录入一个整数n,用来作为阶乘的最高位数
*/
#include <stdio.h>
#include <math.h>

int main()
{
    int n = 1;//接受控制台输入,作为阶乘最高位
    int r = 1;//用来接受计算结果

    printf("请输入一个整数:\n");
    scanf("%d",&n);

    //循环实现阶乘
    for(int i = 1;i <= fabs(n);i++)
    {
        r *= i;
    }

    printf("1-%d之间的阶乘的结果是:%d\n",n,r);
    return 0;
}

举例:for求1-100之间的偶数和
/**
*需求:for循环案例_求1-100之间的偶数和
*/
#include <stdio.h>

//while实现
void while_test()
{
    int sum = 0;
    int i = 1;

    while(i <= 100)
    {
        if(1 % 2 == 0)
        {
            sum += i;
        }
        i++;
    }
    printf("while实现:1-100之间的偶数和:%d\n",sum);
}

//for实现
void for_test()
{
    int sum = 0;

    for(int i = 1;i <= 100;i++)//死循环表示:while(1)、for(;;)
    {
        if(i % 2 == 0)
        {
            sum += i;
        }
    }
    printf("for实现:1-100之间的偶数和:%d\n",sum);
}

int main()
{
    while_test();
    for_test();

    return 0;
}

总结:
  • for语句使用语法规则上,降低/避免因为忘记循环条件更新操作,而引起的产生无限循环的几率;
  • 应用场合:for语句往往应用于循环次数实现可以确定的场景。
死循环
for(表达式1;;表达式3);

for(;;);
循环实现的三要素:
  • 循环变量初始化;
  • 循环条件;
  • 循环变量更新。
举例:for_求Fibonacci数列前20个数
 /*
需求:for案例_求Fibonacci数列前20个数
*/
#include <stdio.h>

int main()
{
    int f1 = 1;//前一个数,默认是1,因为第一个是1;
    int f2 = 1;//后一个数,默认是1,因为第二个是1:

    int i = 1;//循环变量

    for(;i <= 20;i++)
    {
        printf("%12d%12d\n",f1,f2);

        //一行显示两个数,每两个换一行
        if(i % 2 == 0)
        {
            printf("\n");
        }

        f1 = f1 + f2;//f1=2=1+1
        f2 = f2 + f1;//f2=3=1+2
    }

    return 0;
}

5、直到型循环的实现

  • do...while

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

特点:

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

举例:求1-100之间奇数的累加和
/*
需求:do...while案例:求1-100之间奇数的累加和
*/
#include <stdio.h>

int main()
{
    //创建一个变量,用来存储累加和
    int sum = 0;
    //创建循环变量,默认值1
    int i = 1;

    do
    {
        //判断i是否是奇数
        if(i % 2 != 0)
        {
            sum += i;
        }
        i++;//改变循环变量的值
    }while(i <= 100);

    printf("1-100之间奇数的累加和是:%d\n",sum);
    return 0;
}

  • goto

语法:
goto 标签(label);
标签:

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

举例:求1-100之内的累加和
// 需求:求1~100之内的累加和
#include <stdio.h>

int main()
{
    int sum = 0;
    int i = 1;
loop: // 自己定义的 标签
    sum += i;
    i++;
    if(i <= 100)
   {
        goto loop; 
   }
   printf("1~100之内的累加和是:%d\n",sum);
    
   return 0;
}

注意:

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

6、循环的嵌套

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

举例:嵌套for循环案例_求100-200之间的所有素数

/**
* 需求:嵌套for循环案例_求100-200之间的所有素数
*/
#include <stdio.h>

int main()
{
    int num = 100;//存放100-200之间的自然数
    int i = 2;//循环变量,默认从2开始,因为自然数除以1没有意义 102,100-102,102%100,102%101
    int isPrime = 1;//用来记录1-自身之间能整除的次数 6,2-5,6%2,6%3,6%4,6%5

    //第一层for循环:生成100-200之间的自然数
    for(;num <= 200;num++)
    {
        //默认是素数
        isPrime = 1;

        //第二层循环,生成2-自身-1的自然数,用于和自身校验,是否能够整除,如果有
一个能被整除,就说明不是素数
        for(i = 2;i < num -1;i++)
        {
            if(num % i == 0)
            {
                isPrime = 0;//不是素数
            }
        }

        if(isPrime)//条件判断:isPrime == 1 缩写 isPrime
        {
            printf("%d\n",num);
        }
    }

    printf("\n");
    return 0;
}

7、循环结构的典型应用场景

  • 求累加和:举例 1+2+3+...+100的和;
  • 求累乘:举例 1*2*3*...*100的积;
  • 求均值:举例 (1+2+3+...+100) / 100的值;
  • 求极值:举例 12,34,56,7,23中的最大值或最小值;
  • 元素遍历:举例 常用于数组元素的遍历,比如:从数组[1,2,3,4,5]中获取每一个元素;

8、基础算法模型

  • 累加和

  1. 定义一个变量(sum),并赋初值为0;
  2. 用该变量累加(+=)每一个数据项(i);
  3. 当访问完每一个数据项,此时该变量的取值就是累加和的结果。
  • 累乘

  1. 定义一个变量,并赋初值为1;
  2. 用该变量累乘(*=)每一个数据项;
  3. 当访问完每一个数据项,此时该变量的取值就是累乘积的结果。
  • 极值【知识点:数组

  1. 定义一个变量,并赋初值为第一个数据项;
  2. 从第二个数据项开始,一次性与该变量进行比较,如果大于/小于该变量,则将当前数据项的数据赋值给该变量;
  3. 当访问完每一个数据项,此时该变量的取值就是求极值的结果。

9、break 和 continue

  • break

功能:
  1. 用在switch中,用来跳出switch的case语句;如果case没有break,可能会产生cse穿透;
  2. 用在循环中(while、do...while、for...),提前结束循环,也就是跳出整个循环
说明:
  1. break不能用于循环语句和switch语句之外的任何其它语句之中;
  2. break只能终止并跳出最近一层的结构。
图示:
举例:(do...while)一阶段分段考试,考试及格时跳出循环
/**
* 需求:break案例_xx参与一阶段分段考试,如果考试及格,就跳出循环,否则一直考
*/

#include <stdio.h>

int main()
{
    printf("一阶段分段考试\n");

    //声明一个变量,用来存放考试成绩
    int score = 0;
    do
    {
        //int score = 78;//score的作用域只能作用在{}以内;

        printf("丽丽开始一阶段分段考试...\n");
        scanf("%d",&score);

        //考试合格,结束循环
        if(score >= 60)
        {
            break;
        }

    }while(1);

    printf("恭喜丽丽考试通过\n");
}
举例:(for...)输出1-100以内的偶数,只输出前10个
/**
 * 需求:break案例-输出1~100以内的偶数,只输出前10个
 */
#include <stdio.h>
int main()
{
    for(int i = 1,count = 1;i <= 100;i++)
   {
        if(i % 2 == 0)
       {
            if(count > 10){
                break;
           }
            count++;// 注意位置:只记录偶数
            printf("%d\t",i);
       }
   }
    
    printf("\n");
    return 0;
}

  • continue

功能:

结束本次循环的执行,但不退出循环结构。即跳过循环体中下面尚未执行的语句,接着进行下一次是否执行循环的判定。

说明:
  1. 仅用于循环语句中;
  2. 在嵌套循环的情况下,continue语句只对包含它的最内层的循环体语句起作用。
图示:

举例:求1-100之内的偶数和
/**
 * 需求:continue案例-求1~100之内的偶数和
 */
#include <stdio.h>
// 不使用continue
void fun01()
{
 int sum = 0;
 for(int i = 1; i <= 100; i++)
 {
 // 判断偶数
 if(i % 2 == 0)
 {
 sum += i;
 }
 }
 printf("1~100之内的偶数和是:%d\n",sum);
}
// 使用continue
void fun02()
{
 int sum = 0;
 for(int i = 1; i <= 100; i++)
 {
 // 判断奇数
 if(i % 2 != 0)
 {
 continue;// 跳出所有的奇数
 }
 
 sum += i;
 }
 printf("1~100之内的偶数和是:%d\n",sum); 
}
int main()
{
 fun01();
 fun02();
}

  • 跳出多层循环

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

举例:
#include <stdio.h>
// 定义一个标志位
int isFlag = 1;// 默认循环成立
char fu;
while(isFlag)
{
   printf("第一层循环执行的内容...\n");
   while(isFlag)
   {
        printf("第二层循环执行的内容...\n");
        
        printf("是否跳出循环?(y/n)");
        scanf("%c",&fu);
        if(fu == 'Y' || fu == 'y')
       {
            isFlag = 0;
       }
   }
}

注意:

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

10、消除回车函数

getchar();//消除回车
/*用于提示重复两遍出现时想消除一条提示*/

11、综合案例:猜拳游戏

/*
   需求:猜拳游戏
   步骤:
        1. 选择对手
        2. 自己出拳
        3. 对手出拳
        4. 双方比较
 */
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
int main()
{
    // 管理变量
    int isStop = 1;// 退出状态,默认是连续
    char stop;// 退出游戏
    int computer_no; // 玩家编号
    char computer_name[6];// 玩家姓名 c语言不支持 char[6] computer_name 样的写法
    int is_select_ct = 1;// 默认,选择对手操作是不重复的   
    int is_select_own = 1;// 默认,自己出拳操作是不重复的
    int own_no; // 自己出拳的序号
    char own_name[6];// 自己出拳的名称
    int player_no;// 对手出拳的序号
    char player_name[6];// 对手出拳的名称
    // 游戏头部
    printf("*******************************************\n");
    printf("************ 猜拳游戏 v1.0版 **************\n");
    printf("*******************************************\n");
    while(isStop)
   {
       // 选择对手
       while(is_select_ct)
       {
             printf("请选择您的对战玩家:\n[1].李白 [2].唐三 [3].萧炎\n");
             scanf("%d",&computer_no);       
             switch(computer_no)
             {
                 case 1:
                    // c语言中,对char数组直接赋值
                    strcpy(computer_name,"李白");
                    is_select_ct = 0;
                    break;
                 case 2:
                    strcpy(computer_name,"唐三");
                    is_select_ct = 0;
                    break;
                 case 3:
                    strcpy(computer_name,"萧炎");
                    is_select_ct = 0;
                    break;
                 default:
                    strcpy(computer_name,"无效玩家");
                    is_select_ct = 1;
             }   
             printf("您选择的对手是:%s\n",computer_name);    
       }   
       // 自己出拳
       while(is_select_own)
       {
             printf("\n请选择您出拳方式:\n[1].石头 [2].剪刀 [3].布\n");
             scanf("%d",&own_no);       
             switch(own_no)
             {
                 case 1:
                    // c语言中,对char数组直接赋值
                    strcpy(own_name,"石头");
                    is_select_own = 0;
                    break;
                 case 2:
                    strcpy(own_name,"剪刀");
                    is_select_own = 0;
                    break;
                 case 3:
                    strcpy(own_name,"布");
                    is_select_own = 0;
                    break;
                 default:
                    strcpy(own_name,"无效的出拳");
                    is_select_own = 1;
             }   
             printf("您的出拳方式是:%s\n",own_name);    
       }  
       // 对手出拳(随机生成0~2)
       srand((unsigned)time(NULL));// 以时间作为随机种子
       // 随机生成对手出拳的序号(0~2)
       player_no = rand()%3+1;
       switch(player_no)
       {
           case 1:
              // c语言中,对char数组直接赋值
              strcpy(player_name,"石头");
              break;
           case 2:
              strcpy(player_name,"剪刀");
              break;
           case 3:
              strcpy(player_name,"布");
              break;              
       }   
       printf("\n%s的出拳方式是:%s\n",computer_name,player_name);    
       // 双方比较
       if((own_no == 1 && player_no == 2)||(own_no == 2 && player_no == 3)||(own_no == 3 && player_no == 1))
       {
           printf("\n恭喜,您获胜!\n");
       }
       else if(own_no == player_no){
           printf("\n平局!\n");
       }
       else
       {
           printf("\n很遗憾,您输了!\n");
       }
       // 退出游戏
       printf("\n是否退出游戏?[Y/N]\n");
       getchar();// 消除回车
       scanf("%c",&stop);
       if(stop == 'Y' || stop == 'y')
       {
           is_select_ct = 0;// 默认,选择对手操作是不重复的   
           is_select_own = 0;// 默认,自己出拳操作是不重复的
           isStop = 0;
           printf("\n游戏结束!\n");
       }
        else
       {
           // 还原状态
           is_select_ct = 1;// 默认,选择对手操作是不重复的   
           is_select_own = 1;// 默认,自己出拳操作是不重复的
           isStop = 1;
       }
   }
    
    return 0;
}

二、补充

  • 什么是素数?

素数也被称作质数,只能被1和自身整除的数就叫做素数。

三、作业

上机题

  • 计算n以内所有正奇数的和 ? n值通过键盘输入

代码:
 /*
输入n值,计算1-n以内所有正奇数的累加和
*/
#include <stdio.h>

int main()
{
    int sum = 0;//累加和
    int i = 0;//循环变量
    int n;

    printf("请输入一个整数:%d\n",n);
    scanf("%d",&n);

    do
    {
        if(i % 2 != 0)//奇数
        {
            sum += i;
        }
        i++;
    }while(i <= n);

    printf("1-n之间所有正奇数的累加和是:%d\n",sum);
    return 0;
}
运行效果:

  • 计算 1 + 1/(2 * 3) + 1/(3 * 4) + ...+ 1/(n * (n + 1)) = ?直到最后一相值小于0.00001为止

 代码:
/*
计算1+1/(2*3)+1/(3*4)+...+1/(n*(n+1))=?直到最后一项的值小于0.00001为止
*/
#include <stdio.h>
#include <math.h>

int main()
{
    int n = 2;
    //int n2 = 3;
    double sum = 1;
    double y;
//    double y = 1 / (n * (n + 1));
   // int sum += y;
//    double sum1 = sum + 1;
    do
    {
        y = 1.0/(n*(n+1));
      //  n++;
      //  sum += y;
        if(y < 1.0e-5)
        {
            break;
        }
        sum += y;
        n++;
    }while(1);

    printf("此时计算式的值为:%lf\n",sum);
    return 0;

}
运行效果:

  • 计算1+1/2 - 1/3 + 1/4 - 1/5 ...+1/n= ? n通过键盘输入

 代码:
 /*
 计算1+1/2-1/3+1/4-1/5+...+1/n=?,n通过键盘输入;
*/

#include <stdio.h>

int main()
{
    double sum = 1;//保存累加和
    double b = 1;//分子
//    double sum2=0;//偶数项和奇数项
    int a = 2;//分母
    int n;//输入的整数
//    double i = (1/a);//单个分式

    //输入整数
    printf("请输入一个整数:%d\n",n);
    scanf("%d",&n);

    while(a <= n)
    {
            sum += b/a;
            a = a+1;
            b = -b;
    }
    printf("表达式的值为:%.2lf\n",sum);

    //sum = sum1 - sum2;

   // printf("表达式的值为:%.2lf=%.2lf-%.2lf\n",sum,sum1,sum2);

    return 0;
}
运行效果:

  • 计算n的阶乘 ? n! = 123.....*n n值通过键盘输入

     代码:
    /*
     计算n的阶乘?n! = 123...*n n值通过键盘键入;
    */
    #include <stdio.h>
    
    int main()
    {
        int n;//键盘输入n值
        int pro = 1;//阶乘值
        printf("请输入您要计算的阶乘值:%d\n",n);
        scanf("%d",&n);
    
        for(int a = 1;a <= n;a++)
        {
            pro *= a;
        }
    
        printf("您所计算的阶乘值为:%d\n",pro);
        return 0;
    }
    
    运行效果:

  • 输出半径为1~10的圆面积,面积大于100时停止

     代码:
     /*
     输出半径为1-10的圆面积,面积大于100时停止;
    */
    #include <stdio.h>
    
    #define PI 3.1415926
    
    int main()
    {
        int r;//半径
        double s;//圆面积
    
        for(r = 1;r >= 1 && r <= 10;r++)
        {
            s = PI * (r * r);//面积
            printf("\n当r=%d时,s=%.2lf\n",r,s);
            if(s > 100)
            {
                break;
            }
        }    
        //printf("当r=%d时,s=%.2lf",r,s);
        return 0;
    }
    运行效果:

  • 求输入的十个整数中正数的个数及其平均值

     代码:
     /*
     求输入的十个整数中正数的个数及其平均值;
    */
    #include <stdio.h>
    
    int main()
    {
        int a,b=0,c=0,sum;//总数,累加和,个数,和
        printf("请随意输入十个整数:\n");
    //    scanf("%d",&a);
    
        for(a = 0;a <= 10;a++)
        {
            scanf("%d",&sum);
            if(sum > 0)
            {
                b += sum;//整数累加和
                c++;//个数
            }
        }
        printf("在您输入的十个整数中,有%d个正数,且平均值为%d\n",c,b/c);
        return 0;
    }
    运行效果:

  • 打印出100以内能整除7之外的的自然数

     代码:
     /*
     打印出100以内的能够整除7之外的自然数
    */
    #include <stdio.h>
    
    int main()
    {
        int i;
    
        for(i = 1;i <= 100;i++)
        {
            if(i % 7 == 0)
            {
                printf("%d\n",i);
            }
        }
        printf("\n");
        return 0;
    }
    
    运行效果:

  • 打印乘法表

     代码:
     /**
     * 嵌套循环案例:九九乘法表
     */
    #include <stdio.h>
    int main()
    {
        // 分析
        //   九九乘法表本质上行列构成三角形
        //   九九乘法表 总共9行
        //   九九乘法表 列受到行的影响:列数 <= 行数
        //   如果涉及到行列,我们首选双重嵌套for循环,外层循环控制行数,内层循环控制列数
        // 外层循环控制行:9行
        for(int i = 1;i <= 9;i++)
       {
            // 内层循环控制列:列 <= 当前行
            for(int j = 1;j <= i;j++)
           {
                // 生成当前行中的所有乘法序列
                printf("%d×%d=%d\t",j,i,i*j);
           }
            
            // 一行中所有列输出完毕,需要换行
            printf("\n");
       }
        printf("\n");
        return 0;
    }
    
    运行效果:

  • 我国古代数学家张丘建在《算经》一书中提出的数学问题:鸡翁一值钱五,鸡母一值钱三,鸡雏三 值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?

     代码:
    /**
      我国古代数学家张丘建在《算经》一书中提出的数学问题:
      鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、>鸡母、鸡雏各几何?
     **/
    #include <stdio.h>
    int main(void)
    {
        int x,y,z;//鸡翁x只,鸡母y只,鸡雏z只
        
        for(x = 1;x <= 20;x++)//百钱最多买20只鸡翁
       {    
            for(y = 1;y <= 33;y++)//百钱最多买33只鸡母
           {    
                for(z = 3;z <= 300;z+=3)//百钱最多买300只鸡雏
               {    
                    if((x + y + z)==100 && (5 * x + 3 * y + z / 3 == 100))          
                   {
                        printf("鸡翁有%d只,鸡母有%d只,鸡雏有%d只\n",x,y,z);
                   }
               }
    
           }
       }
        return 0;
    }
    
    运行效果:

  • 从键盘上输入多个无符号整型数据,直到 0 结束 ,输出所输入数据中的最大值

     代码:
     /*
     键盘上输入多个无符号整型数据,直到0结束,输出所输入数据中的最大>值;
    */
    #include <stdio.h>
    
    int main()
    {
        unsigned int i,max;
        printf("请输入任意几个无符号整型数据:");
        scanf("%d",&i);
    
        max = i;
        while(i != 0)
        {
            if(max < i)
            {
                max = i;
            }
            scanf("%d",&i);
    
        }
        printf("输入数据中的最大值为:%d\n",max);
        return 0;
    }
    
    运行效果:

思考题

  • 判断一个数是不是回文数。(回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整 数。如:12321

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值