第6章 C控制语句:循环

news2024/11/25 16:30:35

本章介绍以下内容:
关键字:for、while、do while
运算符:<、>、>=、<=、!=、==、+=、*=、-=、/=、%=
函数:fabs()
C语言有3种循环:for、while、do while
使用关系运算符构建控制循环的表达式
其他运算符
循环常用的数组
编写有返回值的函数
大多数人都希望自己是体格强健、天资聪颖、多才多艺的能人。虽然有时事与愿违,但至少我们用 C能写出这样的程序。诀窍是控制程序流。对于计算机科学(是研究计算机,不是用计算机做研究)而言,一门语言应该提供以下3种形式的程序流:
执行语句序列;
如果满足某些条件就重复执行语句序列(循环
通过测试选择执行哪一个语句序列(分支)。
读者对第一种形式应该很熟悉,前面学过的程序中大部分都是由语句序列组成。while循环属于第二种形式。本章将详细讲解while循环和其他两种循环:for和do while。第三种形式用于在不同的执行方案之间进行选择,让程序更“智能”,且极大地提高了计算机的用途。不过,要等到下一章才介绍这部分的内容。本章还将介绍数组,可以把新学的知识应用在数组上。另外,本章还将继续介绍函数的相关内容。首先,我们从while循环开始学习。

6.1 再探while循环

6.1.1 程序注释

这叫作伪代码(pseudocode),是一种用简单的句子表示程序思路的方法,它与计算机语言的形式相对应。伪代码有助于设计程序的逻辑。确定程序的逻辑无误之后,再把伪代码翻译成实际的编程代码。使用伪代码的好处之一是,可以把注意力集中在程序的组织和逻辑上,不用在设计程序时还要分心如何用编程语言来表达自己的想法。例如,可以用缩进来代表一块代码,不用考虑C的语法要用花括号把这部分代码括起来。

6.1.2 C风格读取循环

但是C更为简洁,下面的代码:
status = scanf("%ld", &num);
while (status == 1)
{
/* 循环行为 */
status = scanf("%ld", &num);
}
可以用这些代码替换:
while (scanf("%ld", &num) == 1)
{
/*循环行为*/
}

6.2 while语句

while循环的通用形式如下:
while ( expression )
statement
statement部分可以是以分号结尾的简单语句,也可以是用花括号括起来的复合语句。

6.2.1 终止while循环

6.2.2 何时终止循环

6.2.3 while:入口条件循环

while循环是使用入口条件的有条件循环。所谓“有条件”指的是语句部分的执行取决于测试表达式描述的条件

6.2.4 语法要点

缩进是为了让读者阅读方便,不是计算机的要求。

即使while语句本身使用复合语句,在语句构成上,它也是一条单独的语句。该语句从while开始执行,到第1个分号结束。在使用了复合语句的情况下,到右花括号结束。
要注意放置分号的位置。

测试条件后面的单独分号是空语句(null statement),它什么也不做。在C语言中,单独的分号表示空语句。有时,程序员会故意使用带空语句的while语句,因为所有的任务都在测试条件中完成了,不需要在循环体中做什么。

6.3 用关系运算符和表达式比较大小

while循环经常依赖测试表达式作比较,这样的表达式被称为关系表达式(relational expression),出现在关系表达式中间的运算符叫做关系运算符(relational operator)

表6.1 关系运算符 

比较浮点数时,尽量只使用<和>。因为浮点数的舍入误差会导致在逻辑上应该相等的两数却不相等。

使用fabs()函数(声明在math.h头文件中)可以方便地比较浮点数,该函数返回一个浮点值的绝对值(即,没有代数符号的值)

6.3.1 什么是真

对C而言,表达式为真的值是1,表达式为假的值是0

6.3.2 其他真值

一般而言,所有的非零值都视为真,只有0被视为假。在C中,真的概念还真宽!

用while (goats)替换while (goats !=0)

待比较的一个值是常量,可以把该常量放在左侧有助于编译器捕获错误:

6.3.4 新的_Bool常量

在编程中,表示真或假的变量被称为布尔变量(Boolean variable),所以_Bool是C语言中布尔变量的类型名。_Bool类型的变量只能储存1(真)或0(假)。如果把其他非零数值赋给_Bool类型的变量,该变量会被设置为1。这反映了C把所有的非零值都视为真。

C99提供了stdbool.h头文件,该头文件让bool成为_Bool的别名,而且还把true和false分别定义为1和0的符号常量。包含该头文件后,写出的代码可以与C++兼容,因为C++把bool、true和false定义为关键字。

6.3.5 优先级和关系运算符

关系运算符的优先级比算术运算符(包括+和-)低,比赋值运算符高

关系运算符之间有两种不同的优先级。
高优先级组: <<= >>=
低优先级组: == !=
与其他大多数运算符一样,关系运算符的结合律也是从左往右。

 表6.2 运算符优先级

小结:while语句
关键字:while
一般注解:
while语句创建了一个循环,重复执行直到测试表达式为假或0。while语句是一种入口条件循环,也就是说,在执行多次循环之前已决定是否执行循环。因此,循环有可能不被执行。循环体可以是简单语句,也可以是复合语句。
形式:
while ( expression )
statement
在expression部分为假或0之前,重复执行statement部分。
示例:
while (n++ < 100)
printf(" %d %d\n",n, 2 * n + 1); // 简单语句
while (fargo < 1000)
{ // 复合语句
fargo = fargo + step;
step = 2 * step;
}
小结:关系运算符和表达式
关系运算符:
每个关系运算符都把它左侧的值和右侧的值进行比较。
<     小于
<=     小于或等于
==     等于
>=     大于或等于
>     大于
!=     不等于
关系表达式:
简单的关系表达式由关系运算符及其运算对象组成。如果关系为真,关系表达式的值为 1;如果关系为假,关系表达式的值为0。
示例:
5 > 2为真,关系表达式的值为1
(2 + a) == a 为假,关系表达式的值为0

6.4 不确定循环和计数循环

所谓不确定循环,指在测试表达式为假之前,预先不知道要执行多少次循环。

计数循环(counting loop)。这类循环在执行循环之前就知道要重复执行多少次

在创建一个重复执行固定次数的循环中涉及了3个行为:
1.必须初始化计数器;
2.计数器与有限的值作比较;
3.每次循环时递增计数器。

6.5 for循环

关键字for后面的圆括号中有3个表达式,分别用两个分号隔开。第1个表达式是初始化,只会在for循环开始时执行一次。第 2 个表达式是测试条件,在执行循环之前对表达式求值。如果表达式为假(本例中,count大于NUMBER时),循环结束。第3个表达式执行

更新,在每次循环结束时求值。程序清单6.10用这个表达式递增count 的值,更新计数。完整的for语句还包括后面的简单语句或复合语句。for圆括号中的表达式也叫做控制表达式,它们都是完整表达式,所以每个表达式的副作用(如,递增变量)都发生在对下一个表达式求值之前

1.可以使用递减运算符来递减计数器

2.可以让计数器递增2、10等

3.可以用字符代替数字计数

4.还可以测试其他条件

5.可以让递增的量几何增长,而不是算术增长。

6.可以省略一个或多个表达式(但是不能省略分号),只要在循环中包含能结束循环的语句即可

7.第1个表达式不一定是给变量赋初值,也可以使用printf()。

小结:for语句
关键字:for
一般注解:
for语句使用3个表达式控制循环过程,分别用分号隔开。initialize表达式在执行for语句之前只执行一次;然后对test表达式求值,如果表达式为真(或非零),执行循环一次;接着对update表达式求值,并再次检查test表达式。for语句是一种入口条件循环,即在执行循环之前就决定了是否执行循环。因此,for循环可能一次都不执行。statement部分可以是一条简单语句或复合语句。
形式:
for ( initialize; test; update )
statement
在test为假或0之前,重复执行statement部分。
示例:
for (n = 0; n < 10 ; n++)
printf(" %d %d\n", n, 2 * n + 1);

6.6 其他赋值运算符:+=、-=、*=、/=、%=

并非一定要使用这些组合形式的赋值运算符。但是,它们让代码更紧凑,而且与一般形式相比,组合形式的赋值运算符生成的机器代码更高效。

6.7 逗号运算符

逗号运算符有两个其他性质。首先,它保证了被它分隔的表达式从左往右求值(换言之,逗号是一个序列点,所以逗号左侧项的所有副作用都在程序执行逗号右侧项之前发生)

整个逗号表达式的值是右侧项的值

小结:新的运算符
赋值运算符:
下面的运算符用右侧的值,根据指定的操作更新左侧的变量:
+=  把右侧的值加到左侧的变量上
-=  从左侧的变量中减去右侧的值
*=  把左侧的变量乘以右侧的值
/=  把左侧的变量除以右侧的值
%=  左侧变量除以右侧值得到的余数
示例:
rabbits *= 1.6;与rabbits = rabbits * 1.6;相同
这些组合赋值运算符与普通赋值运算符的优先级相同,都比算术运算符的优先级低。因此,
contents *= old_rate + 1.2;
最终的效果与下面的语句相同:
contents = contents * (old_rate + 1.2);
逗号运算符:
逗号运算符把两个表达式连接成一个表达式,并保证最左边的表达式最先求值。逗号运算符通常在for循环头的表达式中用于包含更多的信息。整个逗号表达式的值是逗号右侧表达式的值。
示例:
for (step = 2, fargo = 0; fargo < 1000; step *= 2)
fargo += step;

6.8 出口条件循环:do while

while循环和for循环都是入口条件循环,即在循环的每次迭代之前检查测试条件,所以有可能根本不执行循环体中的内容

出口条件循环(exit-condition loop),即在循环的每次迭代之后检查测试条件,这保证了至少执行循环体中的内容一次。这种循环被称为 do while循环

do
statement
while ( expression );
statement可以是一条简单语句或复合语句。注意,do while循环以分号结尾

小结:do while语句
关键字:do while
一般注解:
do while 语句创建一个循环,在 expression 为假或 0 之前重复执行循环体中的内容。do while语句是一种出口条件循环,即在执行完循环体后才根据测试条件决定是否再次执行循环。因此,该循环至少必须执行一次。statement部分可是一条简单语句或复合语句。
形式:
do
statement
while ( expression );
在test为假或0之前,重复执行statement部分。
示例:
do
scanf("%d", &number);
while (number != 20);

6.9 如何选择循环

要让for循环看起来像while循环,可以省略第1个和第3个表达式。例如:
for ( ; test ; )
与下面的while效果相同:
while ( test )

要让while循环看起来像for循环,可以在while循环的前面初始化变量,并在while循环体中包含更新语句。例如:
初始化;
while ( 测试 )
{
其他语句
更新语句
}
与下面的for循环效果相同:
for ( 初始化 ;测试 ; 更新 )
其他语句

当循环涉及初始化和更新变量时,用for循环比较合适,而在其他情况下用while循环更好

对于涉及索引计数的循环,用for循环更适合

6.10 嵌套循环

嵌套循环(nested loop)指在一个循环内包含另一个循环。嵌套循环常用于按行和列显示数据,也就是说,一个循环处理一行中的所有列,另一个循环处理所有的行

6.10.1 程序分析

6.10.2 嵌套变式

6.11 数组简介

数组(array)是按顺序储存的一系列类型相同的值

用于识别数组元素的数字被称为下标(subscript)、索引(indice)或偏移量(offset)。下标必须是整数,而且要从0开始计数

可以通过外层循环控制内层循环,在每次外层循环迭代时内层循环完成不同的任务

遵循模块化(modularity)的原则。模块化隐含的思想是:应该把程序划分为一些独立的单元,每个单元执行一个任务。这样做提高了程序的可读性。也许更重要的是,模块化使程序的不同部分彼此独立,方便后续更新或修改程序。在掌握如何使用函数后,可以把每个执行任务的单元放进函数中,提高程序的模块化。

6.12 使用函数返回值的循环示例

6.12.1 程序分析

6.12.2 使用带返回值的函数

6.13 关键概念

6.14 本章小结

本章的主题是程序控制。C语言为实现结构化的程序提供了许多工具。while语句和for语句提供了入口条件循环。for语句特别适用于需要初始化和更新的循环。使用逗号运算符可以在for循环中初始化和更新多个变量。有些场合也需要使用出口条件循环,C为此提供了do while语句。
典型的while循环设计的伪代码如下:
获得初值
while (值满足测试条件)
{
处理该值
获取下一个值
}
for循环也可以完成相同的任务:
for (获得初值; 值满足测试条件; 获得下一个值)
处理该值
这些循环都使用测试条件来判断是否继续执行下一次迭代。一般而言,如果对测试表达式求值为非0,则继续执行循环;否则,结束循环。通常,测试条件都是关系表达式(由关系运算符和表达式构成)。表达式的关系为真,则表达式的值为1;如果关系为假,则表达式的值为0。C99新增了_Bool类型,该类型的变量只能储存1或0,分别表示真或假。
除了关系运算符,本章还介绍了其他的组合赋值运算符,如+=或*=。这些运算符通过对其左侧运算对象执行算术运算来修改它的值。
接下来还简单地介绍了数组。声明数组时,方括号中的值指明了该数组的元素个数。数组的第 1 个元素编号为0,第2个元素编号为1,以此类推。例如,以下声明:
double hippos[20];
创建了一个有20个元素的数组hippos,其元素从hippos[0]~hippos[19]。利用循环可以很方便地操控数组的下标。
最后,本章演示了如何编写和使用带返回值的函数。
 

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

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

相关文章

Linux tun虚拟网卡通信初识

什么是linux tun设备 Linux TUN 设备是一种虚拟网络设备&#xff0c;用于在用户空间和内核空间之间建立数据通道&#xff0c;使用户空间程序可以通过这个设备与内核网络栈进行交互。TUN 设备是一种通用的网络隧道设备&#xff0c;常用于实现虚拟专用网络&#xff08;VPN&#…

适配器模式-java实现

意图 复用已经存在的接口&#xff0c;与所需接口不一致的类。即将一个类&#xff08;通常是旧系统中的功能类&#xff09;&#xff0c;通过适配器转化成另一个接口的实现。&#xff08;简单来说&#xff0c;就是复用旧系统的功能&#xff0c;去实现新的接口&#xff09; 我们举…

Python Web开发 Jinja2模板引擎

在之前的文章中&#xff0c;简单介绍了Python Web开发框架Flask&#xff0c;知道了如何写个Hello World&#xff0c;但是距离用Flask开发真正的项目&#xff0c;还有段距离&#xff0c;现在我们目标更靠近一些 —— 学习下Jinja2模板。 模板的作用 模板是用来做什么的呢&…

C 语言高级3--函数指针回调函数,预处理,动态库的封装

目录 1.函数指针和回调函数 1.1 函数指针 1.1.1 函数类型 1.1.2 函数指针(指向函数的指针) 1.1.3 函数指针数组 1.1.4 函数指针做函数参数(回调函数) 2.预处理 2.1 预处理的基本概念 2.2 文件包含指令(#include) 2.2.1 文件包含处理 2.2.2 #incude<>和#include&q…

数据结构:栈的实现(C实现)

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》 文章目录 前言一、栈的实现思路1. 结构的定义2. 初始化栈(StackInit)3. 入栈(StackPush)4. 出栈(StackPop)5. 获取栈顶元素(StackTop)6. 检查栈是否为空(StackEmpty)7. 销毁栈(StackDestroy) 二、…

踩坑 视觉SLAM 十四讲第二版 ch13 编译及运行问题

一、安装Geset 库 sudo apt-get install libgtest-dev cd /usr/src/gtest sudo mkdir build cd build sudo cmake .. //一定要以sudo的方式运行&#xff0c;否则没有写入权限 sudo make //这个也一样要以sudo的方式 sudo cp libgtest*.a /usr/local/lib //将生成…

python表白代码大全可复制,python表白代码大全简单

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python表白代码大全可复制&#xff0c;python表白程序代码完整版&#xff0c;现在让我们一起来看看吧&#xff01; 今天是20230520&#xff0c;有人说&#xff1a;5代表的是人生五味&#xff0c;酸甜苦辣咸&#xff1b;…

设备管理平台:采用以可靠性为中心的维护策略的优势

在如今的工业领域&#xff0c;以可靠性为中心的维护策略正逐渐成为企业数字化转型的核心。无论是混合还是离散自动化应用&#xff0c;优化维护和工作流程实践已经成为提高利润、降低停机时间、增强运营和生产性能的不可或缺的一环。在这个过程中&#xff0c;设备管理系统与物联…

Harbor部署--使用 Harbor 安装包

一、Harbor安装准备条件 这里以 harbor 2.8.3 版本为例 1.1 硬件要求 Harbor 安装对硬件资源CPU、内存和硬盘的要求如下表&#xff1a; 资源 最小要求 推荐配置 CPU 2 CPU 4 CPU Mem 4 GB 8 GB Disk 40 GB 160 GB 使用如下命令分别查看服务器的物理CPU和逻辑CPU个数…

LCD1602相关

一.概述 LCD1602是一种工业字符型液晶&#xff0c;能够同时显示16*02即32字符&#xff08;16列2行&#xff09; 二.引脚接口说明表 第 1 脚 : VSS 为电源地 第 2 脚 : VDD 接 5V 正电源 第 3 脚 : VL 为液晶显示器对比度调整端 , 接正电源时对比度最弱&#xff…

第三章 图论 No.8最近公共祖先lca, tarjan与次小生成树

文章目录 lcaTarjan板子题&#xff1a;1172. 祖孙询问lca或tarjan&#xff1a;1171. 距离356. 次小生成树352. 闇の連鎖 lca O ( m l o g n ) O(mlogn) O(mlogn)&#xff0c;n为节点数量&#xff0c;m为询问次数&#xff0c;lca是一种在线处理询问的算法 自己也是自己的祖先 倍…

XML方式AOP快速入门XML方式AOP配置详解

目录 1.XML方式AOP快速入门 1&#xff1a;导入AOP相关坐标 2&#xff1a;准备目标类&#xff0c;准备增强类&#xff0c;并配置给Spring管理 3&#xff1a;配置切点表达式&#xff08;那些方法要被增强&#xff09; 4&#xff1a;配置织入&#xff08;切点被哪些方法增强&…

漫画算法做题笔记

诸神缄默不语-个人CSDN博文目录 哦这是我三年前写的&#xff0c;我现在Java语法都快忘光了…… 反正之前的博文也发一下好了。这个因为我当年是用有道云笔记而不是直接用CSDN编辑器写的&#xff0c;所以后面有些内容写乱了&#xff0c;因为我现在猛的一看有点看不懂&#xff0…

一文读懂|RDMA原理

什么是DMA DMA全称为Direct Memory Access&#xff0c;即直接内存访问。意思是外设对内存的读写过程可以不用CPU参与而直接进行。我们先来看一下没有DMA的时候&#xff1a; 无DMA控制器时I/O设备和内存间的数据路径 假设I/O设备为一个普通网卡&#xff0c;为了从内存拿到需要…

事务的隔离级别与Spring事务的传播机制

目录 事务的隔离性 事务的隔离级别 读未提交 读已提交 可重复读 串行化 Spring事务的传播机制 支持当前事务 不支持当前事务 嵌套事务 事务的隔离性 事务的隔离性是事务的四大特性之一&#xff0c;数据库允许多个事务并发操作数据&#xff0c;为了尽可能地避免并发操…

【JAVA】-【IO流】

文章目录 FileReader读入数据的基本操作FileReader中使用reader()FileWrite写出数据的操作使用FileInputStream、FileOutputStream操作图片缓冲流&#xff08;字节型&#xff09;实现非文本文件的复制 复制文本文件也可以使用字节流&#xff0c;但是不要在内存中读出来&#xf…

【Matlab】Elman神经网络遗传算法(Elman-GA)函数极值寻优——非线性函数求极值

往期博客&#x1f449; 【Matlab】BP神经网络遗传算法(BP-GA)函数极值寻优——非线性函数求极值 【Matlab】GRNN神经网络遗传算法(GRNN-GA)函数极值寻优——非线性函数求极值 【Matlab】RBF神经网络遗传算法(RBF-GA)函数极值寻优——非线性函数求极值 本篇博客将主要介绍Elman神…

【Spring Boot】Spring Boot项目的创建和文件配置

目录 一、为什么要学Spring Boot 1、Spring Boot的优点 二、创建Spring Boot项目 1、创建项目之前的准备工作 2、创建Spring Boot项目 3、项目目录的介绍 4、安装Spring Boot快速添加依赖的插件 5、在项目中写一个helloworld 三、Spring Boot的配置文件 1、配置文件的…

opencv基础48-绘制图像轮廓并切割示例-cv2.drawContours()

绘制图像轮廓&#xff1a;drawContours函数 在 OpenCV 中&#xff0c;可以使用函数 cv2.drawContours()绘制图像轮廓。该函数的语法格式是&#xff1a; imagecv2.drawContours( image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]…

mousedown拖拽功能(vue3+ts)

因为项目有rem适配&#xff0c;使用第三方插件无法处理适配问题&#xff0c;所有只能自己写拖拽功能了 拖拽一般都会想到按下&#xff0c;移动&#xff0c;放开&#xff0c;但是本人亲测&#xff0c;就在div绑定一个按下事件就行了&#xff08;在事件里面写另外两个事件&#x…