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

本文详细介绍了C语言中的while、for和do_while三种循环结构,通过实例演示了它们的执行流程和应用,并以猜字谜游戏为例展示了循环结构的混合使用。
摘要由CSDN通过智能技术生成


循环结构

1.浅析循环结构

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

2.循环结构的介绍

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

2.1 while循环

while (表达式)
{
	语句
}

while (表达式) 单个语句

但后者却不是好的代码风格,我们应该切记C语言程序需要具备可读性可扩展性
这是 while 循环的执行流程:
while循环
(continue——跳出本次循环,break——终止循环)
是不是非常简单,我们的 while 语句先对表达式进行判断,表达式为真,即结果为非零数或 true (布尔类型),则执行语句,一直为真则一直执行,否则停止
给出代码示例并分析如下:

#include<stdio.h>
int main() //打印1-10
{
	int i = 1, input = 0;
	scanf("%d", &input); //输入input的值
	while (i < 11) //当i < 11,即i为1-10的数时表达式结果为真,返回值不为 0,循环执行
	{
		if (i == input) //当i等于input时停止打印
		{
			break;
		}
		printf("%d ", i); //打印 i
		i = i + 1;
	}

	return 0;
}

(输入11i永远不可能等于input,正常打印1-10)

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

结果


(输入6使程序只打印1-5的数)

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

让我们来分析一下这个代码。
上例中我们设置 while 循环的表达式为i < 11,又在循环内的末尾让 i 随每一次循环的结束而加 1易知 i 能使循环成立的最大值为 10,所以当我们想正常打印 1~10 的数时,只需要输入一个大于 10 的数就可以了,如上例第一次输入的 11;当我们想打印 1~5 的数时,我们需要注意,我们的 if 判断语句是写在打印之前的,也就代表i 等于 input 时,这次循环中的 i 是不会打印的,所以我们的输入值需要目标数加 1 才能打印,这里目标数是 5 ,那么打印从 15 的数,需要输入值为 6
在这里给大家出个题,如果我们把 break 换成 continue,再输入相同的输入值 116 又是什么答案呢?可以在评论区留言写出你的答案。作为程序员,我们一定要学会自己动手操作去找出答案,这样才能随着一次又一次的解决问题,提高我们的各方面能力,如信息检索能力、编程能力。

2.2 for循环

for 循环是上面三种循环语句中最常用,最普适的一种循环语句,我们来看看它的语法示例

for (表达式1; 表达式2; 表达式3;)
{
	语句
} //相同的,单个语句也是可以直接跟在for语句后面的,但是,打咩,这不利于程序的可读性和扩展性

其中:

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

我们来看看执行流程
执行流程

我在这祭出一套代码来给大家来分析一下 for 循环的执行流程,如下:
要求打印一个腰长为10的等腰直角三角形,如下图所示。
等腰直角三角形

#include<stdio.h>
int main() //和if嵌套类似,套娃式写法,我们阅读时只需要层层剖析,很容易理解
{ 
	for (int i = 0; i < 10; i++) //外循环,此处含义:i代表第i+1行,一次循环为一行,逐行打印
	{
		/*内循环,此处含义:j的取值范围代表星号*个数,j随内循循环次数增加而增加,但j的范围即
		星号个数随外循环次数增加而减少*/
		for (int j = 0; j < 10 - i; j++)
		{
			printf("* ");
		}
		printf("\n"); //每次循环结束,即行尾打印一个换行符
	}
	return 0;
}

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

2.3 do_while循环

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

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

whilefor 这两种循环都是先判断,条件如果满⾜就进⼊循环,执⾏循环语句,一旦不满⾜就跳出循环
do while 循环则是先进⼊循环体,执⾏循环语句,再执⾏判断表达式,表
达式为真,就会进⾏下⼀次循环,表达式为假,则不再继续循环。
执行流程如下:
执行流程
do_while 语句中,我们通常在循环体外进行循环变量的初始化,当程序执行到 do_while 语句时,先进入循环体执行语句并进行循环变量的调整,一次循环结束后再来执行表达式,判断是否进入下一次循环,所以 do_while 循环是至少执行一次的,这是它的特殊所在
代码示例如下:

#include <stdio.h>
int main() //打印1-10的数
{
 	int i = 1; //循环变量的初始化
 	do //开始循环
 	{
 		printf("%d ", i); //循环体/语句
 		i = i + 1; //循环变量的调整
	}while(i < 11); //判断条件:当i >= 11,终止循环,不再打印
 return 0;
}

结果:
结果

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

到这里我们已经学完了顺序结构,分支结构和循环结构了,除开一点点点点点点点点琐碎的知识外,我们已经可以开始尝试完成一个猜字谜游戏了。
在这里,我们先给出完整代码(有需要自取,无需要可跳过看详解):

#include<stdio.h>
#include<windows.h>
#include<stdlib.h> //提供rand函数,功能为基于某个数(种子)生成随机数;srand函数改变种子
#include<time.h> //提供time函数,用于获取一个时间戳,以时间作为种子
void menu() //菜单函数,提供菜单功能
{
	printf("**************\n");
	printf("****1.Play****\n");
	printf("****0.Exit****\n");
	printf("**************\n");
}
void game() //game函数,提供游戏功能
{
	//times规定并记录游戏次数,guess存储用户的输入值,r为随机数且此处被赋值范围为1~100
	int times = 5, guess = 0, r = rand() % 100 + 1;
	while (times)
	{
		scanf("%d", &guess);
		if (guess > r)
		{
			printf("太可惜了,你猜大了!\n");
		}
		else if (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);
	}
}
int main()
{
	printf("哼哼( ̄、 ̄),大笨蛋赶快看清楚本大爷的名字,本大爷叫作“猜数字游戏”,你应该知道怎么玩。\n");
	int input = 0; //存储输入值,用于开始游戏或结束游戏
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		system("cls"); //系统命令:清屏
		if (input == 1)
		{
			printf("\n开始游戏噜!!!赶快输入你猜的数字吧:\n");
		}
		switch (input) //代码核心部分
		{
		case 1: game(); break;
		case 0: printf("\n游戏结束了,下次再来吧\\(n.n)/Bye~\n"); break;
		default: printf("输入错误,请重新输入\n"); break;
		}
	} while (input);
	return 0;
}

下面我们按程序思维来逐步分析:
首先从main函数起始:

int main() //程序入口
{
	printf("哼哼( ̄、 ̄),大笨蛋赶快看清楚本大爷的名字,本大爷叫作“猜数字游戏”,你应该知道怎么玩。\n"); //小小的游戏说明,也可写入菜单函数,亦可与菜单函数结合并制作跳转游戏说明页面功能
	int input = 0; //存储用户输入值,即0或1,开始或结束游戏
	srand((unsigned int)time(NULL)); //使用time函数获取时间戳,强制转换返回值为无符号整型,再用srand函数生成种子
	do //用do_while循环先开始,若用户输入1则继续循环,开始游戏,输入0则终止循环,程序结束
	{
		menu(); //走来先给个菜单
		printf("请选择:>");
		scanf("%d", &input);
		system("cls"); //系统命令:清屏
		if (input == 1) //增加一点氛围感
		{
			printf("\n开始游戏噜!!!赶快输入你猜的数字吧:\n");
		}
		switch (input) //游戏主体模块,一个小小的分支结构
		{
		case 1: game(); break; //input为1则跳转到game函数,game函数结束并返回,直接break出去
		case 0: printf("\n游戏结束了,下次再来吧\\(n.n)/Bye~\n"); break;//input为0,直接break然后say good bye
		default: printf("输入错误,请重新输入\n"); break; //输入错误,但input不为0,直接break出switch语句再循环一遍
		}
	} while (input);
	return 0;
}

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

void menu() //菜单函数,提供菜单功能
{
	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 需要一个错误提醒,并且此处不能有分支重叠,所以都要加个 break 来直接结束 switch 语句。
上述,我们在考虑第二、第三环节时说要增加一个循环体,那么对于循环体内设计完毕后,我们需要考虑构建一个什么循环更加方便。很明显,我们可以发现我们设置的输入值正好是 01(这当然是设计人故意设计包含了一个 0),而其他输入值包括 1 在内都是非零值,我们正好可以用 0 当作跳出循环的条件来设计循环体,很快地,我们的 do_while 循环就派上了用场。
以上是 main 函数的设计流程,我们只需要继续细化,完成我们的重中之重——game 函数,属于我们的一款游戏就新鲜出炉了。
代码如下

void game() //game函数,提供游戏功能
{
	//times规定并记录游戏次数,guess存储用户的输入值,r为随机数且此处被赋值范围为1~100
	int times = 5, guess = 0, r = rand() % 100 + 1;
	while (times)
	{   //当times减小到 0停止循环,一轮游戏结束
		scanf("%d", &guess);
		if (guess > r) //if else语句用于判断是否猜中数字
		{
			printf("太可惜了,你猜大了!\n");
		}
		else if (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 和猜测值 guess 的初始化然后编写循环体囊括上述两个流程,接着对流程细化我们需要先 scanf 输入,然后对输入值判断,如果大了就提示玩家大了,小了就提示玩家小了,注意,如果等于,我们就不需要继续猜了,我们直接break终止循环。如果玩家一直没猜中,我们还需要考虑次数耗尽的情况,我们直接告诉玩家正确答案然后结束——game 函数完毕,返回 main 函数继续向下执行语句。


点个赞


以上就是三大结构的混合案例解析了,如果喜欢我的博客,请直接关注吧~~

飞飞飞!


我会将我对C语言的理解和认知,精心写下来,这不仅是对我知识的梳理与回顾,更是一种分享,供后来者借鉴(无论妙笔或谬误)与学习,亦给自己一个被先行者校正、勘误和交流的机会。
Bye~

  • 27
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

David猪大卫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值