你好,C++(18) 到底要不要买这个西瓜?4.1.6 操作符之间的优先顺序
你好,C++(18) 到底要不要买这个西瓜?4.1.6 操作符之间的优先顺序
4.1.6 操作符之间的优先顺序
在表达一些比较复杂的条件判断时,在同一个表达式中,有时可能会存在多个操作符。比如,我们在判断要不要买某个西瓜时,不仅要 判断它的总价(单价8.2元/斤,一共10.3斤)是否小于100块钱(因为兜里只有这么多钱),同时还要判断这个西瓜是否有坏掉的地方。要表达这个复杂 的条件判断,我们不得不把前面学过的算术操作符、关系操作符和逻辑操作符全都派上场:
bool bBad = false; // 是否有坏掉的地方
float fPrice = 8.2; // 单价
float fWeight = 10.3; // 重量
// 判断总价是否小于100且是否坏掉
if(fPrice * fWeight < 100 && !bBad)
{cout<<"买西瓜"<<endl;
}
else
{cout<<"算了,不买了"<<endl;
}
在“fPrice * fWeight < 100 && !bBad”这个表达式中,有算术操作符“*”,有关系操作符“<”,同时也还有逻辑操作符“!”和“&&”。那么,这么多操作符 在同一个表达式中,到底该从哪一个操作开始呢?这个表达式的最终结果又是什么呢?
要想搞清楚一个表达式是按照什么顺序计算的,就得先搞清楚各个操作符之间的计算优先级。按照正确的计算顺序进行计算,才可以得出正确的结果。在C++中,各个操作符的优先级如表4-1所示。
表4-1 操作符的优先级
级别
操 作 符
说 明
1
( )
括号是所有操作符中的领导,具有最高的优先级。如果括号内部还有括号,内部括号的优先级更高
2
!、+(正号)、-(负号)、++、--
它们都是一元操作符,往往是对操作数进行计算得到结果后继续参与下一个计算
注意,这里的+、-指的是改变数值正负属性的符号,而不是加减操作的符号
3
*、/、%
乘、除、取余运算
4
+、-
加、减运算
5
>、>=、<、<=、==、!=
关系运算
6
&&
逻辑与运算,它会首先计算其左侧表达式的值,当其值为true时,才会继续计算右侧表达式的值,最后计算两个值的逻辑与
7
||
逻辑或运算,它同样会首先计算其左侧表达式的值,若其值为false,则继续计算右侧表达式的值,最后计算两个值的逻辑或
8
=、+=、*=、/=、%=
赋值操作
表达式的计算顺序规则是:总是优先计算优先级较高的操作符;同一优先级的操作符,则按照从左到右的顺序进行计算;如果有特殊规 则的操作符(比如逻辑与“&&”),则按照特殊规则进行计算。在清楚了各操作符的优先级及表达式的计算规则后,那就可以计算上面这个复杂 表达式的结果了。在这个表达式中,有一个拥有特殊规则的操作符“&&”,按照它的计算规则,这个表达式会首先计算其左侧表达式的值:
fPrice * fWeight < 100 // 首先得到计算的左侧表达式
在这个表达式中,没有特殊规则的操作符,那就按照操作符的优先级进行计算。其中,优先级最高的是计算总价的乘法算术操作符“*”,对其进行计算后得到一个中间结果:
84.46 < 100 // fPrice*fWeight的结果是84.46
这个中间结果表达式只有一个操作符,直接计算得到其结果值为true。按照“&&”操作符的计算规则,如果左侧表达式的值为true,则继续计算其右侧表达式的值。所以,接下来要计算的表达式变为:
true && !bBad // 左侧表达式计算完成后的中间结果
在“&&”的右侧只有一个操作符“!”,直接计算得到的中间结果是:
true && true
现在,剩下唯一的逻辑与操作符“&&”,最终结果一目了然,对两个true值进行逻辑与运算,表达式的最终结果是true。计算机 在对表达式进行计算时,是按照各个操作符的优先级确定的计算顺序进行的。反过来,这也就要求我们在设计表达式的时候,也同样必须遵守操作符的优先顺序,按 照这个顺序来设计表达式。否则,实际的计算顺序跟我们设想的计算顺序不同,得到的计算结果自然也就跟我们的设想大相径庭了。从这个意义上讲,熟悉和掌握操 作符的优先级十分必要。
最佳实践:合理使用括号标示表达式的计算顺序
从上面这个例子我们可以看到,过于复杂的表达式计算起来非常麻烦。虽然表达式是由计算机负责计算,我们不用担心计算机怕麻烦。但是,表达式却是由程 序员进行设计,并且也是要提供给他人阅读的。设计过于复杂的表达式很容易出错,且代码的可读性非常差。所以我们应当尽量避免在同一表达式中混合使用多个操 作符,尽量保持表达式的短小精悍。必要的时候,可以将复杂的表达式拆分成多个较小的表达式分别计算得到中间结果,最后再将中间结果组合起来得到最终结果。 例如,我们可以把上面的复杂表达式拆分成两个较小的表达式,分别判断是否有坏掉的地方以及总价是否小于100块,然后再将这两个中间结果进行“与”运算, 得到最终结果:
// 将复杂表达式拆分成两个较小的表达式
bool bFresh = !bBad; // 表示是否新鲜
float fTotal = fPrice * fWeight; // 计算总价
bool bMoney = fTotal < 100; // 判断总价是否小于100块
// 对中间结果进行比较
if( bFresh && bMoney)
// …
经过这样的拆分,每个表达式的计算都清楚明了,减少了出错的可能,可读性也得到了提升。但是它同时也带来一个不便之处,那就是代码变的过于繁琐。既想得到拆分表达式带来的清楚明了的好处,又想避免代码繁琐的不便,那就只有使用“()”了。
“()”的优先级是所有操作符中最高的,使用它,可以人为地按照设计者的意图标示表达式中的计算顺序。比如,可以改写上面的表达式,用括号来表达我们希望的计算顺序,让其表达的意义更加清晰:
// …
if(((fPrice * fWeight) < 100) && (!bBad))
// …
使用括号后,整个表达式的计算顺序变得一目了然:按照括号确定的计算顺序,首先计算最里层的(fPrice * fWeight) 得到中间结果84.46,然后计算(84.46 < 100)得到中间结果true,接着计算(!bBad)得到中间结果true,最后计算“true && true”得到最终结果true。使用括号后,计算顺序跟默认顺序相同,但是却增加了代码的可读性,让我们对计算顺序一目了然,同时也避免了让代码变得过 于繁琐。另外,在某些特殊情况下需要改变表达式的默认计算顺序时,括号成为一种必须。
总结起来,使用“()”后,我们想让表达式按照什么顺序计算就按照什么顺序计算,妈妈再也不用担心我记不住各个操作符的优先级。
4.1.7 将表达式组织成语句
学习C++编程,实际上也就是学习如何使用这门特殊的语言来描述和表达现实世界,就如同我们学习英语是为了用它来描述和表达现 实世界一样。在前面的章节中,我们学习了操作符,学习了由操作符连接操作数而构成的各种表达式,而这些只能算是这门语言中的“短语”,它们可以表达一定的 意义,但却是不完整的:
// 短语式的表达式
a // 一个单独的变量,什么都不做
3 + 2 // 用算术操作符“+”计算3和2的和
这些表达式可以被执行,但它们并不改变程序的状态,也没有计算结果保留下来,所以没有任何实际的意义。就像在英语中我们需要给短语加上主谓宾才能构 成一个完整的句子一样,在C++中,我们也同样需要把一些表达零散意义的表达式组合起来,最后再加一个英文分号表示结束,以此来形成一个语句,用以完成某 个相对独立而完整的功能。例如,把上面两个表达式通过赋值操作符组合起来,就形成了一条完整的赋值语句:
// 赋值语句
a = 3 + 2;
形成语句后,它表达了一个完整的意义:用算术操作符“+”计算3和2的和,然后将其赋值给变量a。
在C++中,语句和表达式并没有严格的区分。很多时候,一个表达式加上一个分号就可以直接形成一条语句。语句强调它所完成的功能,而表达式关注它所描述的运算和最终的结果。在此之前,我们已经接触过两种最常见的语句类型:变量定义语句和赋值语句。
知道更多:使用“{}”表示的语句块
当连续的多条语句属于同一个控制结构时,可以用一对花括号“{}”将这些语句括起来,从而形成一个语句块,共同表达一个相对独立的意义。在使用上, 语句块与单独的语句并无太大区别,但是它的意义在于,它可以将多条语句打包成一个语句块,从而可以在for循环等控制结构中执行多条语句。例如,在for 循环结构中,我们可以这样来统计从1到100间所有整数的和:
int nTotal = 0;for(int i = 1; i <= 100; ++i)nTotal += i;
这个统计只需要一条语句就可以完成,自然可以把这条语句直接放在for循环结构之后完成,可是如果我们只需要统计这个区间中所有偶数的和,那么就需 要加上条件判断,这就不是单独一条语句可以完成的了。我们必须用“{}”将所有判断偶数、统计偶数的语句打包成一个语句块,然后放在for循环结构之后才 能完成统计:
for(int i = 1; i <= 100; ++i){ // for循环语句块开始if(0 == i%2) // 判断语句nTotal += i; // 统计语句
} // for循环语句块结束
除了打包语句之外,语句块的另外一个意义是,它代表了C++中的作用域的起讫位置。关于作用域的具体介绍可以参考后继的7.3.3小节。
相关文章:
你好,C++(18) 到底要不要买这个西瓜?4.1.6 操作符之间的优先顺序
你好,C(18) 到底要不要买这个西瓜?4.1.6 操作符之间的优先顺序 4.1.6 操作符之间的优先顺序 在表达一些比较复杂的条件判断时,在同一个表达式中,有时可能会存在多个操作符。比如,我们在判断要…...

C语言 for 循环语句的基本格式是什么?
一、问题 for 循环语句在C语⾔中是最为常见的循环语句,其功能强⼤,⽽且⽤法灵活,那么它的基本格式是什么呢? 二、解答 for 语句的⼀般形式为: for(表达式1;表达式2;表达3)语句; 每条 for 语句包含三个⽤分…...
项目-SERVER模块-日志宏
日志宏 #define INF 0 #define DBG 1 #define ERR 2#define LOG_LEVEL INF #define LOG(level, format, ...) do {\if (level < LOG_LEVEL) break;\time_t t time(NULL);\struct tm *ltm localtime(&t);\char tmp[32] {0};\strftime(tmp, 31, "%H:%M:%S"…...

TCP为什么要三次握手?
TCP三次握手协议是为了在不可靠的互联网环境中可靠地建立起一个连接,三次握手可以确保两端的发送和接收能力都是正常的。 那么,为什么是三次而不是二次或四次握手呢? 为什么不是二次握手? 如果是二次握手,即客户端发…...

网络防御第6次作业
防病毒网关 按照传播方式分类 病毒 病毒是一种基于硬件和操作系统的程序,具有感染和破坏能力,这与病毒程序的结构有关。病毒攻击的宿主程序是病毒的栖身地,它是病毒传播的目的地,又是下一次感染的出发点。计算机病毒感染的一般过…...

Jmeter分布式部署
前期准备: 1. 控制机一台,代理机一台,Jmeter安装包 操作步骤: 1. Linux安装Jmeter(windows安装教程自己搜一下) 1.1创建一个单独的文件夹(jmeter),用来存放Jmeter的安装包 mkdir jmeter 1.2…...

Odoo迈入开源第一低代码开发平台的重要里程碑
Odoo17的正式发布已经过去好几个月了,通过一段时间的运用,最大的感触就是,Odoo会成为企业管理软件低代码开发平台的重要一员,而V17则会成为这个过程中具有里程碑意义的版本。 时隔四个月,让我们回头来看看Odoo17带来的…...

WinForm、Wpf自动升级 AutoUpdater.NET
Github AutoUpdater.NET 目录 一、IIS部署 更新站点 二、创建Winform 一、IIS部署 更新站点 IIS默认站点目录下创建 目录 Downloads、Updates Updates目录创建文件 UpdateLog.html、AutoUpdaterStarter.xml UpdateLog.html: <html><body><h1…...
GPU不够用:语言模型的分布式挑战
引言 随着深度学习技术的飞速发展,大规模语言模型(LLM)在各种NLP任务中取得了令人瞩目的成绩。然而,这些模型的大小和复杂度也不断增加,给部署和应用带来了诸多挑战。特别是在单个GPU或服务器的内存容量有限的情况下,如何高效地利用分布式计算资源成为了一个亟待解决的问…...
深入理解Redis中的渐进式Rehash技术
1. 引言 Redis是一款高性能的键值存储系统,被广泛应用于缓存、队列、计数器等场景,因其快速、稳定的特性备受开发者青睐。在Redis的背后,有着许多复杂的数据结构和算法支撑着其高效运行,而其中之一就是Rehash操作。 Rehash是Redis中的一个关键操作,负责在数据量增加时对…...
数据结构 栈和队列 力扣例题AC——代码以及思路记录
20. 有效的括号 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应…...

管理类联考--复试--英文面试--各校英文面试内容
文章目录 北京地区北京大学中国人民大学北京交通大学北京航空航天大学北方工业大学北京林业大学北京语言大学中央财经大学对外经济贸易大学首都经济贸易大学华北电力大学中国矿业大学中国石油大学北京国家会计学院中国财政科学院研究院北京理工大学北京工商大学中国农业大学 湖…...

Android修行手册-Chaquopy中opencv、numpy的初步应用
Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分…...
VBA将当前打开的表格生成PDF图片
前言 VBA将当前的表格存储成PDF文件进行存储 代码 Sub ExportToPDF()Dim FilePath As StringDim FileName As StringDim ExportRange As Range 设置导出文件路径及名称FilePath "D:\Users\"FileName "ExportedPDF" 设置导出区域范围Set ExportRange Ra…...

解锁AI大模型秘籍:未来科技的前沿探索
在当今这个技术高速发展的时代,人工智能(AI)已经成为了我们生活中不可或缺的一部分。从简单的个人助手到复杂的数据分析和决策制定,AI的应用范围日益扩大,其目的是为了让我们的生活变得更加智能化。本文旨在探讨AI如何…...

一文带你了解MySQL之B+树索引的原理
前言 学完前面我们讲解了InnoDB数据页的7个组成部分,知道了各个数据页可以组成一个双向链表,而每个数据页中的记录会按照主键值从小到大的顺序组成一个单向链表,每个数据页都会为存储在它里边儿的记录生成一个页目录,在通过主键查…...

【Vue】npm run build 打包报错:请在[.env.local]中填入key后方可使用...
报错如下 根目录添加 .env.local 文件 .env.local :本地运行下的配置文件 配置:VUE_GITHUB_USER_NAME 及 VUE_APP_SECRET_KEY 原因...
中国电子学会2020年06月真题C语言软件编程等级考试三级(含详细解析答案)
中国电子学会考评中心历届真题(含解析答案) C语言软件编程等级考试三级 2020年06月 编程题五道 总分:100分一、最接近的分数(20分) 分母不超过N且小于A/B的最大最简分数是多少? 时间限制: 1000ms 内存限制: 65536kb 输入…...

WPF的DataGrid自动生成中文列头
直接将一个对象集合绑定到DataGrid上面,设置自动生成列AutoGenerateColumns"True",DataGrid会自动根据对象类的属性生成对应的列 示例类对象: public class DataModel{public int Id { get; set; }public string Name { get; set;…...

CSS【详解】居中对齐 (水平居中 vs 垂直居中)
水平居中 内部块级元素的宽度要小于容器(父元素) 方案一:文本居中对齐(内联元素) 限制条件:仅用于内联元素 display:inline 和 display: inline-block; 给容器添加样式 text-align:center<!DOCTYPE html> <html lang&q…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...