选择结构

一、布尔值

1、布尔值

布尔值bool是一种数据类型,只能是true 和 false中的一个,表示“真”或"假":

bool isMale = true; cout << isMale; //输出1 cout << boolalpha << isMale; //输出true

在c语言里,数字0表示"假",非0的数字表示"真",可以和bool互相转换。

int isMale = true; //true转换为1 bool b = 3; //3被自动转换为true

### 二、关系运算符

#### 1、关系运算符
用来判断两者关系的运算符,称之为关系运算符,共有:
```c++{.line-numbers}
大于        >
大于等于 >=
小于        <
小于等于 <=
等于        ==
不等于    !=

2、关系表达式

用关系运算符将两个表达式联起来的式子,称为关系表达式,其结果是布尔值,只能是true或者false。

3 > 2   结果是true
3 < 2   结果是 false
5 == 6 结果是false
5 != 6  结果是true
5 <= 6 结果是true

3、变量与关系表达式

判断高智商使用 iq > 140的表达式进行判断,其它例如:

高智商:iq > 140
是否为偶数: n % 2 == 0
是否为负数:n < 0

由于变量可以取不同的值,由变量组成的关系表达式会有不同的结果,例如:

表达式: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<ca <= b < c是三角形的三个边,判断是不是直角三角形,关系表达式用那个什么?aa + bb == c* c

四、if/esle语句

小学举办跳绳比赛,一分钟跳绳次数再200及以上的被评为“跳绳达人”,否则需要“继续努力”。

1、语句格式

状态变量
if (关系表达式)
  语句1;
else
  语句2;

运行说明

  • 语句执行到if一行。
  • 如果状态变量在真集合里,则关系表达式为true,此时执行语句1。
  • 如果状态变量在假集合里,则关系表达式为false,此时执行语句2。

2、else的隐藏表达式

else后面没有写判断表达式,但实际上有一个隐藏的表达式,就是if表达式的求反。

例如: if (n >= 200), else的潜在表达式是 n < 200。

3、语句块

如果在if下面或者else下面有多条语句要执行,需要用{}将语句包括起来,称为语句块。

if (布尔值)
{
    语句1;
    语句2;
    ...
} else
{
   语句3;
   语句4;
}

问题:如果不加{}会怎么样?

五、if嵌套

1、嵌套结构

在if-else的每一个分支代码里面,可以继续嵌套if-else语句,如:

if (布尔值1) //第一层
{
  if (布尔值2) //第二层
  {
     语句1.1
  } else  //第二层
  {
    语句1.2
  }
} else //第一层
{
   ...
}

2、if和else的对应

由于else的隐藏表达式是取if后面表达式的反,如果else和if的对应关系错位,就会导致逻辑错误。

例如:

if (n >= 200)
  if (a % 2 == 0)
    ....;
  else //这里的隐藏表达式是 a % 2 != 0
    .....;

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、用逻辑与(&&)

if (n % 3 == 0 && n % 5 == 0)
  cout << "欧耶欧耶";
else
  cout << "错";

3、逻辑与(&&)

表示两边同时成立

a b a&&b
true true
false false
false true
false
bool b = n >= 3 && n < 100

4、逻辑或(||)

表示两边有一个成立

| a | b | a||b | | ----- | ----- | -------------- | | true | true | true | | true | false | true | | false | true | true | | false | false | false |

bool b = n > 3 || n >= 100

5、逻辑非(!)

a !a
true false
false true

6、扩展理解:集合的概念

  • 关系表达式对应两个集合,真集合和假集合
  • ! 运算符将真集合和假集合反过来:
    • !表达式的真集合为表达式的假集合
    • !表达式的假集合为表达式的真集合
  • && 运算符表示两个真集合的交集
  • || 运算符表示两个真集合的并集

八、逻辑运算高级

1、优先级

运算符的优先级如下:! > 算术 > 关系 > 位 > 逻辑与 > 逻辑或

例如:38妇女节超市计算价格,会员(卡号是4的倍数)或者 购物满200元的女生,均享受8折优惠。

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 ? "偶数": "奇数";