初阶C语言-分支和循环语句(下)

news2024/11/18 15:32:06

“花会沿途盛开,以后的路也是。” 今天我们一起来继续学完分支语句和循环语句。

分支和循环

  • 3.循环语句
    • 3.4 do...while()循环
      • 3.4.1 do语句的用法
    • 3.5关于循环的一些练习
    • 3.6 goto语句

3.循环语句

3.4 do…while()循环

3.4.1 do语句的用法

do
    循环语句;//当循环语句不止一句的时候,要用大括号括起来
while(表达式);

在前面,我们学过了用while循环for循环在屏幕上打印1~10的数字,那么在do...while()循环中,如何实现这步操作呢?

#include <stdio.h>
int main()
{
	int i = 1;
	do
	{
		printf("%d ", i);
		i++;
	} while (i <= 10);
	return 0;
}

在这里插入图片描述
接下来,让我们用一张图了解一下do...while()循环的执行流程:
在这里插入图片描述

do语句的特点:循环至少执行一次,使用的场景有限,所以不是经常使用。

同样的,在do…while()循环中,也存在break和continue语句。接下来,让我们用示例看看用法是否一致?

#include <stdio.h>
int main()
{
	int i = 1;
	do
	{
		if (i == 5)
			break;//遇到break循环终止,因此屏幕上只打印出1~4
		printf("%d ", i);
		i++;
	} while (i <= 10);
	return 0;
}

在这里插入图片描述

#include <stdio.h>
int main()
{
	int i = 1;
	do
	{
		if (i == 5)
			continue;//遇到continue,跳过本次循环后面的代码
		printf("%d ", i);
		i++;
	} while (i <= 10);
	return 0;
}

通过运行,我们可以发现程序进入了死循环,光标在4的后面一直闪烁。
在这里插入图片描述

总结:do...while循环中的breakcontinue和在while循环中一模一样。break都是用来终止循环的,continue是跳过本次循环后面的代码,直接去判断部分。

3.5关于循环的一些练习

下面让我们一起下一些关于循环的练习:
1.计算n的阶乘

//计算n的阶乘
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	int n = 0;
	int i = 0;
	int ret = 1;
	scanf("%d", &n);
	for (i = 1; i <= n; i++)//循环产生1~n的数字
	{
		ret = ret * i;
	}
	printf("n! = %d", ret);
}

在这里插入图片描述

2.计算1!+2!+3!+4!+5!+6!+7!+8!+9!+10!

//计算1!+2!+3!+4!+5!+6!+7!+8!+9!+10!
#include <stdio.h>
int main()
{
	int n = 0;
	int i = 0;
	int ret = 1;
	int sum = 0;
	for (n = 1; n <= 10; n++)
	{
		ret = 1;//要让ret每次都从1开始
		for (i = 1; i <= n; i++)//循环产生1~n的数字
		{
			ret = ret * i;
		}
		sum = ret + sum;
	}
	printf("%d\n", sum);
	return 0;
}

在这里插入图片描述

我们可以发现,这段代码相对来说还是比较复杂的,每次都得先把n!算出来,然后在相加,每次都要从1开始乘到n,但实际上我们可以发现后一个数的阶乘等于前一个数的阶乘乘以这个数本身就行了,这样一来,简化了计算过程。那么,我们一起把代码优化一下吧!

#include <stdio.h>
int main()
{
	int i = 0;
	int ret = 1;
	int sum = 0;
	for (i = 1; i <= 10; i++)
	{
		ret = ret * i;
		sum = ret + sum;
	}
	printf("%d\n", sum);
	return 0;
}

在这里插入图片描述
我们可以发现,这两段代码的结果相同,后者更优!因此,我们在写代码的时候,不光要看怎么能写出代码,还需要思考怎么样写才是最简便的。

3.在一个有序数组中查找具体的某个数字n,如果有,打印出它的下标,没有的话,给出提示。
当我们看到这个题目的第一眼,可能大多数人的想法就是从左向右一个一个寻找,找到的话就打印出下标,找不到就给出提示,这种方法我们也叫做遍历查找。假设我们要从1~10的十个数中找出6,那么该如何写这段代码呢?

//假设我们要从1~10的十个数中找出6,那么该如何写这段代码呢?有的话给出下标,没有的话给出提示
#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int n = 0;
	int flag = 0;
	scanf("%d", &n);
	for (int i = 0; i <= 9; i++)
	{
		if (arr[i] == n)
		{
			printf("找到了,下标是: % d", i);
			flag = 1;
			break;
		}
	}
	if (flag == 0)
	{
		printf("没找到!\n");
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述
虽然这种方法实现了我们想要的结果,但是我们发现这种算法比较复杂,如果我们现在要寻找的是10.那么这个循环将要走10次,那么如果是一个更大的数呢?比方说:妈妈带着小明去买了一双鞋,小明说这双鞋在600元以内,那么这个时候让我们来猜这双鞋是多少钱,难道我们需要从1开始一直查找到600吗?显然,计算量是相当大的,对于这种有序数组中某个元素的查找,我们这个给大家介绍一个新的方法,叫做折半查找,又称二分法。 下面,我们给出用二分查找解决上述问题的示例先帮助大家了解一下二分查找的过程。
在这里插入图片描述

我们可以发现二分查找的效率很高,但是条件苛刻,只针对有序的数组中。

下面,我们给出详细代码:

//二分查找
#include <stdio.h>
int main()
{
	int left = 0;
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int right = sizeof(arr)/sizeof(arr[0])-1; //sizeof(arr)算的是数组的总大小,单位是字节
	int mid = 0;
	int flag = 0;
	int n = 0;
	scanf("%d", &n);
	while (left <= right)
	{
		mid = (right + left)/2;
		if (arr[mid] == n)
		{
			printf("下标为:%d", mid);
			flag = 1;
			break;
		}
		else if (arr[mid] > n)
		{
			right = mid - 1;
		}
		else if (arr[mid] < n)
		{
			left = mid + 1;
		}
	}
	if (flag == 0)
	{
		printf("没找到!\n");
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述
4.编写代码,演示多个字符从两端移动,向中间汇聚。
假设我们这里需要实现Hello C World !!!的字符从两端移动,往中间汇聚,该如何实现呢?

#define _CRT_SECURE_NO_WARNINGS 1
//编写代码,演示多个字符从两端移动,向中间汇聚。Hello C World !!!!!!
#include <stdio.h>
#include <string.h>//使用strlen需要添加的头文件
#include <windows.h>//使用system("cls");需要添加的头文件
int main()
{
	char arr1[] = "Hello C World !!!!!!";
	char arr2[] = "********************";
	int left = 0;
	int right = strlen(arr2) - 1;//此时是数组元素是字符串,而不是一个个字符,通过前面的学习我们知道了字符串结束标志为'\0',但strlen计算的是除了'\0'以外的字符长度,因此-1即得到最右边数组的下标
	//int right = sizeof(arr2) / sizeof(arr2[0]) - 2;当然使用sizeof也是可以的,不过此时我们要进行减2的操作
	while (left <= right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", arr2);
		Sleep(1000);//等待1秒
		system("cls");//清空屏幕
		left++;
		right--;
	}
	printf("%s\n", arr2);
	return 0;
}

5.编写代码实现,模拟用户登录情景,并且只能登录三次(如果正确,显示登录成功,如果错误,退出程序。)

//编写代码实现,模拟用户登录情景,并且只能登录三次(如果正确,显示登录成功,如果错误,退出程序。)
#include <stdio.h>
#include <string.h>//strcmp需要包含该头文件
int main()
{
	char arr[20] = { 0 };
	char password[] = "123456";
	int i;
	for (i = 0; i < 3; i++)
	{
		printf("请输入密码:>");
		scanf("%s", arr);
		//strcmp函数是比较字符串的大小,如果>,则返回>0的值,如果<,则返回<0的值,如果相等,则返回0
		if (strcmp(arr, password) == 0)
		{
			printf("登录成功!\n");
			break;
		}
		else
			printf("密码错误!\n");
	}
	if (i == 3)
	{
		printf("三次密码均输入错误,退出程序!\n");
	}
	return 0;
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
6.猜数字游戏-电脑随机产生1~100之间的一个数,接下来,我们猜数字,如果小了,我们给出提示猜小了,如果猜大了我们给出提示猜大了,如果猜对了,那么恭喜你猜对了,游戏结束。
这里,我们需要先给大家介绍一下产生随机数的函数rand()
在这里插入图片描述
上述资料中,我们知道想要使用rand()函数,我们需要添加头文件#include <stdlib.h>我们可以先通过简单的代码看看rand()的功能

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int ret = rand();
	printf("%d", ret);
	return 0;
}

在这里插入图片描述
经过调试运行,我们发现rand()确实能够产生一个随机数,但是多次调试我们又发现,每次产生的随机数都是41,那这就不能达到我们期望的结果。

查阅资料,我们可以发现rand()函数是通过某种算法生成的随机数,因此它还不够随机,不能达到我们预期的结果。rand()函数生成的是伪随机数,且其生成的随机数的范围是:0~RAND_MAX. 通过查找我们可以发现RAND_MAX的值为32767。rand()函数在生成随机数之前,需要通过srand()函数设置随机数的生成器。

在这里插入图片描述
大家肯定又在想srand()函数又是干什么的呢?这里,我们带大家一起了解一下:
在这里插入图片描述
下面我们通过代码给大家进行演示:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	srand(1);
	//srand(2);
	int ret = rand();
	printf("%d", ret);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

我们可以发现rand()是一个产生随机数的函数,而srand是一个设置随机数种子的函数,通常这两个函数是一起使用的,来完成产生随机数的功能。srand函数通过参数seed来改变系统提供的种子值,从而可以使得每次调用rand函数生成的伪随机数序列不同,从而实现真正意义上的“随机”。

这里,我们介绍一下时间戳,通过百度,我们可以对时间戳有所了解:
在这里插入图片描述
我们可以发现,只要时间在变化,那么其所对应的时间戳就在变化,那么我们如何在C语言中获得时间戳呢,这里我们需要给大家介绍一下time()函数
在这里插入图片描述
我们可以发现time()函数还存在一个参数,会返回时间戳,但是它的参数是一个指针,我们可以通过参数带回时间戳,这里我们不想用的话,可以用NULL(0)这个空指针来代替。我们发现time()函数的类型是time_t,但是srand()所需类型是unsigned int,这里我们就可以进行强制类型转换。

srand((unsigned)time(NULL));

这条指令的意思是利用系统时间来初始化系统随机数的种子值,使得每次运行由于时间不同产生而产生不同的随机数序列。如果想在一个程序中生成随机数序列,只需要在主程序开始处调用srand((unsigned)time(NULL));后面直接用rand()函数就可以了。

接下里,我们就一起来写一下猜数字的游戏吧!

//猜数字游戏
#include <stdio.h>
#include <stdlib.h>//srand()函数和rand()函数所需要的头文件
#include <time.h>//time()函数所需要的头文件
void menu()
{
	printf("********************************\n");
	printf("**********   1.play   **********\n");
	printf("**********   0.exit   **********\n");
	printf("********************************\n");
}
//1.生成1~100的随机数
//2.猜数字
void game()
{
	int guess = 0;
	int ret = rand() % 100 + 1;//生成1~100的随机数,任何一个数%100等于0~99,加上1,就是1~100.
	while (1)
	{
		printf("请猜数字:");
		scanf("%d", &guess);
		if (guess > ret)
		{
			printf("猜大了!\n");
		}
		else if (guess < ret)
		{
			printf("猜小了!\n");
		}
		else
		{
			printf("恭喜你猜对了!\n");
			break;
		}
	};
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//利用系统时间来初始化系统随机数的种子值,使得每次运行由于时间不同产生而产生不同的随机数序列。
	do 
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 0:
			printf("game over!\n");
			break;
		case 1:
			printf("game start!\n");
			game();
			break;
		default:
			printf("选择错误,请重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}

3.6 goto语句

C语言中,提供了可以随意滥用的goto语句和标记跳转的标号。从理论上goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。但在某种场合下,goto语句还是用得着的,最常见的用法就是终止程序在某种深度嵌套的结构的处理过程。例如:一次跳出两层或多层循环。多层循环这种情况使用break是达不到目的的,它只能从最内层循环退出到上一层循环。

goto语言真正适合的场景如下:

for(...)
    for(...{
        for(...)
        {
             if(disaster)
                  goto error;
        }
    }
    ...
error:
   if(disaster)
   //处理错误情况

下面呢,我们给出goto语句的示例:

//goto语句
#include <stdio.h>
int main()
{
	printf("hehe!\n");
	printf("haha!\n");
	goto end;
	printf("heihei!\n");
end:
	printf("hihi!\n");
	return 0;
}

在这里插入图片描述

注:goto函数只能在同一个函数内部跳转,不能跨函数

下面,我们也给出一个用goto语句写出关机程序的例子:(该程序仅供学习使用,不要过度整蛊同学!)

//关机程序
#include <stdio.h>
int main()
{
	char input[10] = { 0 };
	system("shutdown -s -t 60");
again:
	printf("你的电脑将在1分钟内关机,如果输入:我是猪,则可以取消关机程序!\n");
	scanf("%s", input);
	if (strcmp(input, "我是猪") == 0)
	{
		system("shutdown -a");
		printf("关机程序已经取消!\n");
	}
	else
		goto again;
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

好啦,关于分支和循环到这里就完结啦,欢迎大家关注、点赞和评论!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/791520.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【unity】ShaderGraph学习笔记

【unity】ShaderGraph学习笔记 创建ShaderGraph 创建URP的shaderGraph文件 在Project面板里Create→ShaderGraph→URP→这里主要有几个选项 Lit Shader Graph&#xff1a;有光照三维着色器 Unlit Shader Graph&#xff1a;无光照三维着色器 Sprite Custom Lit Shader Gra…

【解决方案】医疗行业资产定位管理方案-蓝牙资产定位方案

蓝牙资产定位追踪技术已经开始应用于多种行业的资产、设备管理方面&#xff0c;有不少机构、企业开始尝试使用实时蓝牙定位系统对其各类资产、机器设备、工具、材料、产品等进行精准定位&#xff0c;提高各类资产、设备的管理和使用效率&#xff0c;从而节省运营成本。 医疗行业…

汽配企业建设数字化工厂的步骤是什么

随着信息技术的迅猛发展&#xff0c;汽车行业也面临着数字化转型的迫切需求。汽配企业作为汽车产业链上重要的一环&#xff0c;也需要积极采取措施&#xff0c;建设数字化工厂系统&#xff0c;以适应市场竞争的变化。下面将介绍建设汽配企业数字化工厂的具体步骤。 第一步&…

在niso ii中读写EPCS时出现“Can‘t open flash device”

在niso ii中读写EPCS时出现“Can’t open flash device”&#xff0c;即alt_flash_open_dev(EPCS_FLASH_NAME)函数返回0。 Cant open flash device函数alt_flash_open_dev(EPCS_FLASH_NAME)打开epcs不成功&#xff0c;返回为0&#xff0c;试了几次硬件重新烧入、重启开发板还是…

呕心沥血解决xampp启动mysql异常停止due to a blocked port, missing dependencies问题

Error: MySQL shutdown unexpectedly.<br> This may be due to a blocked port, missing dependencies 这一行就是我问题的开始。 原因是因为&#xff0c;之前一直使用xampp用作本地mysql的启动管理&#xff0c;是个很好用的工具&#xff0c;但是近日想要给一个项目配…

STM32速成笔记—串口IAP

本文涉及到串口通信和Flash知识&#xff0c;对于这部分知识不熟悉的小伙伴可以到博主STM32速成笔记专栏查看。 文章目录 一、串口IAP简介1.1 什么是IAP1.2 STM32下载程序 二、串口IAP有什么作用三、启动流程3.1 正常启动流程3.2 加入IAP后的启动流程 四、必备知识4.1 修改程序运…

日常开发中Git遇到的问题-记录贴

日常开发中Git遇到的问题 前言场景一&#xff1a;clone代码并进行开发完毕后&#xff0c;进行代码合并时要求在新分支下提交代码场景二&#xff1a;远程分支被删除后&#xff0c;本地分支缓存需要更新&#xff0c;防止提交错误 前言 本篇博客只是用来记录平时开发过程之中用gi…

从头开始:数据结构和算法入门(时间复杂度、空间复杂度)

目录 文章目录 前言 1.算法效率 1.1 如何衡量一个算法的好坏 1.2 算法的复杂度 2.时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 2.3常见时间复杂度计算 3.空间复杂度 4.常见复杂度对比 总结 前言 C语言的学习篇已经结束&#xff0c;今天开启新的篇章——数据结构和算…

Hive视图

hive的视图 简介 hive的视图简单理解为逻辑上的表hive只支持逻辑视图&#xff0c;不支持物化视图视图存在的意义 对数据进行局部暴露&#xff08;涉及隐私的数据不暴露&#xff09;简化复杂查询 创建视图&#xff1a; create view if not exists v_1 as select uid,movie f…

国内十大精准的现货黄金价格走势图软件最新排名(综合版)

选择国内现货黄金价格走势图软件时&#xff0c;需要考虑几个因素。首先&#xff0c;软件的稳定性和可靠性至关重要。应选择有良好声誉和长期稳定运行的平台&#xff0c;以确保价格数据的准确性和及时性。其次&#xff0c;要选择功能齐全的软件。较为优秀的软件应该提供多种技术…

C++学习——类和对象(三)

接着我们就继续学习我们C当中的相关的知识。 一&#xff1a;初始化列表 还记得我们之前讲过的构造函数吗&#xff1f;我们在构造函数的函数体里面可以对对象当中的属性进行初始化。但是作为我们的构造函数来说&#xff0c;初始化的方式并不只是在构造函数体当中进行赋值。我们…

Junit4+MultiThreadedTestRunner 并发测试

目录 前言&#xff1a; 具体步骤&#xff1a; 前言&#xff1a; 在进行软件测试时&#xff0c;我们需要确保应用程序在不同的并发情况下仍能正常运行。 最近要对一个类里的方法&#xff0c;进行压力测试。下面讲一下写出的 Junit4 的并发测试代码吧。如果要复用的话&#x…

通达信一看就懂的成交量指标公式_通达信公式

用法说明&#xff1a;黄色为立桩量&#xff0c;绿色长竖条为逃顶提示&#xff0c;蓝色与红箭头为突破&#xff0c;红色为牛&#xff0c;紫色为立桩三天法则成立&#xff0c;笑脸为寻底&#xff0c;棕色与绿箭头为破位&#xff0c;淡红色黑中线涨停&#xff0c;深绿色黑中线跌停…

yolov7裂缝检测

B站视频笔记。 1.首先到Github上找RoboFlow的仓库地址 该教程提供了传统算法比如Resnet、YOLO等&#xff0c;还有包含一些较新的算法。 2.通过Colab打开例程 可以直接通过Colab打开,还支持其他的打开方式&#xff0c;这里提供三种方式。 提示&#xff1a;点击授权即可。 …

dy设备deviceid iid注册分析

清楚缓存&#xff0c;重新打开app, 点击同意按钮&#xff0c;会触发设备注册&#xff1b; 很明显是一个post包&#xff0c;device_register 可以看到请求体加密了 那么 请求体是什么呢&#xff1f; 很老版本思路&#xff1a;都是直接明文注册 较老版本思路&#xff1a;在反编译…

二、SQL-5.DQL-8).案例练习

1、查询年龄为20,21,22,23岁的员工信息 select * from emp where age in(20, 21, 22, 23) and gender 女; 2、查询性别为男&#xff0c;并且年龄在20-40岁&#xff08;含&#xff09;以内的姓名为三个字的员工 select * from emp where gender 男 && age between 2…

如何从任何地方远程解决电脑问题?

​如何远程解决电脑问题&#xff1f; “嗨&#xff01;我有一台Windows 10家用电脑。我外出旅行&#xff0c;但我的家人告诉我我的电脑有一段时间无法正常工作。我该如何远程检查电脑并解决相应的问题&#xff1f;提前谢谢&#xff01;” 您是否正在寻找远程解决电…

重庆市北斗新型智慧城市政府项目

技术栈&#xff1a;使用vue2JavaScriptElementUIvuexaxiosmapboxcesium 项目描述&#xff1a;重庆市北斗新型智慧城市政府项目是基于千寻孪界开发的一款智慧城市项目&#xff0c;包含车辆实时位置定位&#xff0c;智能设备的报警&#xff0c;基础设施的部设等等功能 工作内容&a…

javascript 7种继承-- 寄生式继承分析(5)

文章目录 概要继承的进化史技术名词解释寄生式继承案列分析源代码解析效果图小结 概要 这阵子在整理JS的7种继承方式&#xff0c;发现很多文章跟视频&#xff0c;讲解后都不能让自己理解清晰&#xff0c;索性自己记录一下&#xff0c;希望个位发表需要修改的意见&#xff0c;共…

C++多线程编程(第一章 多线程基本使用)

C 11&#xff1b; C 14; C 17; C 20&#xff1b; 1、为什么要多线程 任务分解 耗时的操作&#xff0c;任务分解&#xff0c;实时响应 数据分解 充分利用多核CPU处理数据 数据流分解 读写分离&#xff0c;解耦合设计 2、相关代码 1、初步&#xff1a; join(),detach() …