news 2026/10/16 7:28:49

C语言修炼——三大结构之循环结构!!!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言修炼——三大结构之循环结构!!!

目录

  • 1.浅析循环结构
  • 2.循环结构的介绍
    • 2.1 while循环
    • 2.2 for循环
    • 2.3 do_while循环
  • 3.案例解析——猜字谜游戏

1.浅析循环结构

上一篇我们学习了分支结构,完成了关机病毒程序,里面我们用到了一个简单又经典的循环结构。
循环结构、顺序结构、分支结构都是我们生活的一种抽象化。例如我们大多数同学都要经历学校——工作——退休,这是一种顺序结构;在学校上学或者参加工作,我们可以选择不同的学校和不同的城市,这是一种分支结构;在学校我们要日复一日的读书,上班了我们要日复一日的工作,退休了我们要日复一日的等待残生了却。再往大了看,一代又一代的人都要经历受教育——社会建设——退休,这里面的循环往复又岂止眼前之语。

2.循环结构的介绍

我们通常使用的循环结构有:for循环、while循环、do_while循环。

2.1 while循环

while(表达式){语句}

或

while(表达式)单个语句

但后者却不是好的代码风格,我们应该切记C语言程序需要具备可读性与可扩展性。
while循环的执行流程:

(continue——跳出本次循环,break——终止循环)
while语句先对表达式进行判断,表达式为真,即结果为非零数或true (布尔类型),则执行语句。一直为真则循环执行,直到为假。
给出代码示例并分析如下:

#include<stdio.h>// 打印1-10intmain(){inti=1,input=0;scanf("%d",&input);// 记录用户的输入while(i<11)// 当i<11,即i为1到10的数时表达式结果为真,返回值不为0,循环执行{if(i==input)// 当i等于input时跳出循环,停止打印{break;}printf("%d ",i);// 打印 ii=i+1;// 每次循环结束,i加1}return0;}

(输入11,i永远不可能等于input,可不break,正常走完循环次数,1到10全部打印)

  • 输入:11
  • 结果:1 2 3 4 5 6 7 8 9 10


(输入6,则打印6之前break跳出循环)

  • 输入:6
  • 结果:1 2 3 4 5

让我们来分析一下这个代码。
上例中,我们设置while循环的表达式为i < 11,则最多打印到10。
每次循环结束i加1,所以我们想正常打印1~10,就要避免break提前跳出循环,必须输入一个大于10的数。
如果我们不想打印到10,想提前break结束打印,需要注意,break的if判断写在打印之前,所以输入值等于最终打印的数字加1。这里最终的目标数是5,即需要打印1到5,则输入值为6。
如果我们把break跳出循环,换成continue跳出当次循环,再输入相同的输入值11、6,会是什么结果?

2.2 for循环

for循环是最常用的循环语句,我们来看看它的语法示例:

for(表达式1;表达式2;表达式3;){语句}// 相同的,单个语句也可以不带花括号{},直接跟在for之后

其中:

  • 表达式1用于循环变量的初始化,如int i = 0,且循环变量的初始化只执行一次。
  • 表达式2用于循环条件的判断,如i < 10,如果表达式2结果为0循环结束,否则继续。
  • 表达式3用于循环变量的调整,如i++或i+=2。
  • 循环变量的初始化和循环条件一起决定了循环变量的范围,在此基础上,调整则影响了循环次数。

我们来看看执行流程:

现要求打印一个腰长为10的等腰直角三角形,如下图所示。

#include<stdio.h>intmain(){// 和if嵌套类似,套娃for(inti=0;i<10;i++)// 外循环:i代表第i+1行,一次外循环代表一行{// 内循环:j的取值范围代表星号*个数,j的范围随外循环次数增加而减少for(intj=0;j<10-i;j++){printf("* ");}printf("\n");// 每次外循环结束,一行打印完毕,打印换行符,进入下一行即下一遍外循环}return0;}

我们可以看到,无论是外循环还是内循环都只执行了一次循环变量的初始化。往后都是表达式2(判断循环是否继续)——语句(继续循环,执行语句)——表达式3(调整循环变量)的循环往复,直到表达式2结果为0,循环结束。

2.3 do_while循环

do while是三种循环语句中使用最少的,但在某些情况下,它也很有用(Tips:其实goto语句也可以实现循环结构,但万一使用不当,后果很严重)。
下面我们来看看它的语法结构:

do{语句;}while(表达式);

while和for这两种循环都是先判断,满⾜条件就进⼊循环,一旦不满⾜就结束循环。
do while是先进⼊循环体,执⾏循环语句,再判断。表达式为真,则进入第二次循环;表达式为假,结束循环。
其执行流程如下:

do_while通常需要我们在循环体外初始化循环变量。
do_while是先执行再判断,所以do_while循环至少执行一次,这是它的特殊所在。
代码示例如下:

#include<stdio.h>intmain(){// 打印1-10的数inti=1;// 循环体外初始化循环变量do{// 先执行printf("%d ",i);i=i+1;// 调整循环变量}while(i<11);// 再判断:当i >= 11,终止循环,不再打印return0;}

结果:

3.案例解析——猜字谜游戏

到这里我们已经学完了三大结构。虽然下面有些琐碎的知识,但会用即可,我们直接来尝试完成一个猜字谜游戏。
先给出完整代码(需要自取,否则跳过看详解):

#include<stdio.h>#include<windows.h>#include<stdlib.h>//提供rand函数,功能为基于某个数(种子)生成随机数;srand函数设置、改变种子#include<time.h>//提供time函数,用于获取一个时间戳,可作为种子voidmenu()//菜单函数,提供菜单功能{printf("**************\n");printf("****1.Play****\n");printf("****0.Exit****\n");printf("**************\n");}voidgame()//game函数,提供游戏功能{//times规定并记录游戏次数,guess存储用户的输入值,r为随机数且此处被赋值范围为1~100inttimes=5,guess=0,r=rand()%100+1;while(times){scanf("%d",&guess);if(guess>r){printf("太可惜了,你猜大了!\n");}elseif(guess<r){printf("太可惜了,你猜小了!\n");}else{printf("芜湖~,恭喜你猜对了!!!\n");break;}times--;if(guess>r||guess<r)//打印剩余猜测次数{printf("你只剩下%d次机会啦!\n",times);}}if(times==0)//一轮游戏结束,打印正确答案{printf("\n猜错了哦,正确答案应该是%d\n",r);}}intmain(){printf("哼哼( ̄、 ̄),大笨蛋赶快看清楚本大爷的名字,本大爷叫作“猜数字游戏”,你应该知道怎么玩。\n");intinput=0;//存储输入值,用于开始游戏或结束游戏srand((unsignedint)time(NULL));do{menu();printf("请选择:>");scanf("%d",&input);system("cls");//系统命令:清屏if(input==1){printf("\n开始游戏噜!!!赶快输入你猜的数字吧:\n");}switch(input)//代码核心部分{case1:game();break;case0:printf("\n游戏结束了,下次再来吧\\(n.n)/Bye~\n");break;default:printf("输入错误,请重新输入\n");break;}}while(input);return0;}

分析:首先从main函数起始

intmain()//程序入口{// 提前说明游戏,可写入menu一起打印,亦可与菜单函数结合并拓展,制作跳转到另一个游戏说明页面功能printf("哼哼( ̄、 ̄),大笨蛋赶快看清楚本大爷的名字,本大爷叫作“猜数字游戏”,你应该知道怎么玩。\n");intinput=0;// 存储用户输入值,即0或1,开始或结束游戏srand((unsignedint)time(NULL));// time函数获取并返回时间戳,强制类型转换为无符号整型,再用srand设置种子// do_while循环:走来先打印游戏菜单界面,让玩家用户选择开始或结束do{menu();// 打印游戏菜单// 用户进行输入printf("请选择:>");scanf("%d",&input);// 根据输入,开始游戏或结束游戏system("cls");// 系统命令:清屏。开始游戏需要打印游戏界面if(input==1)// 如果开始游戏,就打印一些欢迎话术,增加一点氛围感{printf("\n开始游戏噜!!!赶快输入你猜的数字吧:\n");}switch(input)// 游戏主体模块,分支结构{// 都加了break,只执行匹配的case,避免分支重叠case1:game();break;// input为1,开始游戏,执行game函数case0:printf("\n游戏结束了,下次再来吧\\(n.n)/Bye~\n");break;// input为0,游戏结束default:printf("输入错误,请重新输入\n");break;// 其他非法输入,但input不为0,提示错误信息}}while(input);// 开始游戏,input为1;非法输入,input不为0。两个都是非0数,都继续循环重新开始return0;}

main函数可分为三个核心步骤:菜单函数—>scanf—>选择与分支(三个分支:开始游戏、结束游戏、选择错误)。
游戏开始需要给出一个菜单。我们可以先写一个简单的函数menu(这里涉及函数知识,可以不用管,按照示例代码写即可)。

voidmenu()// 菜单函数,提供菜单功能{printf("**************\n");printf("****1.Play****\n");printf("****0.Exit****\n");printf("**************\n");}

下一环节需要scanf,通过用户的输入选择分支。第三个环节开始之前,我们可以先使用system(“cls”)清屏保证接下来的游戏画面清爽。

在第三个环节,需要考虑玩家非法输入的可能,我们应该给用户重新选择的机会,再走一遍流程,即menu—>输入—>分支。

因此,input有三种可能情况,可以用switch来设计一个多分支结构:case 1、case 0 和 default。
case 1进入具体的游戏逻辑;
case 2需要游戏结束的话术;
default需要非法输入的错误提醒。
以上3种情况不能有分支重叠,都加个break直接结束switch语句。

可以发现,游戏开始和非法输入,全部流程结束之后,都需要进入下一轮循环,让用户重新选择开始或结束游戏。
因此,特别将input设计为0,此时游戏结束,do while循环结束。
不管用户选择游戏开始,input 为 1,还是用户非法输入,input都是非零值,进入do while的第二次循环。

以上是main函数所有设计。我们只需要补充game函数就大功告成。
代码如下:

voidgame()// game函数,提供游戏功能{// times规定并记录游戏次数,guess存储用户的输入值,r为随机数且此处被赋值范围为1~100inttimes=5,guess=0,r=rand()%100+1;while(times){// 当times减小到 0停止循环,一轮游戏结束scanf("%d",&guess);if(guess>r)// if else语句用于判断是否猜中数字{printf("太可惜了,你猜大了!\n");}elseif(guess<r){printf("太可惜了,你猜小了!\n");}else{printf("芜湖~,恭喜你猜对了!!!\n");break;}times--;// 调整循环变量if(guess>r||guess<r)// 打印剩余猜测次数{printf("你只剩下%d次机会啦!\n",times);}}if(times==0)// 循环结束,即一轮游戏结束,打印正确答案{printf("\n猜错了哦,正确答案应该是%d\n",r);}}

核心流程大致如下:输入猜测值 —> 判断 —> 给出提示/反馈(三个分支 ‘ > ’、‘ == ’、‘ < ’)。
很明显这三个流程属于一个循环过程,我们还需要一个值来代表可循环次数——可猜测次数。
我们可以先在循环体外,进行游戏次数times的初始化。
游戏开始,先scanf等待用户输入,再对输入值判断,提示玩家猜测值大了或者小了。如果等于,猜成功了就结束,直接break终止循环。
如果玩家一直没猜中,需要考虑次数是否耗尽,可以直接告诉玩家正确答案然后结束。

game函数完毕,返回main函数。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 7:28:25

神经网络模糊自整定PID控制器在AUV运动控制中的仿真实现

做水下机器人控制这些年&#xff0c;最折腾我的往往不是水动力建模本身&#xff0c;而是“仿真里参数明明调好了&#xff0c;换个工况就拉垮”。后来在AUV&#xff08;自主水下车辆&#xff09;的定深、航向这类典型运动控制问题上&#xff0c;我开始把神经网络、模糊逻辑和自整…

作者头像 李华
网站建设 2026/10/16 7:27:23

数字广播为何成智能汽车安全底线?从应急通信原理到强制国标落地

做汽车通信这行的&#xff0c;应该都遇到过类似的灵魂拷问&#xff1a;现在车都联网了&#xff0c;5G、OTA、卫星通信都往车里塞&#xff0c;为什么还要强制装一个“收音机”&#xff1f;我最早被问住是在一次标准讨论后的茶歇&#xff0c;某车企的电子电气架构负责人语气里带着…

作者头像 李华
网站建设 2026/10/16 7:27:14

GEO优化全攻略:从行业趋势到服务商选型,一文读懂AI营销新赛道

一、行业现状与GEO优化核心投放价值 随着AI搜索生态全面规模化落地&#xff0c;国内主流智能AI平台已形成独立、差异化的算法体系与内容分发机制&#xff0c;行业竞争从传统流量抢夺&#xff0c;升级为AI知识信源占位与品牌心智抢占。在此行业趋势下&#xff0c;GEO(Generative…

作者头像 李华
网站建设 2026/10/16 7:27:00

Excel多表关联神器实测:告别VLOOKUP低效操作,快速合并跨表数据

做数据分析或者报表的人&#xff0c;应该都有过这样的经历&#xff1a;Excel表越堆越多&#xff0c;需要的数据散落在好几个文件里。每次要做月报&#xff0c;先打开销售表&#xff0c;再打开客户表&#xff0c;对着工号或者订单编号一个一个VLOOKUP&#xff0c;辛辛苦苦拉出来…

作者头像 李华
网站建设 2026/10/16 7:25:45

STM32电子密码锁状态机实战:从Proteus仿真到实物调试

简介&#xff1a;本资源是一套基于STM32F103C6芯片设计的电子密码锁完整嵌入式开发工程&#xff0c;面向嵌入式初学者、单片机课程设计学生及STM32入门开发者&#xff0c;聚焦密码验证、LCD显示、矩阵键盘交互与EEPROM数据存储等典型功能实现。压缩包共277个文件&#xff0c;主…

作者头像 李华
网站建设 2026/10/16 7:25:30

双目ORB-SLAM2与EuRoC数据集实战:从环境配置到轨迹评估

1. 为什么选择双目ORB-SLAM2与EuRoC数据集这个组合双目视觉SLAM一直是机器人、无人机、AR/VR领域里绕不开的一块硬骨头。单目SLAM存在尺度不确定和初始化漂移的问题&#xff0c;RGB-D虽然能直接拿到深度&#xff0c;但受限于红外结构光的测量距离和室外强光干扰&#xff0c;真正…

作者头像 李华