初阶C语言-分支和循环语句(下)
“花会沿途盛开,以后的路也是。” 今天我们一起来继续学完分支语句和循环语句。
分支和循环
- 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~4printf("%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循环中的break和continue和在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的值,如果相等,则返回0if (strcmp(arr, password) == 0){printf("登录成功!\n");break;}elseprintf("密码错误!\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");}elsegoto again;return 0;
}



好啦,关于分支和循环到这里就完结啦,欢迎大家关注、点赞和评论!
相关文章:
初阶C语言-分支和循环语句(下)
“花会沿途盛开,以后的路也是。” 今天我们一起来继续学完分支语句和循环语句。 分支和循环 3.循环语句3.4 do...while()循环3.4.1 do语句的用法 3.5关于循环的一些练习3.6 goto语句 3.循环语句 3.4 do…while()循环 3.4.1 do语句的用法 do循环语句;//当循环语句…...
pytorch工具——pytorch中的autograd
目录 关于torch.tensor关于tensor的操作关于梯度gradients 关于torch.tensor 关于tensor的操作 x1torch.ones(3,3) xtorch.ones(2,2,requires_gradTrue) print(x1,\n,x)yx2 print(y) print(x.grad_fn) print(y.grad_fn)zy*y*3 outz.mean() print(z,out)注意 atorch.randn(2,…...
Linux--进程池
1.一个父进程生成五个子进程且分别建立与子进程管道 ①用for循环,结束条件为<5 ②father父进程每次都要离开for循环,生成下一个子进程和管道 2.#include <cassert>和#include <assert.h>的区别 assert.h 是 C 标准库的头文件ÿ…...
SpringCloudAlibaba微服务实战系列(四)Sentinel熔断降级、异常fallback、block细致处理
SpringCloudAlibaba Sentinel降级和熔断 接着上篇文章的内容,在Sentinel中如何进行降级和熔断呢? 熔断降级规则 降级规则 在Sentinel中降级主要有三个策略:RT、异常比例、异常数,也是针对某个资源的设置。而在1.8.0版本后RT改为…...
WebDAV之π-Disk派盘+ WinSCP
WinSCP是一个免费的开源文件传输应用程序,它使用文件传输协议,安全外壳文件传输协议和安全复制协议来进行纯文件或安全文件传输。该应用程序旨在与Windows一起使用,并支持常见的Windows桌面功能,例如拖放文件,跳转列表…...
Python案例分析|使用Python图像处理库Pillow处理图像文件
本案例通过使用Python图像处理库Pillow,帮助大家进一步了解Python的基本概念:模块、对象、方法和函数的使用 使用Python语言解决实际问题时,往往需要使用由第三方开发的开源Python软件库。 本案例使用图像处理库Pillow中的模块、对象来处理…...
音视频——压缩原理
H264视频压缩算法现在无疑是所有视频压缩技术中使用最广泛, 最流行的。随着 x264/openh264以及ffmpeg等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大降低了人们使用H264的成本。 但为了用好H264,我们还是要对…...
微服务 云原生:搭建 K8S 集群
为节约时间和成本,仅供学习使用,直接在两台虚拟机上模拟 K8S 集群搭建 踩坑之旅 系统环境:CentOS-7-x86_64-Minimal-2009 镜像,为方便起见,直接在 root 账户下操作,现实情况最好不要这样做。 基础准备 关…...
C++中的数学问题---进制转换
二进制转十六进制 string binToHex(string bin){string hex"";if(bin.size()%4!0){for(int i0;i<(4-bin.size()%4);i){bin"0"bin;}}for(int i0;i<bin.size();i4){string tmpbin.substr(i,4);bitset<4>b(tmp);hexb.to_ulong()<10?char(b.t…...
开发一个RISC-V上的操作系统(三)—— 串口驱动程序(UART)
目录 文章传送门 一、什么是串口 二、本项目串口的FPGA实现 三、串口驱动程序的编写 四、上板测试 文章传送门 开发一个RISC-V上的操作系统(一)—— 环境搭建_riscv开发环境_Patarw_Li的博客-CSDN博客 开发一个RISC-V上的操作系统(二&…...
nuxt项目部署,npm run build 和npm run generate的区别
每日鸡汤:每个你想要学习的瞬间都是未来的你向自己求救 非服务端渲染的项目,比如普通的vite vue项目,我们在部署生产环境的时候,只需要两步 运行 npm run build 然后得到了一个 dist 文件夹将这个dist文件夹部署到一个静态服务器…...
数据仓库设计理论
数据仓库设计理论 一、数据仓库基本概念 1.1、数据仓库介绍 数据仓库是一个用于集成、存储和分析大量结构化和非结构化数据的中心化数据存储系统。它旨在支持企业的决策制定和业务分析活动。 1.2、基本特征 主题导向:数据仓库围绕特定的主题或业务领域进行建模…...
数据接口有哪些?(数据接口有哪几种)
数据接口是指不同应用程序或系统之间交换数据的通信界面。在现代信息化社会中,数据接口扮演着极为重要的角色,它们使得不同平台之间能够相互连接和交流,从而实现数据共享和应用集成。 数据接口的种类繁多,常见的有以下几种&#…...
华为云CodeArts产品体验的心得体会及想法
文章目录 前言CodeArts 的产品优势一站式软件开发生产线研发安全Built-In华为多年研发实践能力及规范外溢高质高效敏捷交付 功能特性说明体验感受问题描述完结 前言 华为云作为一家全球领先的云计算服务提供商,致力于为企业和个人用户提供高效、安全、可靠的云服务。…...
下载安装:SQLite+SQLiteStudio+VS
目录 1、SQLite 1.1、下载SQLite 1.2、配置SQLite的环境变量 2、SQLite Studio 2.1、下载SQLite Studio 2.2、安装SQLite Studio 3、Visual Studio 3.1、下载Visual Studio 3.2、安装Visual Studio 1、SQLite 1.1、下载SQLite SQLite官网:SQLite Downl…...
nginx路由
一般我们经常在访问网站时,通常会遇到输入某个页面的网址时,出现路由的转发,重定向等。可能访问的是一个网址,出来的时候就显示的是另外的地址。这是由于使用了nginx的缘故,保护了网址的安全性 (1…...
MobPush Android SDK 厂商推送限制
概述 厂商推送限制 每个厂商通道都有对应的厂商配额和 QPS 限制,当请求超过限制且已配置厂商回执时,MobPush会采取以下措施: 当开发者推送请求超过厂商配额时,MobPush将通过自有通道进行消息下发。当开发者推送请求超过厂商 QP…...
计算机网络 day7 扫描IP脚本 - 路由器 - ping某网址的过程
目录 network 和 NetworkManager关系: 实验:编写一个扫描脚本,知道本局域网里哪些ip在使用,哪些没有使用? 使用的ip对应的mac地址都要显示出来 计算机程序执行的两种不同方式: shell语言编写扫描脚本 …...
gitee 配置ssh 公钥(私钥)
步骤1:添加/生成SSH公钥,码云提供了基于SSH协议的Git服务,在使用SSH协议访问项目仓库之前,需要先配置好账户/项目的SSH公钥。 绑定账户邮箱: git config --global user.name "Your Name" git config --glob…...
JAVA面试总结-Redis篇章(七)——数据淘汰策略
JAVA 面试总结-数据淘汰策略...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
DAY 26 函数专题1
函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...
