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

推荐阅读
  • 在金融和会计领域,准确无误地填写票据和结算凭证至关重要。这些文件不仅是支付结算和现金收付的重要依据,还直接关系到交易的安全性和准确性。本文介绍了一种使用C语言实现小写金额转换为大写金额的方法,确保数据的标准化和规范化。 ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 本文详细介绍了 GWT 中 PopupPanel 类的 onKeyDownPreview 方法,提供了多个代码示例及应用场景,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • MySQL 数据库迁移指南:从本地到远程及磁盘间迁移
    本文详细介绍了如何在不同场景下进行 MySQL 数据库的迁移,包括从一个硬盘迁移到另一个硬盘、从一台计算机迁移到另一台计算机,以及解决迁移过程中可能遇到的问题。 ... [详细]
  • 网易严选Java开发面试:MySQL索引深度解析
    本文详细记录了网易严选Java开发岗位的面试经验,特别针对MySQL索引相关的技术问题进行了深入探讨。通过本文,读者可以了解面试官常问的索引问题及其背后的原理。 ... [详细]
  • 本文深入探讨了HTTP请求和响应对象的使用,详细介绍了如何通过响应对象向客户端发送数据、处理中文乱码问题以及常见的HTTP状态码。此外,还涵盖了文件下载、请求重定向、请求转发等高级功能。 ... [详细]
  • 本文介绍如何使用 Python 将一个字符串按照指定的行和元素分隔符进行两次拆分,最终将字符串转换为矩阵形式。通过两种不同的方法实现这一功能:一种是使用循环与 split() 方法,另一种是利用列表推导式。 ... [详细]
  • 深入理解OAuth认证机制
    本文介绍了OAuth认证协议的核心概念及其工作原理。OAuth是一种开放标准,旨在为第三方应用提供安全的用户资源访问授权,同时确保用户的账户信息(如用户名和密码)不会暴露给第三方。 ... [详细]
  • Python 异步编程:深入理解 asyncio 库(上)
    本文介绍了 Python 3.4 版本引入的标准库 asyncio,该库为异步 IO 提供了强大的支持。我们将探讨为什么需要 asyncio,以及它如何简化并发编程的复杂性,并详细介绍其核心概念和使用方法。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Søren Kierkegaard famously stated that life can only be understood in retrospect but must be lived moving forward. This perspective delves into the intricate relationship between our lived experiences and our reflections on them. ... [详细]
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社区 版权所有