关系与逻辑表达式
关系表达式
- 在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;从而构建逻辑表达式。
- 假设
p1
和p2
是关系表达式的返回结果&#xff0c;逻辑运算符的运算规则可以参考下表&#xff1a;
p1 | p2 | p1&&p2 | p1llp2 | !p1 |
---|
0 | 0 | 0 | 0 | 1 |
0 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | 0 |
1 | 1 | 1 | 1 | 0 |
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 {当条件不成立时需要执行的语句
}
我们都知道未成年人不能进入网吧&#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后面再接if
、else
、if
、else
&#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不成立时需要执行的语句
}
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;对比这个场景下
if
和switch
的用法&#xff1a; - 如果用
if
来写会有如下的缺点&#xff1a; - 需要很多
opt &#61;&#61; &#39;1&#39;
这样的关系表达式 - 一个分支下如果有多条语句&#xff0c;就需要加上大括号
- 相比之下&#xff0c;switch就比较简洁。