C语言笔记第02章:三大基本结构(二)

简介: C语言笔记第02章:三大基本结构

3.循环结构

学习本章之前:循环结构是结构化程序设计的三种基本结构之一,在程序设计中对于那些需要重复执行的操作应该采用循环结构来完成,利用循环结构处理各类重复操作既简单又方便。所以相较于前面两种结构的难度会有所提升,所以在此章节的代码和语法知识更需要花时间消化并且上机操作❤️

  • 使用循环可以多次重复地执行多条语句,这里的“多条语句”称为循环体。在C语言中,可以使用三种循环,分别是:while、do…while、for
  • 在这些语句中,循环体被重复执行的次数由循环条件控制,称为控制表达式(controlling expression)。
  • 这是一个标量类型的表达式,也就是说,它属于一个算术表达式或指针表达式。如果控制表达式的值不等于 0,循环条件为 true,反之,循环条件为 false。
  • 语句 break 和 continue 用于在一次循环还未执行完时,跳转出循环或返回到循环头部。

📍 无论是 while,do…while 还是 for,他们都具有四要素:

  • 循环变量初始化:循环的起始位置
  • 循环变量迭代:所执行的步长,统计变化情况,识别是否继续
  • 循环条件判断:标记循环继续的条件
  • 循环操作(循环体):循环所执行的内容

3.1 for 循环

3.1.1 基本语法

for(循环变量初始化;循环条件判断;循环变量迭代)
{
    语句1;
    语句2;
    …………;
} 

🚩在一个典型的 for 循环中,在循环体顶部,下述三个动作需要执行:

  • 表达式 1:循环变量初始化
    只计算一次。在计算控制表达式之前,先计算一次表达式 1,以进行必要的初始化,后面不再计算它。
  • 表达式 2:循环条件判断
    每轮循环前 都要进行循环条件判断,以判断是否需要继续本轮循环。当控制表达式的结果为 false,结束循环。
  • 表达式 3:循环变量迭代,也叫调节器
    调节器(例如计数器自增)在每轮循环结束后 且表达式 2 计算前 执行。即,在运行了调节器后,再执行表达式 2进行判断。

📍 执行过程如图:

📝 我们来举个例子

#include<stdio.h>
int main()
{
    int i;
    /*在这里面:
     1. 循环变量初始化:i = 0
     2. 循环条件判断:i < 3
     3. 循环变量迭代:i++
     4. 循环体:printf("print the value of i =%d\n", i);
    */
    for(i = 0; i < 3; i++)
    {
        printf("print the value of i =%d\n", i);
    }
    return 0;
}

运行结果:

📍 一次循环的执行过程:

  • 循环变量赋初值: 将 i 的初始值变成 0
  • 循环条件判断: 判断 i 是否小于3,若小于3则为true,其它为false
  • 循环变量值变化: i 的值自动加1

3.1.2 中途终止循环 - return&break

第 3.5 节会再次介绍 break,这里预热一波

1️⃣ 方式一:return

#include<stdio.h>
int main()
{
    int i;
    for(i = 0; i < 3; i++)
    {
        if(i == 1)
        {
            return 0;//直接退出程序,这也是中途终止循环的方式
        }else
        {
            printf("%d", i);   
        }
    }
    printf("My love end");
    return 0;
}

💬 当 i==1 时直接退出程序,因此这道题的输出结果就是 0 。因为 i为1的时候就直接退出程序了,并未printf打印结果,也并未打印My love end。注意与第二种方式 break 进行比较哦。

2️⃣ 方式二:break

break语句用于终止某条语句块的执行,一般使用在 switch或者 循环(for,while,do…while)中,表示退出 switch 或退出循环。

#inlcude<stdio.h>
int main()
{
    int i;
    for(i = 0; i < 3; i++)
    {
        if(i == 1)
        {
            break;//退出for循环,但并未退出程序
        }else
        {
            printf("%d", i);   
        }
    }
    printf("My love end");
    return 0;
} 

💬 当 i==1 时直接退出for循环,但并未退出程序,因此控制台的打印结果为0My love end

3.1.3 跳过本次循环,进入下次循环 - continue

在第 3.5 节会再次介绍continue,这里预热一波

除了break 语句可以结束循环体外,这里再介绍一个continue语句,这个语句跟break语句一样,也可以结束循环体,但不同的是,它只是结束本次循环,循环体会跳过continue后面的语句,直接去再次判断循环条件,进行下一次的循环操作。

📝 举个例子

#include<stdio.h>
int main()
{
    int i;
    for(i = 0; i < 3; i++)
    {
        //即当i等于1的时候,执行 continue语句,结束本次循环
        //即当i等于1的时候不会打印信息,直接执行下一次循环
        if(i == 1) 
        { 
            continue;
        }
        printf(" print the value of i = %d\n", i);
    }
    return 0;
}

运行结果如下:

通过以上例子,我们可以看到,运用 breakcontinue 语句,我们可以更加灵活的使用循环语句来控制程序的流程。

3.1.4 🚩 一个思考

for(表达式1;表达式2;表达式3)
{
  循环操作;    
}

我们已经知道了for循环的基本结构,但我们一定要遵循那个位置标准吗?这么说吧,我们一定要把循环变量初始化放在表达式1吗,一定要把循环条件判断放在表达式2的位置吗,一定要把循环变量迭代放在表达式3的位置吗?

✏️ 不是的,这些只是一些规范,你可以遵循,也可以不遵循。我们来举个例子,把位置改一改。

#include<stdio.h>
int main()
{
  int i = 0; //循环变量初始化
    for(;i < 3;)//表达式1和表达式2的位置空缺,甚至我们把 i < 3 的位置改到循环体中也是没问题的
    {
      printf("%d\n",i);
        i++; //循环变量迭代
    }
}

于是我们发现了,其实表达式1,2,3都可以不放任何东西,可以放到其它位置的。再来看一个更特殊的:

#include<stdio.h>
int main()
{
    for(;;)//三个位置什么都不放,但两个分号无论如何是一定都要写的
    {
        printf("I love you ,软件协会");
    }
}

你可以发现,循环变量初始化循环条件判断循环变量迭代都没有,而且你应该意识到这个for循环居然无法退出循环(可以自己运行一下看看),这叫做**死循环**。这是我们必须避免的,在程序中绝对不能够出现死循环,带给程序的伤害比拒绝你表白的女孩给你的伤害更大!

3.2 while 循环

3.2.1 基本语法

循环变量初始化;
while(循环条件判断)
{
    循环体;
    循环变量迭代;
}
  1. 在while循环前,先进行循环变量初始化。
  2. 再判断while后边括号内的表达式是否为真,若为真即执行大括号内的语句,若为假,则跳过while循环结构执行大括号下方的第一条语句。
  3. 若为真,当执行完大括号内语句后,再次回到2去判断,执行。
  4. 直到while后小括号内表达式的表达式为假,结束循环。

📍 注意:若在while的大括号内执行了 break语句,则立刻结束循环结构,开始执行大括号外下方的第一条语句。

3.2.2 实例演示

📝 例子1:

#include <stdio.h>
int main()
{
    int a = 5, b = 10;
    while(b > a) //即若b > a 为真就执行大括号内的语句,
    {                  
        //若为假则执行大括号下方语句
        printf("while looping a = %d, b = %d\n", a, b);
        a++;
    }
    printf("while loop over\n");
    return 0;
}

运行结果:

即当,a的值等于10时,b>a 不成立,循环结束。

📝 例子2:

#include <stdio.h>
int main()
{
    int a = 5, b = 10;
    while(b > a)            //即若b > a 为真就执行大括号内的语句,
    {                       //若为假则执行大括号下方语句
        printf("while looping a = %d, b = %d\n", a, b);
        if(a == 8)
        {
            break; //如果a等于8跳出while循环,注意哦,如果是return则就是结束整个程序
        }
        a++;
    }
    printf("while loop over\n");
    return 0;
}

运行结果如下:

将例子1和例子2分别执行一下,查看打印输出信息的不同,体会一下while循环的使用,以及 break 的用法。

3.2.3 while死循环

不多说明,上代码演示最简单的while死循环,细品。

#include<stdio.h>
int main()
{
  while(true)
    {
    }
}

3.2.4 注意事项

  • 循环条件判断必须返回一个布尔值的表达式
  • while循环是先循环条件判断再执行大括号中循环操作

3.3 do…while 循环

3.3.1 基本语法

不像 forwhile 循环,它们是在循环头部 检查循环条件。在 C 语言中,do…while 循环是在循环的尾部 检查它的条件。

do…while 循环与 while 循环类似,但是 do…while 循环会确保至少执行一次循环

循环变量初始化;
do
{
  循环操作;
    循环变量迭代;
}while(循环条件判断);
  • 首先执行大括号内语句
  • 判断while后边括号内的表达式是否为真,若为真回到第一步,若为假,则退出while循环结构,执行大括号下方的第一条语句。

3.3.2 实例演示

#include<stdio.h>
//输出结果:012【3】
int main() {
  int i = 0;//循环变量初始化
  do
  {
    printf("%d", i);//循环操作
    i++;//循环变量迭代
  } while (i < 3);//循环条件判断
  printf("【%d】", i);
}

3.3.3 注意事项

  • 循环条件判断必须返回一个布尔值的表达式
  • do…while循环是先执行大括号中的循环操作再进行循环条件判断,因此循环操作会至少执行一次。
  • 注意 while(循环条件判断) 的后面有一个;,千万不要忘记写哦。

3.4 嵌套循环

3.4.1 基本介绍

  • 将一个循环放在另一个循环体内,就形成了嵌套循环,其中 forwhiledo...while均可以作为外层循环和内层循环,建议一般使用两层即可,最多不要超过三层,否则代码的可读性很差。
  • 实际上嵌套循环就是把内层循环当成外层循环的循环体,当只有内层循环的循环条件为false时,才会完全跳出内层循环,才可以结束外层的当次循环,开始下一次循环。

3.4.2 实例演示

📝 示例1

#include<stdio.h>
int main() {
  for (int i = 1; i <= 3; i++)//外循环
  {
    for (int j = 1; j <= 4; j++)//内循环
    {
      printf("i = %d ; j = %d\n", i, j);
    }
  }
}

📝 示例2:输出三三乘法表

#include<stdio.h>
//三三乘法表
int main() {
  for (int i = 1; i <= 3; i++)//外循环
  {
    for (int j = 1; j <= i; j++)//内循环
    {
      printf("%d * %d = %d\t", i, j, i * j);// \t是水平制表符,即向右移动8个单位
    }
    printf("\n");
  }
}

运行结果:

3.5 跳转控制语句

循环控制语句改变你代码的执行顺序。通过它你可以实现代码的跳转。

📍 C 提供了下列的循环控制语句。

控制语句 描述
break 语句 终止循环或 switch 语句,程序流将继续执行紧接着循环或 switch 的下一条语句。
continue 语句 告诉一个循环体立刻停止本次循环迭代,重新开始下次循环迭代。
goto 语句 将控制转移到被标记的语句。但是不建议在程序中使用 goto 语句。

3.5.1 break

C 语言中 break 语句有以下两种用法:

  • 当 break 语句出现在一个循环内时,循环会立即终止,且程序流将继续执行紧接着循环的下一条语句。
  • 它可用于终止 switch 语句中的一个 case。

📍如果小伙伴使用的是嵌套循环(即一个循环内嵌套另一个循环),break 语句会退出离自己最近的那层循环,然后开始执行该块之后的下一行代码。

3.5.2 continue

  • C 语言中的 continue 语句有点像 break 语句。但它不是强制终止,continue 会跳过当前循环中的代码,强迫开始下一次循环。
  • 对于 for 循环,continue 语句执行后自增语句仍然会执行。对于 whiledo…while 循环,continue 语句重新执行条件判断语句。

3.5.3 goto

💬goto语句在此不要求小伙伴们掌握,只需要了解,知道有这么个东西,并且要求大家非必要不使用goto语句。

📍在任何编程语言中,都不建议使用 goto 语句。因为它使得程序的控制流难以跟踪,使程序难以理解和难以修改。任何使用 goto 语句的程序可以改写成不需要使用 goto 语句的写法。原因如下:

  • goto语句是低级语言的表征。它很灵活,灵活到没有任何拘束,在函数体内直来直往。函数体内可能含有一些嵌套的循环,这就意味着goto可以跳进跳出循环而无所顾忌。当程序比较复杂时很容易造成程序流程的混乱。

  • 滥用goto语句,程序无规律,可读性差。在团队开发中影响效率,以后调试和维护程序的过程会令同事和自己都头秃。

任何事物都有两面性,goto语句灵活性如果在适当的地方发挥出来确实非常有用的,毕竟现在有些地方需要无条件的跳转语句。尤其在汇编语言中,如果不使用类似于goto语句的jmp指令,那么其就无法实现循环和条件分支。所以在汇编语言中,goto语句用处还是很大的。使用goto可以使程序变得更加可扩展。当程序需要在错误处理时释放资源时,统一到goto处理最方便。这也是为什么很多大型项目,开源项目,包括Linux,都会大量的出现goto来处理错误!

但现在的编程趋势是要模块化、结构化、所以大多书上已经不建议使用无条件分支的goto语句了,尽管现在大多数语言还在支持它,但还是少用为妙,尤其是像C语言小白玩家,还是瑟瑟发抖的乖乖用break慢慢跳吧。

3.5.4 return

return 使用在方法中,表示跳出/退出所在的方法。如果 return 写在 main 方法中,则会退出程序。

相关文章
|
3月前
|
网络协议 编译器 Linux
【C语言】结构体内存对齐:热门面试话题
【C语言】结构体内存对齐:热门面试话题
115 0
|
2月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
112 16
|
3月前
|
编译器 C语言 Python
C语言结构
C语言结构
25 0
|
4月前
|
存储 编译器 程序员
C语言程序的基本结构
C语言程序的基本结构包括:1)预处理指令,如 `#include` 和 `#define`;2)主函数 `main()`,程序从这里开始执行;3)函数声明与定义,执行特定任务的代码块;4)变量声明与初始化,用于存储数据;5)语句和表达式,构成程序基本执行单位;6)注释,解释代码功能。示例代码展示了这些组成部分的应用。
154 10
|
4月前
|
C语言
C语言程序设计核心详解 第四章&&第五章 选择结构程序设计&&循环结构程序设计
本章节介绍了C语言中的选择结构,包括关系表达式、逻辑表达式及其运算符的优先级,并通过示例详细解释了 `if` 语句的不同形式和 `switch` 语句的使用方法。此外,还概述了循环结构,包括 `while`、`do-while` 和 `for` 循环,并解释了 `break` 和 `continue` 控制语句的功能。最后,提供了两道例题以加深理解。
111 7
|
4月前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
4月前
|
C语言
C语言程序设计核心详解 第三章:顺序结构,printf(),scanf()详解
本章介绍顺序结构的基本框架及C语言的标准输入输出。程序从`main()`开始依次执行,框架包括输入、计算和输出三部分。重点讲解了`printf()`与`scanf()`函数:`printf()`用于格式化输出,支持多种占位符;`scanf()`用于格式化输入,需注意普通字符与占位符的区别。此外还介绍了`putchar()`和`getchar()`函数,分别用于输出和接收单个字符。
|
4月前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。
|
5月前
|
测试技术 C语言 C++
【C语言刷题训练——6】鹏哥C语言刷题训练营笔记,含代码讲解改进
【C语言刷题训练——6】鹏哥C语言刷题训练营笔记,含代码讲解改进
|
5月前
|
存储 C语言
【C语言】鹏哥C语言刷题训练营——第5节内容笔记(含代码全面分析和改进,讲解)
【C语言】鹏哥C语言刷题训练营——第5节内容笔记(含代码全面分析和改进,讲解)