热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C++算法与数据结构_3

关系与逻辑表达式关系表达式在C中,关系运算符用于判断表达式之间的大小关系,对两边的值进行6种情况的判断:大于和大于等于运算符小于

关系与逻辑表达式


关系表达式


  • 在C++中,关系运算符用于判断表达式之间的大小关系,对两边的值进行6种情况的判断:
    • 大于>和大于等于>=运算符
    • 小于<和小于等于<&#61;运算符
    • 相等&#61;&#61;和不相等!&#61;运算符
  • 关系运算符中&#xff0c;表达式结果的类型可以是字符或者数字&#xff0c;但不可以是字符串
  • 关系表达式返回一个布尔值&#xff1a;成立为1&#xff08;true&#xff09;代表真&#xff0c;不成立为0&#xff08;false&#xff09;代表假

Tips&#xff1a;判断两个数是否相等&#xff0c;用的是&#61;&#61;而非&#61;&#xff0c;因为&#61;是用于赋值操作的。


  • 浮点数一般不会用 &#61;&#61; 或者 !&#61; 来判断&#xff0c;因为可能产生表示误差。
  • 比较两个浮点数是否相等&#xff0c;需要看两个数的差值是否小于一定的精度&#xff0c;比如&#xff1a;
    • 对于浮点数a和b&#xff0c;如果(a - b) <1e-6 如果值为真&#xff0c;就判断两个浮点数相等。

举例&#xff1a;假设血量是整型数&#xff0c;小六希望判断己方血量hp_a和敌方血量hp_b两个数值之间的关系。

判断己方与敌方血量&#xff08;整型数&#xff09;关系的程序段

int hp_a, hp_b;
hp_a &#61; 456;
hp_b &#61; 857;
cout <<"己方血量: " <// 判断 自己血量 是否大于 敌方血量
cout <<(hp_a > hp_b) <// 判断 自己血量 是否大于等于 敌方血量
cout <<(hp_a >&#61; hp_b) <// 判断 自己血量 是否小于 敌方血量
cout <<(hp_a // 判断 自己血量 是否小于等于 敌方血量
cout <<(hp_a <&#61; hp_b) <// 判断 自己血量 是否等于 敌方血量
cout <<(hp_a &#61;&#61; hp_b) <// 判断 自己血量 是否不等于 敌方血量
cout <<(hp_a !&#61; hp_b) <// 判断 自己回50点血后的血量 是否小于 敌方血量
cout <<((hp_a &#43; 50) // 判断 自己血量 是否小于 100
cout <<(hp_a <100) <

举例&#xff1a;假设血量是浮点数&#xff0c;小六希望判断己方血量 hp_c 和 敌方血量hp_d 是否相等。

判断己方与敌方血量&#xff08;浮点数&#xff09;关系的程序段

float hp_c, hp_d;
hp_c &#61; 100.0;
hp_d &#61; 100.0;
cout <<((hp_c - hp_d) <1e-6) <

逻辑表达式


  • 关系表达式可以判断某个条件是否成立&#xff0c;逻辑表达式中包含了多个关系表达式&#xff0c;可以对多个条件进行判断&#xff0c;例如:
    • 多个条件是否同时成立
    • 多个条件中是否至少有一个成立
    • 某个或某些条件是否不成立
  • C&#43;&#43;使用逻辑运算符连接多个关系表达式&#xff0c;从而构建逻辑表达式。
  • 常用的逻辑运算符有以下三种&#xff1a;
    • 逻辑AND运算符&&&#xff1a;判断两个关系表达式是否同时成立
    • 逻辑OR运算符||&#xff1a;判断两个关系表达式是否至少有一个成立
    • 逻辑NOT运算符!&#xff1a;判断某个关系表达式是否不成立C&#43;&#43;使用逻辑运算符连接多个关系表达式&#xff0c;从而构建逻辑表达式。
  • 假设p1p2是关系表达式的返回结果&#xff0c;逻辑运算符的运算规则可以参考下表&#xff1a;

p1p2p1&&p2p1llp2!p1
00001
01011
10010
11110

Tips&#xff1a;判断多个条件是否成立时&#xff0c;我们可以组合逻辑运算符&#xff0c;构成更复杂的逻辑表达式。

举例&#xff1a;判断当变量 a 是否是30以下或者100以上的偶数时&#xff0c;可以通过 (a%2&#61;&#61;0) && ((a <30) || (a > 100)) 得到结果。

举例&#xff1a;小六最近在游戏上进步了一点点&#xff0c;他知道有的时候撤不撤退&#xff0c;不只需要看自己血量是否比敌方高&#xff0c;还需要看自己的蓝量是否比敌方高。

假设布尔值 higher_hp 表示自己血量比对方高&#xff0c;higher_mp 表示自己蓝量比对方高。

小六想要知道&#xff1a;“是否自己血量和蓝量都比敌方高”&#xff0c;“是否自己血量和蓝量和中至少有一种比敌方高”&#xff0c;“是否血量没有敌方高”&#xff0c;“是否自己血量和蓝量都没有敌方高”&#xff0c;你能够把这些信息都输出给小六吗&#xff1f;

判断敌我双方血量和蓝量的程序段

// 假设小六血量比敌方高&#xff0c;但是蓝量没有敌方高
bool higher_hp &#61; 1;
bool higher_mp &#61; 0;// 是否自己血量和蓝量都比敌方高
cout <<(higher_hp && higher_mp) <// 是否自己血量和蓝量和中至少有一种比敌方高
cout <<(higher_hp || higher_mp) <// 是否血量没有敌方高
cout <<(!higher_hp) <// 是否自己血量和蓝量都没有敌方高
cout <<(!higher_hp && !higher_mp) <

运算符优先级


  • 至此&#xff0c;我们已经学习的运算符如下&#xff1a;
    • 算术运算符&#xff08;&#43; - * / % &#43;&#43; --等&#xff09;
    • 赋值运算符&#xff08;&#61;等&#xff09;
    • 位运算符&#xff08;<<>>等&#xff09;
    • 关系运算符&#xff08;> >&#61; <<&#61; &#61;&#61; !&#61;等&#xff09;
    • 逻辑运算符&#xff08;&& || !等&#xff09;
  • 对于这些常用的运算符&#xff0c;按照计算优先级从高到低&#xff08;左边更高&#xff0c;右边更低&#xff09;进行排列&#xff0c;可以得到如下表格&#xff1a;

()! -(负号) &#43;&#43; --* / %&#43; -(减号)<<>>&#61;&#61; !&#61;&&ll

Tips&#xff1a;对于一个表达式&#xff0c;虽然可以通过计算优先级省略掉括号&#xff0c;但为了代码的可读性&#xff0c;我们在编写时一般都选择把括号加上


习题

举例&#xff1a;生日在2月29日的程序员小键希望用一段代码判断输入的某一年是否为闰年。


  • 判断“闰年”的口诀是&#xff1a;四年一闰&#xff0c;百年不闰&#xff0c;四百年又闰。即闰年分为两种&#xff1a;
    • 一种是被400整除的年份
    • 一种是不被100整除&#xff0c;但是被4整除的年份

为了综合这两个条件&#xff0c;小键通过逻辑表达式来实现了这个功能&#xff1a;

判断闰年的程序段&#xff08;一&#xff09;

int year;
cin >> year;
bool is_leap_year;// 是400的倍数&#xff1b;或者是4的倍数并且不是100的倍数
is_leap_year &#61; (year % 400 &#61;&#61; 0) || ((year % 4 &#61;&#61; 0) && (year % 100 !&#61; 0));cout <

  • 在C&#43;&#43;中&#xff0c;对于逻辑运算符&&||&#xff01;来说&#xff1a;
    • 参与计算的条件返回值为0&#xff0c;就会被当作假
      • 如果year &#61; 2000是400的倍数&#xff0c;year % 400的结果为0&#xff0c;此时(year % 400)会被当作假
    • 参与计算的条件返回值非0&#xff0c;就会被当作真
      • 如果year &#61; 2001不是400的倍数&#xff0c;year % 400结果为1&#xff0c;此时(year % 400)会被当作真

通过这个特性&#xff0c;用逻辑表达式判断闰年也可以这么写&#xff1a;

判断闰年的程序段&#xff08;二&#xff09;

int year;
cin >> year;
bool is_leap_year;is_leap_year &#61; !(year % 400) || (!(year % 4) && (year % 100));cout <

if 语句


if 基础用法


  • if 基础用法&#xff1a;控制程序在指定条件下执行指定语句。
  • 语法&#xff1a;

if (成立条件表达式) {当条件成立时需要执行的语句
}

  • 语法解析&#xff1a;
    • 成立条件表达式&#xff1a;用圆括号包裹&#xff0c;一般是关系表达式或者逻辑表达式&#xff0c;比如&#xff1a;a, a
    • 如果条件成立&#xff08;成立条件表达式的值为“1或True”&#xff09;&#xff0c;则执行语句&#xff1b;
    • 执行语句可以是一行代码&#xff0c;也可以是多行代码
      • 如果执行语句是多行代码&#xff0c;需要用大括号包裹&#xff1b;
      • 执行语句相比其他语句向右移动一些&#xff0c;就是缩进。读者可以一目了然的知道哪些语句是当条件成立时执行的&#xff0c;可读性更强。

举例&#xff1a;

小键希望用一段代码提醒小戴在下雨时带上伞。

假设天气预报上的降水概率大于40%就表示要下雨&#xff0c;小键需要写一段代码&#xff0c;在输入降水概率后&#xff0c;判断如果要下雨&#xff0c;就输出“请带上伞”。

// 输入一个double类型的变量表示降水概率
double prob_of_precipitation;
cin >> prob_of_precipitation;// 在降水概率大于40%这个条件成立时&#xff0c;需要执行的语句是&#xff1a;输出“请带上伞”。
if (prob_of_precipitation > 0.4)cout <<"请带上伞" <

如果降雨条件成立时&#xff0c;要首先输出降水概率&#xff0c;并且输出“请带上伞”&#xff0c;那么小键就需要在执行语句外加上大括号&#xff1a;

double prob_of_precipitation;
cin >> prob_of_precipitation;
if (prob_of_precipitation > 0.4) {cout <<"降水概率&#xff1a;" <}

if … else 用法


  • if ... else 用法&#xff1a;用来控制程序在指定条件下做事情A&#xff0c;否则做另外去做事情B。
  • 语法&#xff1a;

if (成立条件表达式) {当条件成立时需要执行的语句
} else {当条件不成立时需要执行的语句
}

  • 举例&#xff1a;

我们都知道未成年人不能进入网吧&#xff0c;网吧老板需要小键帮忙写段代码&#xff0c;根据输入的年龄判断是否可以进入网吧。

如果年龄大于等于18&#xff0c;就输出“允许进入”&#xff1b;否则输出“禁止进入”。

// 先输入一个整型表示年龄
int age;
cin >> age;// 判断年龄是否大于等于18&#xff0c;成立的话就输出“允许进入”&#xff1b;不成立就输出“禁止进入”。
if (age >&#61; 18)cout <<"允许进入" <elsecout <<"禁止进入" <

if… else if 用法


  • if ... else if 用法&#xff1a;有些时候&#xff0c;我们会遇到大于两个分支的复杂情况。这时候&#xff0c;我们需要用到 if ... else if 语句&#xff0c;保证在多种情况下&#xff0c;不同条件成立时可以做不同的事情
  • 语法&#xff1a;

if (成立条件表达式1) {当条件1成立时需要执行的语句
} else if (成立条件表达式2) {条件1不成立但是条件2成立时需要执行的语句
} else {当条件1和2都不成立时需要执行的语句
}

  • 语法执行流程&#xff1a;
    • 在条件1成立时进行一些操作&#xff1b;
    • 否则看条件2是否成立&#xff1b;
    • 如果条件2成立&#xff0c;做一些操作&#xff1b;
    • 否则做条件1和2都不成立时需要的操作。
  • 注意点&#xff1a;
    • 成立条件表达式&#xff1a;关系或者逻辑表达式&#xff1b;
    • 最后的一个else&#xff1a;可以没有&#xff0c;你可以选择在条件1和条件2都不成立时&#xff0c;不做任何事情。
  • 举例&#xff1a;

看见小键帮网吧老板的忙&#xff0c;公园售票处也想让小键帮忙写个程序&#xff0c;根据输入的年龄&#xff0c;输出对应的买票政策&#xff1a;如果是老人&#xff0c;就免票&#xff1b;小孩&#xff0c;就半票&#xff1b;否则就全票。

如果我们用年龄对人群做一个划分&#xff0c;假设年龄小于12岁&#xff0c;我们叫小孩&#xff1b;大于等于60岁&#xff0c;我们称之为老人。那么输入年龄&#xff0c;公园售票处该怎么表达对应的操作呢&#xff1f;

// 我们先读入年龄
int age;
cin >> age;// 先判断是否是老人&#xff0c;是的话直接免票
// 如果不是老人&#xff0c;再判断是否是小孩&#xff0c;是的话半票
// 都不是的话&#xff0c;就全票
if (age >&#61; 60)cout <<"免票" <else if (age <12)cout <<"半票" <elsecout <<"全票" <

if… else if 的延伸用法


  • if ... else if 延伸用法&#xff1a;如果情况需要分成不只三种&#xff0c;我们也可以在else后面再接ifelseifelse&#xff0c;依次判断每个条件是否成立&#xff0c;成立就执行对应的操作&#xff0c;否则就判断下一个条件是否成立&#xff1a;

if (成立条件表达式1) {当条件1成立时需要执行的语句
} else if (成立条件表达式2) {否则&#xff0c;当条件2成立时需要执行的语句
} else if (成立条件表达式3) {否则&#xff0c;当条件3成立时需要执行的语句
} ... else if (成立条件表达式n) {否则&#xff0c;当条件n成立时需要执行的语句
} else {当上述所有条件都不成立时需要执行的语句
}

if语句嵌套


  • if 语句嵌套&#xff1a;对于条件成立或者不成立的情况下需要执行的语句里&#xff0c;再嵌入if语句表示新的分支。

Tips&#xff1a;很多时候分支的情况会非常的复杂&#xff1a;当某个条件成立或者不成立时&#xff0c;还需要考虑另一个条件是否成立&#xff0c;根据另一个条件的成立与否再进行分支。这时候&#xff0c;就需要用到if语句的嵌套。


  • 用法&#xff1a;
    • 对于最外层的分支&#xff0c;每个分支需要执行的语句都可以再嵌入分支
    • 嵌入的这个分支可以以任何形式出现&#xff0c;可以是if&#xff0c;可以是if ... else&#xff0c;也可以是if ... else if

举例&#xff1a;假设在条件1成立时&#xff0c;我们要通过条件2再进行分支&#xff0c;就可以这样写&#xff1a;

if (成立条件表达式1) {if (成立条件表达式2) {当条件1和2都成立时需要执行的语句}
} else {当条件1不成立时需要执行的语句
}

  • 注意点1&#xff1a;如果省略大括号&#xff0c;else默认会匹配到最近的那一个if。
    • 举例&#xff1a;如果不加上大括号的话&#xff0c;下面程序会把最后的else和第二个if匹配起来&#xff0c;表达的就不是我们之前说的意思了。

    if (成立条件表达式1)
    if (成立条件表达式2) {当条件1和2都成立时需要执行的语句
    }
    else {
    当条件1不成立时需要执行的语句
    }

  • 注意点2&#xff1a;if语句的嵌套会出现很多的大括号和缩进&#xff0c;大家想想如果有4层以上的嵌套会是什么样的情景&#xff1f;所以为了代码的可读性&#xff0c;尽量避免非必要的多重if语句嵌套。

switch语句

比如聊天机器人需要对不同的情况做出不同的反应&#xff0c;这显然也是一个分支结构。所以我们可以用if语句完成:

// 输入一个字符代表自己的名字
char opt;
cin >> opt;// 根据不同的名字说出不同的话
if (opt &#61;&#61; &#39;6&#39;) {cout <<"主人你好&#xff01;" <}
else if (opt &#61;&#61; &#39;1&#39;) {cout <<"小一你好&#xff01;" <}
else if (opt &#61;&#61; &#39;2&#39;)cout <<"你有什么需要帮助的吗&#xff1f;" <else if (opt &#61;&#61; &#39;4&#39; || opt &#61;&#61; &#39;5&#39;)cout <<"我不想跟你说话。" <elsecout <<"我不太清楚你是谁..." <

可以发现所有表示条件成立的表达式都是一样的形式&#xff1a;opt这个变量是否等于某个值。

针对这种情况&#xff0c;有一种专门的语法&#xff0c;叫做switch语句。


switch 用法


  • switch用于表示这样的分支结构&#xff1a;根据某个变量不同的值进行不同的操作。
  • 语法&#xff1a;

switch (变量名) {case 变量可能的情况1: 执行语句1; break;case 变量可能的情况2: 执行语句2; break;...// 可以有任意数量的 case 语句default: 执行语句n;
}

  • 语法解析
    • switch 后面的变量名&#xff1a;整型变量&#xff08;比如int或者char&#xff09;&#xff0c;或者值为整型的表达式
    • 在一个switch中可以有任意数量的case语句。
    • 每个case后跟一个变量可能的值和一个冒号。这个变量可能的值必须与switch中的变量具有相同的数据类型&#xff0c;而且是一个常量&#xff0c;比如1&#xff0c;2&#xff0c;3或者‘A’&#xff0c;‘B’&#xff0c;‘C’或者‘1’&#xff0c;‘2’&#xff0c;‘3’等等。
    • switch后面的变量等于case后的常量时&#xff0c;case后跟的所有语句将被执行&#xff0c;直到遇到break语句为止。
    • break&#xff08;难点&#xff09;&#xff1a;
      • 当遇到 break 语句时&#xff0c;switch 终止&#xff0c;控制流将跳转到整个 switch 语句后的下一行。
      • case后可以没有break&#xff0c; 如果某个case后没有break语句&#xff0c;程序就会接着往下执行。
        • 举个例子&#xff0c;假设 执行语句1之后没有 break&#xff0c;那么如果变量名 &#61;&#61; 变量可能的情况1时&#xff0c;程序会执行执行语句1&#xff0c;然后接着执行 执行语句2&#xff0c;直到碰到break
    • default&#xff1a;一个switch语句可以有一个可选的default情况&#xff0c;出现在switch的结尾。default情况可用于上面所有case都不为真时执行。
  • 举例&#xff1a;

上一步所说的聊天机器人改写成switch语句是这样的&#xff1a;

char opt;
cin >> opt;switch (opt) {// 如果opt&#61;&#61;&#39;6&#39;&#xff0c;执行完两句cout后&#xff0c;遇见break&#xff0c;就会跳出整个switchcase &#39;6&#39;: cout <<"主人你好&#xff01;" <}

  • Tips&#xff1a;对比这个场景下ifswitch的用法&#xff1a;
    • 如果用if来写会有如下的缺点&#xff1a;
      • 需要很多 opt &#61;&#61; &#39;1&#39; 这样的关系表达式
      • 一个分支下如果有多条语句&#xff0c;就需要加上大括号
    • 相比之下&#xff0c;switch就比较简洁。

推荐阅读
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 本文详细介绍了 GWT 中 PopupPanel 类的 onKeyDownPreview 方法,提供了多个代码示例及应用场景,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • Java 中 Writer flush()方法,示例 ... [详细]
  • 导航栏样式练习:项目实例解析
    本文详细介绍了如何创建一个具有动态效果的导航栏,包括HTML、CSS和JavaScript代码的实现,并附有详细的说明和效果图。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文基于刘洪波老师的《英文词根词缀精讲》,深入探讨了多个重要词根词缀的起源及其相关词汇,帮助读者更好地理解和记忆英语单词。 ... [详细]
  • 数据管理权威指南:《DAMA-DMBOK2 数据管理知识体系》
    本书提供了全面的数据管理职能、术语和最佳实践方法的标准行业解释,构建了数据管理的总体框架,为数据管理的发展奠定了坚实的理论基础。适合各类数据管理专业人士和相关领域的从业人员。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 本文介绍了一款用于自动化部署 Linux 服务的 Bash 脚本。该脚本不仅涵盖了基本的文件复制和目录创建,还处理了系统服务的配置和启动,确保在多种 Linux 发行版上都能顺利运行。 ... [详细]
  • 在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ... [详细]
author-avatar
王强丫ES
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有