C语言入门(四)——分支语句

news2024/11/17 20:47:31

if语句

if/else语句

布尔代数

switch语句


if语句

目前我们写的简单函数中可以有多条语句,但这些语句总是从前到后顺序执行的。除了顺序执行之
外,有时候我们需要检查一个条件,然后根据检查的结果执行不同的后续代码,在 C 语言中可以用
分支语句( Selection Statement )实现,比如:
if (x != 0) {
 printf("x is nonzero.\n");
}
其中 x != 0 表示 “x 不等于 0” 的条件,这个表达式称为控制表达式( Controlling Expression )如果条
件成立,则 {} 中的语句被执行,否则 {} 中的语句不执行,直接跳到 } 后面。 if 和控制表达式改变了程
序的控制流程( Control Flow ),不再是从前到后顺序执行,而是根据不同的条件执行不同的语
句,这种控制流程称为分支( Branch )。上例中的 != 号表示 不等于 ,像这样的运算符有:
关系运算符和相等性运算符
运算符含义
==等于
!=不等于
>大于
<小于
>=大于或等于
<=小于或等于
注意以下几点:
1.这里的 == 表示数学中的相等关系,相当于数学中的 = 号,初学者常犯的错误是在控制表达式中把== 写成 = ,在 C 语言中 = 号是赋值运算符,两者的含义完全不同。
2.如果表达式所表示的比较关系成立则值为真( True ),否则为假( False ),在 C 语言中分别
int 型的 1 0 表示。如果变量 x 的值是 -1 ,那么 x>0 这个表达式的值为 0 x>-2 这个表达式的
值为 1。
3.在数学中a<b<c表示b既大于a又小于c,但作为C语言表达式却不是这样。以上几种运算符都是
左结合的,请读者想一下这个表达式应如何求值。
4.这些运算符的两个操作数应该是相同类型的,两边都是整型或者都是浮点型可以做比较,但
两个字符串不能做比较,在后面我们会介绍比较字符串的方法。
5.==和!=称为相等性运算符(Equality Operator),其余四个称为关系运算符(Relational
Operator ),相等性运算符的优先级低于关系运算符。
总结一下, if (x != 0) { ... } 这个语句的计算顺序是:首先求 x != 0 这个表达式的值,如果值为0 ,就跳过 {} 中的语句直接执行后面的语句,如果值为 1 ,就先执行 {} 中的语句,然后再执行后面的语句。事实上控制表达式取任何非0 值都表示真值,例如 if (x) { ... } if (x != 0) { ...}是等价的,如果 x 的值是 2 ,则 x != 0 的值是 1 ,但对于 if 来说不管是 2 还是 1 都表示真值。
if 语句相关的语法规则如下:
语句 → if ( 控制表达式 ) 语句
语句 → { 语句列表}
语句 → ;
C 语言中,任何允许出现语句的地方既可以是由 ; 号结尾的一条语句,也可以是由 {} 括起来的若干
条语句或声明组成的语句块( Statement Block ),语句块和上一章介绍的函数体的语法相同。注意语句块的} 后面不需要加 ; 号。如果 } 后面加了 ; 号,则这个 ; 号本身又是一条新的语句了,在 C 语言中一个单独的; 号表示一条空语句( Null Statement )。上例的语句块中只有一条语句,其实没必要写成语句块,可以简单地写成:
if (x != 0)
 printf("x is nonzero.\n");
语句块中也可以定义局部变量,例如:
void foo(void)
{
 int i = 0;
 {
 int i = 1;
 int j = 2;
 printf("i=%d, j=%d\n", i, j);
 }
 printf("i=%d\n", i); /* cannot access j here */
}
和函数的局部变量同样道理,每次进入语句块时为变量 j 分配存储空间,每次退出语句块时释放变
j的存储空间。语句块也构成一个作用域,和 作用域的分析类似,如果整个源文件是一张
大纸, foo 函数是盖在上面的一张小纸,则函数中的语句块是盖在小纸上面的一张更小的纸。语句
块中的变量 i 和函数的局部变量 i 是两个不同的变量,因此两次打印的 i 值是不同的;语句块中的变
j 在退出语句块之后就没有了,因此最后一行的 printf 不能打印变量 j ,否则编译器会报错。语句
块可以用在任何允许出现语句的地方,不一定非得用在 if 语句中,单独使用语句块通常是为了定义
一些比函数的局部变量更 局部 的变量。

if/else语句

if 语句还可以带一个 else 子句( Clause ),例如:
if (x % 2 == 0)
 printf("x is even.\n");
else
 printf("x is odd.\n");
这里的 % 是取模( Modulo )运算符, x%2 表示 x 除以 2 所得的余数( Remainder ), C 语言规定 %
算符的两个操作数必须是整型的。两个正数相除取余数很好理解,如果操作数中有负数,结果应该
是正是负呢? C99 规定,如果 a b 是整型, b 不等于 0 ,则表达式 (a/b)*b+a%b 的值总是等于 a,再结表达式讲过的整数除法运算要Truncate Toward Zero,可以得到一个结论: %运算符的结果总是与被除数同号(想一想为什么)。其它编程语言对取模运算的规定各不相同,也有规定结果和除数同号的,也有不做明确规定的。
取模运算在程序中是非常有用的,例如上面的例子判断 x 的奇偶性( Parity ),看 x 除以 2 的余数是不
0 ,如果是 0 则打印 x is even. ,如果不是 0 则打印 x is odd. ,读者应该能看出 else 在这里的作用
了,如果在上面的例子中去掉 else ,则不管 x 是奇是偶, printf("x is odd.\n"); 总是执行。为了
让这条语句更有用,可以把它封装( Encapsulate )成一个函数:
void print_parity(int x)
{
 if (x % 2 == 0)
 printf("x is even.\n");
 else
 printf("x is odd.\n");
}
把语句封装成函数的基本步骤是:把语句放到函数体中,把变量改成函数的参数。这样,以后要检
查一个数的奇偶性只需调用这个函数而不必重复写这条语句了,例如:
print_parity(17);
print_parity(18);
if/else 语句的语法规则如下:
语句 → if ( 控制表达式 ) 语句 else 语句
右边的 语句 既可以是一条语句,也可以是由 {} 括起来的语句块。一条 if 语句中包含一条子语句,
一条 if/else 语句中包含两条子语句,子语句可以是任何语句或语句块,当然也可以是另外一
if if/else 语句。根据组合规则, if if/else 可以嵌套使用。例如可以这样:
if (x > 0)
 printf("x is positive.\n");
else if (x < 0)
 printf("x is negative.\n");
else
 printf("x is zero.\n");
也可以这样:
if (x > 0) {
 printf("x is positive.\n");
} else {
 if (x < 0)
 printf("x is negative.\n");
 else
 printf("x is zero.\n");
}
现在有一个问题,类似 if (A) if (B) C; else D; 形式的语句怎么理解呢?可以理解成
if (A)
 if (B)
        C;
else
   D;

也可以理解成

if (A)
  if (B)
        C;
  else
        D;
1 继续 Hello World” 讲过, C 代码的缩进只是为了程序员看起来方便,实际上对编译器不起
任何作用,你的代码不管写成上面哪一种缩进格式,在编译器看起来都是一样的。那么编译器到底
按哪种方式理解呢?也就是说, else 到底是和 if (A) 配对还是和 if (B) 配对?很多编程语言的语法
都有这个问题,称为 Dangling-else 问题。 C 语言规定, else 总是和它上面最近的一个 if 配对,因此
应该理解成 else if (B) 配对,也就是按第二种方式理解。如果你写成上面第一种缩进的格式就很
危险了:你看到的是这样,而编译器理解的却是那样。如果你希望编译器按第一种方式理解,应该
明确加上 {}
if (A) {
 if (B)
   C;
} else
   D;
顺便提一下,浮点型的精度有限,不适合用 == 运算符做精确比较。以下代码可以说明问题:
double i = 20.0;
double j = i / 7.0;
if (j * 7.0 == i)
 printf("Equal.\n");
else
 printf("Unequal.\n");
不同平台的浮点数实现有很多不同之处,在我的平台上运行这段程序结果为 Unequal ,即使在你的
平台上运行结果为 Equal ,你再把 i 改成其它值试试,总有些值会使得结果为 Unequal 。等学习了 4 浮点数 你就知道为什么浮点型不能做精确比较了。

布尔代数

1 “if 语句 讲过, a<b<c 不表示 b 既大于 a 又小于 c ,那么如果想表示这个含义该怎么写呢?可
以这样:
if (a < b) {
 if (b < c) {
 printf("b is between a and c.\n");
 }
}
我们也可以用逻辑与( Logical AND )运算符表示这两个条件同时成立。逻辑与运算符在 C 语言中写成两个& 号( Ampersand ),上面的语句可以改写为:
if (a < b && b < c) {
 printf("b is between a and c.\n");
}
对于 a < b && b < c 这个控制表达式,要求 a < b 的值非 0” b < c 的值非 0” 这两个条件同时成立
整个表达式的值才为 1 ,否则整个表达式的值为 0 。也就是只有两个条件都为真,它们做逻辑与运算
的结果才为真,有一个条件为假,则逻辑与运算的结果为假,如下表所示:
ABA AND B
000
010
100
111
这种表称为真值表( Truth Table )。注意逻辑与运算的操作数以非 0 表示真以 0 表示假,而运算结果
1 表示真以 0 表示假(类型是 int ),我们忽略这些细微的差别,在表中全部以 1 表示真以 0 表示 假。C 语言还提供了逻辑或( Logical OR )运算符,写成两个 | 线( Pipe Sign ),逻辑非( Logical
NOT )运算符,写成一个 ! 号( Exclamation Mark ),它们的真值表如下:
ABA OR B
000
011
101
111
逻辑或表示两个条件只要有一个为真,它们做逻辑或运算的结果就为真,只有两个条件都为假,逻
辑或运算的结果才为假。逻辑非的作用是对原来的逻辑值取反,原来是真的就是假,原来是假的就
是真。逻辑非运算符只有一个操作数,称为单目运算符 Unary Operator ),以前讲过的加减乘 除、赋值、相等性、关系、逻辑与、逻辑或运算符都有两个操作数,称为双目运算符(Binary
Operator )。
关于逻辑运算的数学体系称为布尔代数 Boolean Algebra),以它的创始人布尔命名。在编程语
言中表示真和假的数据类型叫做布尔类型,在 C 语言中通常用 int 型来表示,非 0 表示真, 0 表示假[ 6 ] 。布尔逻辑是写程序的基本功之一,程序中的很多错误都可以归因于逻辑错误。以下是一些布尔代数的基本定理,为了简洁易读,真和假用1 0 表示, AND * 号表示, OR + 号表示(从真值表可以看出AND OR 运算确实有点像乘法和加法运算), NOT ¬ 表示,变量 x y z 的值可能是0 也可能是 1

 除了第1行之外,这些公式都是每两行一组的,每组的两个公式就像对联一样:把其中一个公式中 的*换成++换成*0换成11换成0,就变成了与它对称的另一个公式。这些定理都可以通过真 值表证明,更多细节可参考有关数字逻辑的教材,例如[数字逻辑基础]

目前为止介绍的这些运算符的优先级顺序是: ! 高于 * / % ,高于 + - ,高于 > < >= <= ,高于 == !=
高于 && ,高于 || ,高于 = 。写一个控制表达式很可能同时用到这些运算符中的多个,如果记不清楚
运算符的优先级一定要多套括号。我们将在 运算符总结 总结 C 语言所有运算符的优先级和结合性。

switch语句

switch 语句可以产生具有多个分支的控制流程。它的格式是:
switch ( 控制表达式 ) {
case 常量表达式: 语句列表
case 常量表达式: 语句列表
...
default : 语句列表
}
例如以下程序根据传入的参数 1~7 分别打印 Monday~Sunday

如果传入的参数是 2 ,则从 case 2 分支开始执行,先是打印相应的信息,然后遇到 break 语句,它的
作用是跳出整个 switch 语句块。 C 语言规定各 case 分支的常量表达式必须互不相同,如果控制表达
式不等于任何一个常量表达式,则从 default 分支开始执行,通常把 default 分支写在最后,但不是
必须的。使用 switch 语句要注意几点:
1.case后面跟表达式的必须是常量表达式,这个值和全局变量的初始值一样必须在编译时计算
出来。
2. 2 “if/else 语句 讲过浮点型不适合做精确比较,所以C语言规定case后面跟的必须是 整型
常量表达式。
3.进入case后如果没有遇到break语句就会一直往下执行,后面其它case或default分支的语句
也会被执行到,直到遇到 break ,或者执行到整个 switch 语句块的末尾。通常每个 case 后面都
要加上 break 语句,但有时会故意不加 break 来利用这个特性,例如:

 

switch 语句不是必不可缺的,显然可以用一组 if ... else if ... else if ... else ... 代替,
但是一方面用 switch 语句会使代码更清晰,另一方面,有时候编译器会对 switch 语句进行整体优
化,使它比等价的 if/else 语句所生成的指令效率更高。

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

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

相关文章

ResNet精读笔记(1)

introduction部分提出了几个问题 1.构建一个好的网络 &#xff1f; 把层堆起来吗 哈哈 跟堆汉堡一样 这里呢 我们都知道 当网络的层数变多之后 加深了 deep了 但是 就会带来 梯度消失或者爆炸的问题 这里 实在找不到好的图 本质上因为当层数多了之后 反向传播的计算里面是…

嵌入式:万字详解通信接口设计

文章目录UART接口UART的工作原理UART的功能和组成S3C2410A的UARTUART 操作&#xff08;1&#xff09;数据发送&#xff08;2&#xff09;数据接收&#xff08;3&#xff09;自动流控制&#xff08;4&#xff09;非自动流控制&#xff08;a&#xff09;接收数据操作&#xff08;…

【C++】模拟实现List的正向和反向迭代器(iterator、reverse_iterator)

文章目录1、搭建List的基本框架2、List中iterator和const_iterator3、反向迭代器revser_iterator1、搭建List的基本框架 STL中List容器底层是一个双向带头循环链表。 这里简单搭建一个List&#xff0c;下面我们不断完善。 思路&#xff1a; 1、List作为一个双向带头链表&…

excel函数公式:常用高频公式应用总结 下篇

公式6&#xff1a;根据身份证号码计算出生日期要从身份证号码中得到出生日期&#xff0c;这种问题对于从事人资行政岗位的小伙伴一定不陌生&#xff0c;公式也比较简单&#xff1a;TEXT(MID(A2,7,8),"0-00-00")就能得到所需结果&#xff0c;如图所示&#xff1a;要明…

vue+xlsx实现表格的导入导出:

文章目录一、vue前端使用xlsx和 xlsx-style 导出excel&#xff0c;并修改样式:1、改造后效果&#xff1a;2、实现&#xff1a;3、引入库xlsx-style4、excelUtil.js文件二、前端xlsx插件怎么设置导出的excel列宽自适应&#xff1f;2-1、效果2-2、效果三、xlsx插件&#xff0c;导…

Java语法六:线程安全以及死锁

前言&#xff1a; 接下来我们要了解一下&#xff0c;线程安全的集合类有哪些&#xff1f;什么是死锁以及怎么避免死锁问题。 1.多线程环境使用哈希表 1.1&#xff1a;HashTable 只是简单的把关键方法加上synchronized关键字。 public synchronized V put(K key, V value) p…

(1分钟速览)最近邻搜索--激光SLAM常用必杀技

学习kdtree的数据结构&#xff0c;和二叉树的思想大体上算是比较相似的。参考博客&#xff1a;https://blog.csdn.net/dive_shallow/article/details/113136145建树&#xff0c;一个递归的操作。这里的删除操作很好理解&#xff0c;分左子树和右子树两种情况。如果是左子树那么…

Go语言设计与实现 -- 内存对齐机制

什么是内存对齐 为了能让CPU可以更快的存取到各个字段&#xff0c;Go编译器会帮你把struct结构体做数据的对齐。所谓的数据对齐&#xff0c;是指内存地址是所存储数据的大小&#xff08;按字节为单位&#xff09;的整数倍&#xff0c;以便CU可以一次将该数据从内存中读取出来。…

每天五分钟机器学习:推荐系统中所有用户的损失函数是什么?

本文重点 我们分析机器学习算法都是从损失函数的角度来说的,为了找到最佳的参数θ,可以最小化损失函数,那么本节课程我们将学习基于内容的推荐系统的损失函数是什么? 数据集 我们将每一个电影称为样本,每个电影有两个特征x1、x2,其中x1表示该电影为恐怖片的程度,x2表…

测试开发 | 跨平台设备管理方案 Selenium Grid

Selenium Grid 是 Selenium 的三大组件之一&#xff0c;它可以在多台机器上并行运行测试&#xff0c;集中管理不同的浏览器版本和浏览器配置。通过将客户端命令发送到远程浏览器的实例, Selenium Grid 允许在远程计算机 (虚拟或真实) 上执行 WebDriver 脚本. 它旨在提供一种在多…

SSL证书的类型

SSL证书类型分3类&#xff1a;DV OV EV.域名型&#xff08;DV&#xff09;SSL证书: 信任等级一般&#xff0c;只需验证网站的真实性便可颁发证书保护网站。企业型&#xff08;OV&#xff09;SSL证书: 信任等级强&#xff0c;须要验证企业的身份&#xff0c;审核严格&#xff0c…

VS2017基于CLR运行环境的VC++.NET界面编程(数据库为mysql)

此篇献给暨南大学珠海校区还在用VS2013编写VC++.NET界面程序的苦逼们! 文章分为四个部分: 1、运行环境的搭建 2、数据库的连接 3、控件介绍 4、程序编写示例 程序效果演示视频和程序源码及数据库文件附于文末。 一、运行环境的搭建 VS自从2013版本后淘汰VC++.NET,编写界面…

恒星物联河道流量监测站——雷达流量计

一、产品概述 河道流量监测站是一款采用一体化设计的河道流量智能监测设备&#xff0c;设备由河道雷达流量计、遥测终端机、太阳能供电系统组成。雷达流量计采用先进的K波段平面雷达技术&#xff0c;通过非接触的方式测量水体的流速和水位&#xff0c;根据内置的软件算法&…

TCP协议重点总结(万字总结-附实例)

文章目录前言一、网络的原生情况二、TCP协议2.1 TCP的特点2.2 TCP协议段格式2.3 TCP原理2.3.1 确认应答机制&#xff08;可靠机制&#xff09;2.3.2 序列号2.3.3 超时重传机制&#xff08;可靠机制&#xff09;2.3.4 连接管理机制&#xff08;可靠机制&#xff09;2.3.5 滑动窗…

RabbitMQ的简介和简单使用

同步调用异步调用MQRabbitMQ的使用docker拉取docker pull rabbitmq:3-management启动容器docker run \-e RABBITMQ_DEFAULT_USERitcast \ &#xff08;账号&#xff09;-e RABBITMQ_DEFAULT_PASS123321 \ &#xff08;密码&#xff09;--name mq \--hostname mq1 \-p 15672:156…

开发工具中SpringBoot使用外置Tomcat启动 (亲测有效)-第458篇

历史文章&#xff08;文章累计450&#xff09; 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 SpringBoot添加外部jar包及打包(亲测有…

评测5款国内外免费远控,谁是最好用第一名?

远程控制应用不少人都有了解使用过&#xff0c;尤其是会常用电脑进行工作的群体&#xff0c;比如程序员、设计师、运维、文员等岗位。在隔离居家远程办公时&#xff0c;通过家里的手机、平板或电脑跨系统、跨设备操控公司所用的办公电脑&#xff0c;就能及时处理工作内容&#…

前端使用lottie-web,使用AE到处的JSON动画贴心教程

Lottie简介 官方介绍&#xff1a;Lottie是一个库&#xff0c;可以解析使用AE制作的动画&#xff08;需要用bodymovie导出为json格式&#xff09;,支持web、ios、android、flutter和react native。 在web端&#xff0c;lottie-web库可以解析导出的动画json文件&#xff0c;并将其…

02_FreeRTOS移植

目录 获取FreeRTOS源码 FreeRTOS源码内容 FreeRTOS内核 Demo文件夹 Source文件夹 portable文件夹 FreeRTOS移植 移植步骤 移植详解 实验源码: 获取FreeRTOS源码 FreeRTOS官网:https://www.freertos.org/ FreeRTOS源码内容 FreeRTOS内核 Demo文件夹 Demo文件夹里面就…

《Protein Actions Principles and Modeling》-《蛋白质作用原理和建模》中文分享(15)

《Protein Actions Principles and Modeling》-《蛋白质作用原理和建模》 本人能力有限&#xff0c;如果错误欢迎批评指正。 第四章&#xff1a;Protein Binding Leads to Biological Actions &#xff08;蛋白质的结合会产生生物作用&#xff09; 如果我们想要对一个结合过…