热门标签 | 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就比较简洁。

推荐阅读
  • 每日精选Codeforces训练题:1119E(贪心算法)、821C(栈模拟)和645D(拓扑排序)
    题目涉及三种不同类型的算法问题:1119E(贪心算法)、821C(栈模拟)和645D(拓扑排序)。其中,1119E的问题背景是有n种不同长度的棍子,长度分别为2^0, 2^1, …, 2^(n-1),每种棍子的数量为a[i]。任务是计算可以组成的三角形数量。根据三角形的性质,任意两边之和必须大于第三边。该问题可以通过贪心算法高效解决,通过合理选择棍子组合来最大化三角形的数量。 ... [详细]
  • PHP预处理常量详解:如何定义与使用常量 ... [详细]
  • 在Cisco IOS XR系统中,存在提供服务的服务器和使用这些服务的客户端。本文深入探讨了进程与线程状态转换机制,分析了其在系统性能优化中的关键作用,并提出了改进措施,以提高系统的响应速度和资源利用率。通过详细研究状态转换的各个环节,本文为开发人员和系统管理员提供了实用的指导,旨在提升整体系统效率和稳定性。 ... [详细]
  • 在PHP中,高效地分割字符串是一项常见的需求。本文探讨了多种技术,用于在特定字符(如“或”)后进行字符串分割。通过使用正则表达式和内置函数,可以实现更加灵活和高效的字符串处理。例如,可以使用 `preg_split` 函数来实现这一目标,该函数允许指定复杂的分隔符模式,从而提高代码的可读性和性能。此外,文章还介绍了如何优化分割操作以减少内存消耗和提高执行速度。 ... [详细]
  • 题目要求维护一个数列,并支持两种操作:一是查询操作,语法为QL,用于查询数列末尾L个数中的最大值;二是更新操作,用于修改数列中的某个元素。本文通过ST表(Sparse Table)优化查询效率,确保在O(1)时间内完成查询,同时保持较低的预处理时间复杂度。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 本文深入解析了Java面向对象编程的核心概念及其应用,重点探讨了面向对象的三大特性:封装、继承和多态。封装确保了数据的安全性和代码的可维护性;继承支持代码的重用和扩展;多态则增强了程序的灵活性和可扩展性。通过具体示例,文章详细阐述了这些特性在实际开发中的应用和优势。 ... [详细]
  • 具备括号和分数功能的高级四则运算计算器
    本研究基于C语言开发了一款支持括号和分数运算的高级四则运算计算器。该计算器通过模拟手算过程,对每个运算符进行优先级标记,并按优先级从高到低依次执行计算。其中,加减运算的优先级最低,为0。此外,该计算器还支持复杂的分数运算,能够处理包含括号的表达式,提高了计算的准确性和灵活性。 ... [详细]
  • 本文探讨了 Java 中 Pair 类的历史与现状。虽然 Java 标准库中没有内置的 Pair 类,但社区和第三方库提供了多种实现方式,如 Apache Commons 的 Pair 类和 JavaFX 的 javafx.util.Pair 类。这些实现为需要处理成对数据的开发者提供了便利。此外,文章还讨论了为何标准库未包含 Pair 类的原因,以及在现代 Java 开发中使用 Pair 类的最佳实践。 ... [详细]
  • 掌握DSP必备的56个核心问题,我已经将其收藏以备不时之需! ... [详细]
  • 微软发布紧急安全更新,所有Windows 10版本均面临影响!
    微软于周五紧急发布了两项安全更新,旨在解决Windows 10所有版本中Windows Codecs库和Visual Studio Code应用存在的安全隐患。此次更新是继本周初发布的月度例行安全补丁之外的额外措施,凸显了这些问题的紧迫性和重要性。这些漏洞可能被攻击者利用,导致系统权限提升或远程代码执行等严重后果。建议用户尽快安装更新,以确保系统的安全性。 ... [详细]
  • 1网络设备驱动的结构Linux网络设备驱动程序体系结构如下图,从上到下依次划分为4层,依次为网路协议接口层、网络设备接口层,提供实际功能的设备驱动功能层以及网络设备与媒介层。 ... [详细]
  • 大数据环境下的存储系统构建:挑战、方法和趋势
    大数据环境下的存储系统构建:挑战、方法和趋势陈游旻,李飞,舒继武清华大学计算机科学与技术系,北京100084摘要:互联网规模的迅速扩展促使 ... [详细]
  • <!DOCTYPEhtml><html><head><metacharsetutf-8><head&g ... [详细]
  • CCNP交换实验(VLAN/VTP/DHCP)
    实验要求:本拓扑按典型中小企业网分支-总部-分支结构模拟,总部核心路由为C3550,外联网通过OSPF协议,内联网通过VTP ... [详细]
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社区 版权所有