《C语言程序设计现代方法》note-3 选择语句 循环语句

助记提要

  1. 关系运算符、判等运算符、逻辑运算符的优先级和结合性;
  2. 条件运算符;
  3. C语言中如何使用布尔值;
  4. switch语句的注意;
  5. for语句省略表达式;
  6. 逗号表达式;
  7. goto语句;
  8. 空语句;

不应该以聪明才智和逻辑分析能力来评判程序员,而要看其分析问题是否全面。

5章 选择语句

5.1 逻辑表达式

选择语句必选先测试表达式的值是真还是假。
构建逻辑表达式的运算符有9个。
逻辑表达式的值只会是1(真)或0(假)。

  • 关系运算符
    大于>、小于<、大于等于>=、小于等于<=

4个关系运算符都是左结合的,优先级低于算术运算符。

注意 i < j < k在C语言中是合法的,但是并不是检测j是否位于i和k之间。它先比较i<j的值,然后用这个结果和k比较。

  • 判等运算符
    等于==、不等于!=

判等运算符是左结合的,优先级低于关系运算符。
表达式i < j == j < k,当i < jj < k同为真或同为假时,表达式的值为真。

==经常被误写为=,有的时候编译器不会警告,导致程序出现错误。使用gcc编译C程序时可以指定-Wall选项,强制编译器检查这类书写错误。程序员可以在if条件外面多加一层圆括号来禁用该警告:if ((i = j)) ...

  • 逻辑运算符
    !、与&&、或||

是一元的右结合运算符,优先级和正负号相同。
&&||是二元的左结合运算符,优先级低于判等运算符。

运算符&&||都会进行短路计算:先计算出左操作数的值,然后计算右操作数。如果表达式的结果可以由左操作数推导出来,就不计算右操作数。

注意 由于&&||的短路特性,有些运算不一定会发生,如:i > 0 && ++j > 0,如果i不大于0,j的自增操作就不会发生。

5.2 if语句

语法
  • 基本语法格式
if (表达式) 语句;

先计算表达式的值,表达式值非零,就执行圆括号后面的语句。
C语言中,非零值都为真。

  • 复合语句
if (表达式){语句1;语句2;...
}

花括号包起来的语句称为复合语句,它会强制编译器将一组语句做为一条语句来处理。
为语句添加花括号,可以使程序更易读。也可以更方便地向语句块中添加语句。

  • else子句
if (表达式) 语句1; else 语句2;if (表达式) {语句11;语句12
} else {语句21;语句22;
}

注意 else子句会归属于离它最近且还未和其他else匹配的if语句。
下面的这种写法,按缩进来理解,else应该属于外层的if语句,但是实际上它是属于内层的if语句的。这时最好把内层if语句使用花括号包起来。

if (y != 0)if (x != 0)result = x / y;
elseprintf("Error: y == 0\n");
  • 级联if语句
    级联式if语句可以避免数量过多的内嵌if语句
if (表达式) 语句1;
else if (表达式)语句2;
else语句3;

级联式if语句不是新的语句类型,只是将另外一个if语句做为else字句。

条件运算符

条件运算符的作用类似if语句,它允许根据条件的结果,产生两个值中的一个。条件运算符构建的条件表达式语法如下:

表达式1 ? 表达式2 : 表达式3

如果表达式1成立,就计算表达式2的值做为条件表达式的结果,否则计算表达式3的值做为结果。
条件运算符是唯一的一个三元运算符。它的优先级低于所有的运算符。

条件表达式短小但是难以阅读,应该避免使用。但在少数地方使用会很方便:

// return语句使用
return i > j ? i : j// printf函数使用
printf("%d\n", i > j ? i : j);

条件表达式i > 0 ? i : j中,如果i是int型,j是float型,即使i > 0为真,表达式的结果也是i转换后的float型。

C语言中的布尔值

C89没有定义布尔类型,但是很多程序中需要变量存储真或假值。
程序员经常使用TRUE和FALSE这样的名字来定义宏:

#define TRUE 1
#define FALSE 0

使用时,可以通过这两个宏去赋值。判定条件时可以这样:

if (flag == TRUE) ...
// 如果flag为真
if (flag) ...
// 如果flag为假
if (!flag) ...

第二种方式更好,因为当flag的值不是0或1时程序也能正确运行。

或者定义一个可以用作类型的宏:

#define BOOL int
BOOL flag;

C99中提供了_Bool类型,用来声明布尔变量。_Bool变量实际上就是整型变量,但是只能赋值为0或1,存储非0值会导致变量被赋值为1。

_Bool flag;

C99还提供了一个新的头<stdbool.h>,这个头提供了宏bool,用来代表_Bool;还提供了true代表1,false代表0。
引用这个头文件,可以很方便地使用布尔值:

bool flag;
flag = false;
flag = true;

5.3 switch语句

需要把表达式和一系列的值进行比较时,可以使用级联式的if语句或switch语句。

switch (表达式){case 常量表达式1: 语句1;...case 常量表达式n: 语句n;default : 语句;
}

switch后面的表达式必须是整型表达式,不能是浮点数和字符串。
case:常量表达式称为分支标号。其中常量表达式也必须是整型表达式,不能包含变量和函数调用。
分支标号只能带一个常量表达式,但是分支标号后面可以跟任意数量的语句,并且不需要花括号括起来。每组语句的最后一句通常是break语句。
分支标号不允许重复,但是没有顺序要求,default分支不是必须写在最后。多个分支标号可以放在同一组语句的前面。
default分支可以没有。

  • break语句的作用
    switch语句实际上是一种基于计算的跳转。控制表达式求值时,控制会跳转到与switch表达式的值相匹配的分支标号处。分支标号只是一个说明switch内部位置的标记,不影响程序控制流。执行完这个分支的最后一条语句后,程序会忽略分支标号,向下跳转到下一个分支的第一条语句上。
    break语句会让控制跳转到switch语句的下面。

switch的最后一个分支不需要break语句,但是也会加一个,以防后续增加分支数目时忘记写break语句。

6章 循环

6.1 while语句

表达式为真,就执行后面的语句。持续执行,直到表达式为假。

while (表达式) 语句;

表达式后面的语句称为循环体。循环体可以有多条语句,使用花括号括起来即可。

如果控制表达式始终为真,while语句会无限循环下去。需要的时候常常用非零常量来构造无限循环。

while (1) ...

6.2 do语句

do语句先执行循环体,然后计算控制表达式的值,如果表达式是非零的,就再次执行循环体,然后再次计算表达式的值。直到表达式的值为0,就终止do语句。

do 语句 while (表达式);

循环体可以是一条语句,也可以是花括号包起来的复合语句。
使用时最好给所有的do语句都加上花括号,因为没有花括号的do语句容易被误认为while语句。

6.3 for语句

for (声明或表达式1; 表达式2; 表达式3) 语句;

表达式1是循环开始前的初始化步骤,只执行1次;表达式2用来控制循环,表达式2的值不为0,循环就会一直执行下去;表达式3是每次循环中都会最后执行的操作。
由于表达式1和表达式3都是以语句的方式执行的,互不相关,它们经常被用做赋值表达式或自增/自减表达式。

for循环可以使用等价的while循环替换:

表达式1;
while (表达式2) {语句;表达式3;
}
for语句常用的形式

for语句很适合用在使用计数变量的循环中。for语句实现“向上加”或“向下减”n次的循环的一般格式:

// 向上加,从0加到n-1
for (i = 0; i < n; i++) ...
// 向上加,从1加到n
for (i = 1; i <= n; i++) ...
// 向下减,从n-1到0
for (i = n - 1; i >= 0; i--) ...
// 向下减,从n到1
for (i = n; i > 0; i--) ...

使用时要注意<<=的使用效果,避免循环次数出错。

for循环省略表达式

C语言允许省略for循环的表达式。

省略表达式1,执行循环前没有初始化操作,相关操作需要放到循环前进行。

for (;表达式2;表达式3) ...

省略表达式3,则需要在循环体中确保表达式2最终会变为假。

for (表达式1;表达式2;) ...

同时省略表达式1和表达式3,产生的效果和while语句一样。这时使用while语句更好。

for (;表达式2;) ...while (表达式2) ...

省略表达式2,默认判定为真,for语句进入无限循环:

for (;;) ...
声明用于循环的变量

C99中,表达式1可以替换为一个声明:

for (int i = 0; i < n; i++) ...

变量i不需要在for语句之前声明。
如果for语句之前已经声明了变量i,表达式1会创建一个新的i仅用于循环内。这样声明的变量不可以在循环外访问。
for语句可以声明多个同类型的变量。

逗号运算符

逗号运算符是为了在C语言要求只能有一个表达式的情况下,可以使用两个或更多表达式。
比如想在for语句中,编写多个初始化表达式,或者在每次循环中对多个变量执行自增操作。

表达式1, 表达式2

逗号表达式先计算表达式1的值,然后扔掉。接着计算表达式2的值,将这个值做为整个表达式的值。
表达式1应该始终都有副作用(更改变量值),否则就没有意义。

for (sum = 0, i = 1; i <= n; i++)sum += i;

6.4 退出循环

  • break
    break可以跳出while、do或for循环。
    它适用于需要把退出点设置在循环体中间而不是之前或之后的情况。

break可以把程序控制从包含它的最内层while、do、for或switch语句中转移出去。
这些语句嵌套出现时,break只能跳出一层嵌套。

  • continue
    continue可以跳过某次迭代的部分内容。
    它只能用在循环中,并且把程序控制转移到循环体末尾之前,不跳出循环,直接进入下一次迭代。

  • goto
    breakcontinue都是跳转语句,它们都有特定的跳转点。break跳到包含它的循环结束之后的点,continue跳到循环结束之前的点。
    goto语句可以跳转到函数中任何有标号的语句处。
    标号是放在语句开始处的标识符。

标识符: 语句;
goto 标识符;

执行goto语句时,控制会转移到标识符后面的语句上。该语句必须和goto处于同一个函数。

goto语句在早期的编程语言中很常见,但是日常编程中很少用了。break、continue、return和exit函数可以代替需要使用goto的大多数情况。
goto语句既可以往前跳又可以往后跳,而且多个goto语句可以到达同一个标号,这会使代码难以理解和修改。

goto语句很有用的地方在于,能一次跳出多层嵌套的循环:

while (...) {while (...){...// 这里使用break只能跳出一层goto loop_done;...}
}
loop_done: ...;

6.5 空语句

空语句是除了末尾的分号外什么也没有的语句。

空语句可以用来编写空循环体的循环:

for (d = 2; d < n && n % d != 0; d++);

空语句最好单独放在一行,避免阅读程序时分不清后面的语句是否是循环体。可以使用其它写法凸显空循环体:

for (d = 2; d < n && n % d != 0; d++)continue;for (d = 2; d < n && n % d != 0; d++){}

循环转变为空循环体的循环后,通常不会提升效率。

注意 如果不小心在ifwhilefor语句的圆括号后面加了分号,就会创建空语句,导致ifwhilefor语句提前结束。
if语句的圆括号后加分号,条件会失效,后面的语句总会被执行;
while语句的圆括号后加分号,会造成无限循环。即使循环终止,也只执行一次循环体。
for语句的圆括号后加分号,只执行一次循环体。

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

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

相关文章

电子电气架构 --- Trace 32(劳特巴赫)多核系统的调试

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所有人的看法和评价都是暂时的,只有自己的经历是伴随一生的,几乎所有的担忧和畏惧,都是来源于自己的想象,只有你真的去做了,才会发现有多快乐。…

Markdown转HTML

来源&#xff1a; https://juejin.cn/post/7310787455112445987 Markdown 一种简单易用的标记语言&#xff0c;旨在使纯文本格式化变得简单且易于阅读&#xff0c;它的设计目标是使文档易于阅读和书写同时保持格式的清晰和简洁 为什么会有Markdown转HTML的需求 尽管 Markdo…

哈希表与unordered_map

1.哈希概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素时&#xff0c;必须要经过关键码的多次比较。搜索的效率取决于搜索过程中元素的比较次数&#xff0c;因此顺序结构中查找的时间复杂度O(N)&#xff0c;平…

Python | Leetcode Python题解之第540题有序数组中的单一元素

题目&#xff1a; 题解&#xff1a; class Solution:def singleNonDuplicate(self, nums: List[int]) -> int:low, high 0, len(nums) - 1while low < high:mid (low high) // 2mid - mid & 1if nums[mid] nums[mid 1]:low mid 2else:high midreturn nums[l…

C++ 项目中使用 .dll 和 .def 文件的操作指南

在 C 项目中使用 sqlite3.dll 和 .def 文件的操作指南 在 C 项目中&#xff0c;当我们只有 sqlite3.dll 和 .def 文件&#xff0c;但没有 .lib 文件时&#xff0c;通常需要生成 .lib 文件以便项目链接或直接调用 sqlite3.dll。本文将介绍几种方法来生成 .lib 文件&#xff0c;…

有Bootloader,为什么还要BROM?

有Bootloader&#xff0c;为什么还要BROM? 不少硬件平台都提供类似Boot ROM或者PBL(高通平台)固化的一段程序&#xff0c;出厂后用户一定不能修改。BROM可以引导Bootloader程序。大家知道&#xff0c;每个可启动的平台都会在存储设备&#xff0c;例如EMMC/NAND/UFS保存Bootloa…

MongoDB笔记02-MongoDB基本常用命令

文章目录 一、前言二、数据库操作2.1 选择和创建数据库2.2 数据库的删除 3 集合操作3.1 集合的显式创建3.2 集合的隐式创建3.3 集合的删除 四、文档基本CRUD4.1 文档的插入4.1.1 单个文档插入4.1.2 批量插入 4.2 文档的基本查询4.2.1 查询所有4.2.2 投影查询&#xff08;Projec…

期权懂|股指期权开户门槛不够该怎么办?

期权小懂每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 股指期权开户门槛不够该怎么办&#xff1f; 股指期权开户门槛不够&#xff0c;可以考虑利用资管分仓账户‌&#xff0c;选择已开通期权交易资格的主账户进行分仓&#xff0c;账户…

数据库SQL学习笔记

第 1 章 绪论 1.1 数据库系统概述 1.1.1 四个基本概念 数据库系统(DBS) 定义&#xff1a;是指在计算机系统中引入数据库后的系统构成 构成&#xff1a;数据库&#xff0c;数据库管理系统&#xff08;及其开发工具&#xff09;&#xff0c;应用系统&#xff0c;数据库管理员…

Jenkins系列

jenkins 1、搭建Jenkins 搭建Jenkins 2、这是什么 3、这是什么 4、 这是什么 5、这是什么 文章目录 jenkins1、搭建Jenkins2、这是什么3、这是什么4、 这是什么5、这是什么 前言 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;随…

WPF(C#)学习日志10:Prism框架下按键绑定

在Prism框架下&#xff0c;提供了DelegateCommand类用于处理了UI的按键请求&#xff0c;XAML中可以直接采用 Command"{Binding **}" 来绑定这些方法。这个类是一个泛型的类生命时仅需要DelegateCommand<T>即可&#xff0c;同时在XAML中绑定CommandParameter&qu…

嵌入式常用功能之通讯协议1--串口

嵌入式常用功能之通讯协议1--串口&#xff08;本文&#xff09; 嵌入式常用功能之通讯协议1--IIC 嵌入式常用功能之通讯协议1--SPI&#xff08;待定&#xff09; ...... 一、串口协议简介 1&#xff0c;简介 UART(异步串行通信)&#xff1a;时钟基准不是同一个&#xff08…

云渲染与汽车CGI图像技术优势和劣势

在数字时代&#xff0c;云渲染技术以其独特的优势在汽车CGI图像制作中占据了重要地位。云渲染通过利用云计算的分布式处理能力&#xff0c;将渲染任务分配给云端的服务器集群进行计算&#xff0c;从而实现高效、高质量的渲染效果。 这种技术的优势主要体现在以下几个方面&#…

Android 延时操作的常用方法

一、简介 在Android开发中我们可能会有延时执行某个操作的需求&#xff0c;例如我们启动应用的时候&#xff0c;一开始呈现的是引导页面&#xff0c;3秒后进入主界面&#xff0c;这就是一个延时操作。还有一种是执行某些接口任务时&#xff0c;需要有超时机制。下面介绍常用的…

Foundry 单元测试

安装 Foundry 如果你还没有安装 Foundry&#xff0c;请按照此处的说明进行操作&#xff1a;Foundry 安装 Foundry Hello World 只需运行以下命令&#xff0c;它将为你设置环境&#xff0c;创建测试并运行它们。&#xff08;当然&#xff0c;这假设你已经安装了 Foundry&…

Anaconda超详细下载安装教程(附安装包)

文章目录 一、下载二、安装Anaconda1.解压下载的安装包2.开始安装3.测试配置是否成功4.其他问题1.查看Anaconda版本2.查看当前是否可以使用python 一、下载 Anaconda安装包下载&#xff1a;https://pan.quark.cn/s/ae29fb506730 &#xff08;直接下载&#xff0c;解压安装即可…

Go-性能优化、优化分析、调优实战pprof

使用官方自带benchmark进行基准性能测试 第一个是函数名-核数 第二个是执行次数 第三个是一次执行时间 第四个是一次执行的多大的内存 第五个是一次执行申请几次内存 slice用的时候在make&#xff08;&#xff09;初始化切片时提供容量信息 data:make([]int,0) data:make([]in…

docker安装低版本的jenkins-2.346.3,在线安装对应版本插件失败的解决方法

提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、网上最多的默认解决方法1、jenkins界面配置清华源2、替换default.json文件 二、解决低版本Jenkins在线安装插件问题1.手动下载插件并导入2.低版本jenkins在…

android 使用xml设置背景图片和圆角

使用xml设置背景图片和圆角 <?xml version"1.0" encoding"utf-8"?> <layer-list xmlns:android"http://schemas.android.com/apk/res/android"><item><shape><solid android:color"android:color/transparen…

SIwave:释放信号网络分析仪的强大功能

SIwave 是一种电源完整性和信号完整性工具。信号网络分析器求解器是 SIwave 中的工具之一。 Signal Net Analyzer 是 SIwave 信号完整性包的一部分。它可以快速计算走线的信号完整性。它计算阻抗、延迟、损耗和许多其他东西。它允许用户研究迹线损耗和任何缺陷对注入信号的影响…