# 选择结构 --- ### 一、布尔值 --- #### 1、布尔值 布尔值bool是一种数据类型,只能是true 和 false中的一个,表示“真”或"假": ```c++ bool isMale = true; cout << isMale; //输出1 cout << boolalpha << isMale; //输出true ``` --- 在c语言里,数字0表示"假",非0的数字表示"真",可以和bool互相转换。 ```c++ int isMale = true; //true转换为1 bool b = 3; //3被自动转换为true ``` --- ### 二、关系运算符 #### 1、关系运算符 用来判断两者关系的运算符,称之为关系运算符,共有: ```c++{.line-numbers} 大于 > 大于等于 >= 小于 < 小于等于 <= 等于 == 不等于 != ``` --- #### 2、关系表达式 用关系运算符将两个表达式联起来的式子,称为关系表达式,其结果是布尔值,只能是true或者false。 ```c++ 3 > 2 结果是true 3 < 2 结果是 false 5 == 6 结果是false 5 != 6 结果是true 5 <= 6 结果是true ``` --- #### 3、变量与关系表达式 判断高智商使用 iq > 140的表达式进行判断,其它例如: ```c++ 高智商:iq > 140 是否为偶数: n % 2 == 0 是否为负数:n < 0 ``` --- 由于变量可以取不同的值,由变量组成的关系表达式会有不同的结果,例如: ```c++ 表达式:n % 2 == 0 n 为 2,表达式结果为true n 为 3,表达式结果为false ``` 实际上,这个关系表达式表示了两类数值: * 一类数值(所有偶数2,4,6,8...)输入到表达式,结果为true。 * 另一类数值(所有奇数1,3,5,7...)输入到表达式,结果为false。 --- ### 三、if语句 法国心理学家比奈设计了一组试题进行智商检测,分数越高表示智商越高,他将一般人的平均智商定为100,140以上者称为天才。 --- #### 1、if语句 ``` 状态变量 if (关系表达式) 语句1; 后续语句; ``` `运行说明`: * 程序运行到if语句一行。 * 判断关系表达式的值(要根据当下状态变量的值),如果为true则执行语句1,否则跳过语句1。 * 继续执行后续语句。 --- #### 2、设计关系表达式 用if语句实现分支结构,重要的是要根据题目的要求,设计出关系表达式,以便区分状态变量的值。 --- 例如:如果智商超过140,输出"天才"。 * 看题目,状态要分成两类:真集合智商超过140,假集合不超过。 * 关系表达式:iq > 140 --- 又如:如果智商不及格,输出"不及格"。 * 看题目,状态要分成两类:真集合智商小于100,假集合超过100。 * 关系表达式:iq < 100 --- `问题`: 1. 如果成绩录入超过100分说明录入错误,关系表达式用什么? 2. 假设a比b大,判断a是b的倍数,关系表达式用什么?`a%b == 0` 3. 假设$a <= b < c$是三角形的三个边,判断是不是直角三角形,关系表达式用那个什么? $a * a + b * b == c * c$ --- ### 四、if/esle语句 小学举办跳绳比赛,一分钟跳绳次数再200及以上的被评为“跳绳达人”,否则需要“继续努力”。 --- #### 1、语句格式 ```c++ 状态变量 if (关系表达式) 语句1; else 语句2; ``` --- `运行说明`: * 语句执行到if一行。 * 如果状态变量在真集合里,则关系表达式为true,此时执行语句1。 * 如果状态变量在假集合里,则关系表达式为false,此时执行语句2。 --- #### 2、else的隐藏表达式 else后面没有写判断表达式,但实际上有一个隐藏的表达式,就是if表达式的求反。 例如: if (n >= 200), else的潜在表达式是 n < 200。 --- #### 3、语句块 如果在if下面或者else下面有多条语句要执行,需要用{}将语句包括起来,称为语句块。 ```c++ if (布尔值) { 语句1; 语句2; ... } else { 语句3; 语句4; } ``` --- 问题:如果不加{}会怎么样? --- ### 五、if嵌套 --- #### 1、嵌套结构 在if-else的每一个分支代码里面,可以继续嵌套if-else语句,如: ```c++ if (布尔值1) //第一层 { if (布尔值2) //第二层 { 语句1.1 } else //第二层 { 语句1.2 } } else //第一层 { ... } ``` --- #### 2、if和else的对应 由于else的隐藏表达式是取if后面表达式的反,如果else和if的对应关系错位,就会导致逻辑错误。 --- 例如: ```c++ if (n >= 200) if (a % 2 == 0) ....; else //这里的隐藏表达式是 a % 2 != 0 .....; ``` 和 ```c++ if (n >= 200) { if (a % 2 == 0) ....; } else //这里的隐藏表达式是 n < 200 .....; ``` --- 在编写多重if嵌套结构的时候,一定要注意if和else的对应关系,特别在括号和缩进两方面都要小心。 --- ### 六、if-else if 多分支 #### 1、else if else if是else里if嵌套的简化,一般用来表示多种选择的情况,例如: * 大于 0 是正数 * 小于 0 是负数 * 还有一个是0 ``` if (n > 0) 正数; else if (n < 0) 负数 else 零 ``` `else if可以很多个,没有限制` --- #### 2、理解 if ... else if .... else的结构,表示的是一种区间结构,例如: ``` if (n % 10 == 0) 语句1 else if ( n % 3 == 0) //隐藏表达式: n % 10 != 0 语句2 else //隐藏表达式: n % 10 != 0 && n % 3 != 0 语句3 ``` 理解: * 第一个if:n % 10 == 0的真集合, 例如20、 30。 * else if:在n % 10 == 0的假集合(不被10整除)里,再找出n % 3 == 0的真集合(被3整除),例如12、 15。 * else:既不被10整除,又不被3整除,例如11、7。 --- #### 3、表达式顺序 表达式的顺序要注意不能搞错。例如: ``` if (s >= 90) cout << "奖励iphone"; else if (s > 100) cout << "输入错误" ``` 这样写是错误的,由于else的隐藏表达式是 s < 90,与s > 100冲突。 --- 正确的写法应该是: ``` if (s > 100) cout << "输入错误"; else if (s >= 90) cout << "奖励iphone"; ``` --- ### 七、逻辑运算 小明和小花玩报数游戏,如小明报数是3和5的公倍数,小花就要说“欧耶欧耶”,否则输出"错"。 --- #### 1、用嵌套if ``` if (n % 3 == 0) if (n % 5 == 0) cout << "欧耶欧耶"; ``` 这样写有什么问题吗? 输出“错”的代码怎么写? --- 要用到两个else: ``` if (n % 3 == 0) { if (n % 5 == 0) cout << "欧耶欧耶"; else cout << "错"; } else cout << "错"; ``` --- #### 2、用逻辑与(&&) ```c++ if (n % 3 == 0 && n % 5 == 0) cout << "欧耶欧耶"; else cout << "错"; ``` --- #### 3、逻辑与(&&) 表示两边同时成立 | a | b | a&&b | | ----- | ----- | ----- | | true | true | true | | true | false | false | | false | true | false | | false | false | false | ``` bool b = n >= 3 && n < 100 ``` --- #### 4、逻辑或(||) 表示两边有一个成立 | a | b | a\|\|b | | ----- | ----- | -------------- | | true | true | true | | true | false | true | | false | true | true | | false | false | false | ```c++ bool b = n > 3 || n >= 100 ``` --- #### 5、逻辑非(!) | a | !a | | ----- | ----- | | true | false | | false | true | --- #### 6、扩展理解:集合的概念 * 关系表达式对应两个集合,真集合和假集合 * ! 运算符将真集合和假集合反过来: - !表达式的真集合为表达式的假集合 - !表达式的假集合为表达式的真集合 * && 运算符表示两个真集合的交集 * || 运算符表示两个真集合的并集 --- ### 八、逻辑运算高级 #### 1、优先级 运算符的优先级如下:! > 算术 > 关系 > 位 > 逻辑与 > 逻辑或 例如:38妇女节超市计算价格,会员(卡号是4的倍数)或者 购物满200元的女生,均享受8折优惠。 ```c++ int no, money, pct = 1; bool isMale; ...... if (no % 4 == 0 || ! isMale && money >= 200) pct = 0.8; ``` --- #### 2、复杂表达式解析 当表达式由多个运算符组成时: * 按照括号拆解子表达式。 * 从左到右,按照优先级拆解子表达式: 例如- no % 4 == 0 || !male && money >= 200: ``` 1. no % 4 == 0: 判断是不是会员 2. ! isMale: 判断是否女生(当isMale为假时,此表达式为真) 3. money >= 200: 判断购物满200 4. ! isMale && money >= 200: 判断购物满200的女生 5. no % 4 == 0 || !male && money >= 200: 判断会员 或者 购物满200的女生 ``` --- #### 3、扩展理解 #### 3.1、表达式的值 任何表达式都有值,其中 * 算术表达式:值即运算结果,如1+3的值是4 * 关系表达式:值即比较结果,如1<=3的值是true * 赋值表达式:值即赋值完成以后的左值,如a=5的值是5,而a=i++的值是自增前的i --- #### 3.2、短路(可选) 逻辑与和逻辑或都具备一个特性叫短路性,从左到右如果第一个条件的真假足够获得结果,则第二个表达式就不进行运算了。 原因: ``` b1 && b2:如果b1是false,则不管b2是true还是false,结果都是false b1 || b2:如果b1是true,则不管b2是true还是false,结果都是true ``` --- 假如第二个表达式是进行运算的(如自增),不进行运算也就意味着自增不产生效果,例如: ``` int i = 0; 1 > 2 && i++; 由于1 > 2是false,所以后面的i++没有进行运算,到这一行时i 还是为0 ``` --- ### 九、条件表达式 #### 1、表达式形态(三元运算符) ``` 条件 ? 值1: 值2 ``` 如果条件为真,则结果为值1, 否则结果为值2。 --- #### 2、应用场景 条件表达式一般用于赋值,把表达式的结果赋值给某个变量,例如: ``` string s = age >= 100 ? "长寿": "普通"; ``` --- #### 3、用if实现同等效果 如果不使用条件表达式,而使用if,则语句会更多。 例如以下: ``` string s; if (age >= 100) s = "长寿"; else s = "普通"; ``` 或者: ``` string s = "普通"; if (age >= 100) s = "长寿"; ``` --- #### 4、应用条件表达式 把题目理解成: 有一个条件,根据条件使用两个值的其中一个。 例如: * 返回值是两个之一吗? 是,偶数 或 奇数 * 条件是什么? n % 2 == 0 于是,条件表达式: n % 2 == 0 ? "偶数": "奇数"; --- ## 习题