第三讲:(一)分支结构和操作符

C语⾔是结构化的程序设计语⾔,这⾥的结构指的是顺序结构、选择结构、循环结构。
这里讲的是选择结构和循环结构的使用。
在C语言中,我们可以使⽤ ifswitch 实现分⽀结构,使⽤ for whiledo while 实现循环结构。

1.if介绍

1.1 if语句使用方法

if语句的语法形式如下:

	if(表达式)
		语句

我们前面说过,在C语言中,0为假,非0为真,
if语句中表达式为非零(真),则语句执行,表达式结果为0(假),则语句不执行。
**例子:**输入一个整数,判断是否为奇数。

#include <stdio.h>

int main()
{
	int a = 0;
	scanf("%d", &a);
	if (a % 2 == 1)
	{
		printf("%d是奇数\n", a);
	}
	return 0;
}

我们输入一个数 5 ,它的输出结果为:
在这里插入图片描述
if语句的流程图如下:

Alt
从上面的if语句中我们可以画出奇数判断的流程图:
在这里插入图片描述

1.2 else语句

如果⼀个数不是奇数,那就是偶数了,如果任意⼀个整数,我们要清楚的判断是奇数还是偶数怎么表示呢?
这⾥就需要 if…else… 语句了,语法形式如下:

	if(表达式)
		语句1
	else
		语句2

**例子:**输入一个整数,判断是否为奇数,如果是奇数打印奇数 ,否则打印偶数。

#include <stdio.h>
int main()
{
	int a = 0;
	scanf("%d", &a);
	if (a % 2 == 1)
	{
		printf("%d为奇数", a);
	}
	else
	{
		printf("%d是偶数", a);
	}
	return 0;
}

运行结果如下:
在这里插入图片描述
在这里插入图片描述

下面我们做一个练习:输⼊⼀个年龄,>= 18岁就输出:成年,否则就输出:未成年

#include <stdio.h>
int main()
{
	int age = 0;
	scanf("%d", &age);
	if (age >= 18)
	{
		printf("成年");
	}
	else
	{
		printf("未成年");
	}
	return 0;
}

1.3分支中包含多条语句

上面的代码中,我们在ifelse语句都加上了大括号{},这么做的原因除了为了容易阅读代码以外,还有另一个原因就是ifelse语句默认都只控制一条语句,比如:

#include <stdio.h>

int main()
{
	int age = 0;
	scanf("%d", &age);
	if (age >= 18)
		printf("成年了\n");
		printf("可以谈恋爱了\n");
	return 0;
}

上面的代码,你会发现输⼊的值不管是>=18 还是⼩于18,“可以谈恋爱了” 都会打印在屏幕上。
在这里插入图片描述
在这里插入图片描述
这是因为 if 语句只能控制⼀条语句,就是 printf(“成年了\n”);if语句为真,则打印成年了if语句为假,则不打印,而 printf(“可以谈恋爱了\n”); 是独立存在的,它是不受 if语句控制的,不管if语句的条件的真假,都会被执行。那如果我们要if语句同时控制2条以上的语句,怎么办呢?那就要使⽤ {} 将代码括起来,else 后也可以跟上⼤括号。

#include <stdio.h>

int main()
{
	int age = 0;
	scanf("%d", &age);
	if (age >= 18)
	{
		printf("成年了\n");
		printf("可以谈恋爱了\n");
	}
	return 0;
}

运行结果如下:
在这里插入图片描述
else使用示例:

#include <stdio.h>

int main()
{
	int age = 0;
	scanf("%d", &age);
	if (age >= 18)
	{
		printf("成年了\n");
		printf("可以谈恋爱了\n");
	}
	else
	{
		printf("未成年\n");
		printf("不可以谈恋爱了\n");
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述

1.4 嵌套if

if…else语句中,else可以与另一个if语句连用,构成多重判断。
比如:要求输⼊⼀个整数,判断输⼊的整数是0,还是正数或者负数。请看如下代码:

#include <stdio.h>

int main()
{
	int num = 0;
	scanf("%d", &num);
	if (num == 0)
	{
		printf("输入的数是0");
	}
	else if (num > 0)
	{
		printf("输入的数是正数");
	}
	else
	{
		printf("输入的数是负数");
	}
	return 0;
}

上面代码中,第一个else后面跟随的if语句就是嵌套在了else语句中的,构成嵌套的if语句。
再比如:
输⼊⼀个整数,如果是正数,再判断是奇数还是偶数,并输出;如果不是正数则输出:负数。

#include <stdio.h>

int main()
{
	int num = 0;
	scanf("%d", &num);
	if (num == 0)
	{
		printf("输入的数是0");
	}
	else if (num > 0)
	{
		if (num % 2 == 1)
		{
			printf("输入的数是奇数");
		}
		else
		{
			printf("输入的数是偶数");
		}
	}
	else
	{
		printf("输入的数是负数");
	}
	return 0;
}

上面代码中的奇偶数判断就是嵌套在正数判断的if语句中的,构成嵌套的if语句。
以上就是嵌套if语句的语法,有了嵌套if语句,就可以完成更多复杂逻辑的判断。
下面我们做一个练习:
输⼊⼀个⼈的年龄

1 如果年龄<18岁,打印"少年"
2 如果年龄在18岁⾄44岁打印"⻘年"
3 如果年龄在45岁⾄59岁打印"中⽼年"
4 如果年龄在60岁⾄89岁打印"⽼年"
5 如果90岁以上打印"⽼寿星"

参考代码如下;

#include <stdio.h>

int main()
{
	int num = 0;
	scanf("%d", &num);
	if (num < 18)
	{
		printf("少年\n");
	}
	else if(num < 45)
	{
		printf("青年\n");
	}
	else if (num < 60)
	{
		printf("中老年\n");
	}
	else if (num < 90)
	{
		printf("中老年\n");
	}
	else {
		printf("老寿星\n");
	}
	return 0;
}

1.5悬空else问题

下面我们看一个代码:

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 2;
	if (a == 1)
		if (b == 2)
			printf("hehe\n");
	else
		printf("haha\n");
	return 0;
}

大家可以思考一下上面的代码运行的结果是什么?
对于初学者来说,上来判断 a 是 0,不等于 1 ,那就执⾏ else ⼦句,打印 haha。
但是结果却是什么都不打印。
在这里插入图片描述

为什么会这样呢?
这就是悬空else的问题,在C语言中,如果有多个ifelse,可以记住这样⼀条规则,else总是跟最接近的if匹配。
上面的代码因为排版的问题,让我们误认为else是和第一个if相对应的,所以在判断a == 1这句代码时,条件为假,而else语句此时和第一个if对齐的,让我们自然而然的就认为会输出hah
如果改成下面这样我们就容易理解为何会这样了:

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 2;
	if (a == 1)
		if (b == 2)
			printf("hehe\n");
		else
			printf("haha\n");
	return 0;
}

或者如果我们希望else确实和第⼀个if匹配,可以这样修改代码:

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 2;
	if (a == 1)
	{
		if (b == 2)
			printf("hehe\n");
	}
	else
	{
		printf("haha\n");
	}
	return 0;
}

只要带上适当的大括号,代码的逻辑就会更加的清晰,所以⼤家以后在写代码的时候要注意括号的使用,让代码的可读性更高。

2.关系操作符

C 语⾔用于比较的表达式,称为 “关系表达式”(relational expression),里面使⽤的运算符就称
为“关系运算符”(relational operator),主要有下⾯6个。

  • >:大于运算符
  • <:小于运算符
  • >=:大于等于运算符
  • <=:小于等于运算符
  • ==:相等运算符,这里要注意,它和 =是两个不一样的运算符,不能混淆。
  • !=:不等于运算符

下面是一些例子。

1 a == b;
2 a != b;
3 a < b;
4 a > b;
5 a <= b;
6 a >= b;

关系表达式通常返回01,表达真假。
C 语⾔中, 0 表示假,所有非零值表示真。比如, 20 > 12 返回 1 12 > 20 返回 0
而这些关系运算符经常用在判断语句if或循环语句while中。

关系操作符介绍中说过,===是不一样的,它是两个意义的符号,如果有时候不小心写错了,虽然是能运行的,但是结果却是想象不到的。例如:

if(x = 3) 

上面的代码实际情况是 把数值3赋予给变量x,虽然我们想表达的意思是判断x的值是否和3相等,但是由于种种原因导致我们少输入了一个=。因此这行代码它的返回值为3,我们说过非零为真,所以if这里会始终为真,转而运行下面代码。
为了防止出现这种错误,我们可以将变量卸载等号的右边。

if(3 == x) 

像上面这种写法,如果我们把==误写成=,编译器就会报错。
还有一个初学者需要避免的错误是:**多个关系运算符不能连用。**如下所示:

 i < j <k

上面的示例中,连续使用两个小于运算符,这个表达式在编译器中是合法的,不会报错,但是它运行后的结果却不是我们想要的变量j大于i小于k的结果.
它实际的运行结果是按照下面的方式运行的:
在这里插入图片描述
如果想要判断变量j的值是否在ij之间,应该使用下面的写法。

	i < j && j < k

3.条件操作符

条件操作符也叫做三目操作符,需要接收三个操作数的操作符,也是唯一一个三木操作符。形式如下。

	exp1 ? exp2 : exp3

上面的代码中exp的意思是表达式。
条件操作符的计算逻辑是:如果 exp1为真, exp2 计算,计算的结果是整个表达式的结果;如果exp1 为假, exp3 计算,计算的结果是整个表达式的结果。可以根据流程图理解为:
在这里插入图片描述
下面做个练习:使⽤条件操作符表示下⾯代码的逻辑

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	if (a > 5)
		b = 3;
	else
		b = -3;
	printf("%d\n", b);
	return 0;
}

改造后

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	b = a > 5 ? 3 : -3;
	printf("%d\n", b);
	return 0;
}

第二个练习:使用条件表达式找出两个数值的最大值

#include <stdio.h>

int main()
{
	int a = 0;
	int b = 0;
	scanf("%d%d", &a, &b);
	int max = a > b ? a : b;
	printf("最大值是%d\n",max);
	return 0;
}

我们看下运行情况:
在这里插入图片描述

4.逻辑 操作符: && , || , !

逻辑运算符主要是用来逻辑判断的功能,用于比较复杂的表达式,常用的逻辑操作符有以下三个:

  • !:逻辑取反
  • && :逻辑与
  • || :逻辑或

4.1逻辑取反运算符 !

逻辑取反运算符,就是改变单个表达式的真假,如下如所示,当a为真时,那么!a则为假,相反的,当a为假时,那么!a则为真。
在这里插入图片描述
注:C语言中,非零表示为真,0表示为假。
举例:有一个变量flag,如果flag为假,就输出do something。

#include <stdio.h>
#include <stdbool.h>

int main()
{
	bool flag = false;
	if (!flag)
	{
		printf("do something\n");
	}
	return 0;
}

上面代码中,我们赋予变量flag为布尔型,值为假。根据if语句的运行规则,当里面的表达式为真时,执行其中的语句,而此时flag的值为假,那么!flag的值就为真,运行结果如下所示:
在这里插入图片描述

4.2逻辑与运算符 &&

逻辑与的表现形式如下表格所示:
在这里插入图片描述
注:C语言中,非零表示为真,0表示为假。
&& 的意思是并且的意思,&& 是一个双目操作符,使用的方式为a&&b
&& 两边的表达式都是真的时候,整个表达式的值才为真,只要a或者b中有一个是假,那么整个表达式的值就是假。
举例说明:3月到5月是春天,其代码如下,

#include <stdio.h>

int main()
{
	int month = 0;
	scanf("%d", &month);
	if (month > 3 && month < 5)
	{
		printf("春天\n");
	}
	return 0;
}

运行结果如下:
在这里插入图片描述
这⾥表达的意思就是month既要⼤于等于3,⼜要⼩于等于5,必须同时满⾜。

4.3 逻辑或运算符 ||

逻辑或的表现形式如下表格所示:
在这里插入图片描述
注:C语言中,非零表示为真,0表示为假。
|| 就是或运算符,也就是或者的意思, || 也是一个双目操作符,使用的方式是 a || b , || 两边的表达式只要有一个是真的,整个表达式就是真,两边的表达式都为假的时候,才为假。
⽐如:我们说⼀年中⽉份是12⽉或者1⽉或者2⽉是冬天,那么我们怎么使⽤代码体现呢?

#include <stdio.h>

int main()
{
	int month = 0;
	scanf("%d", &month);
	if (month ==1 || month == 2 || month == 12)
	{
		printf("冬天\n");
	}
	else {
		printf("不是冬天\n");
	}
	return 0;
}

运行结果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.4逻辑运算符练习

输⼊⼀个年份year,判断year是否是闰年。
闰年判断的规则:

  1. 能被4整除并且不能被100整除是闰年
  2. 能被400整除是闰年

代码1:

#include <stdio.h>

int main()
{
	int year = 0;
	scanf("%d", &year);
	if (year % 4 == 0 && year % 100 != 0)
	{
		printf("是闰年\n");
	}
	else if (year % 400 == 0)
	{
		printf("是闰年\n");
	}
	return 0;
}

代码2:

#include <stdio.h>

int main()
{
	int year = 0;
	scanf("%d", &year);
	if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
	{
		printf("是闰年\n");
	}
	return 0;
}

4.5短路

C语⾔逻辑运算符还有⼀个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是
保证的。
如果左边的表达式满⾜逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为“短路”。
如前面的代码:

if(month > 3 && month < 5)

表达式中&& 的左操作数是 month > 3 ,右操作数是 month < 5 ,当左操作数 month > 3 的结果是假的时候,即使不判断 month < 5 ,整个表达式的结果也是假(值为0),不是春季。
所以,对于&&操作符来说,左边操作数的结果为假的时候,右边操作数就不再执⾏。

对于||操作符又是什么情况呢?我们结合前面的阿代码:

if (month ==1 || month == 2 || month == 12)

如果month == 1,则不⽤再判断month是否等于1或者12,整个表达式的结果也是1(是冬季)。
所以, || 操作符的左操作数的结果不为0时,就⽆需执行右操作数。

像这种仅仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进行计算的运算称为短路求值。
关于短路详细解读,请参考这里:C语言中的短路求值介绍

5.switch语句

除了if语句外,C语言中还提供了switch语句来实现分支结构。
switch语句时一种特殊形式的if…else结构,用于判断条件有多个结果的情况,它把多重的elseif语句变成更易用、可读性更好的形式。
使用方法如下:

switch (表达式) 
	{
		 case1: 语句
		 case2: 语句
		 ........
		 default: 语句
	}

上面代码中,根据表达式不同的值,执⾏相应的 case 分⽀。如果找不到对应的值,就执⾏ default 分⽀。
需要注意的是:
1 switch 后的表达式必须是整型表达式
2 case后的值,必须是整形常量表达式

5.1 if语句和switch语句的对比

练习:输入一个整数,判断是星期几。
如果用if语句完成,它的代码如下:

#include <stdio.h>

int main()
{
	int week = 0;
	scanf("%d", &week);
	if (week == 1)
	{
		printf("星期一\n");
	}else if(week == 2)
	{
		printf("星期二\n");
	}
	else if (week == 3)
	{
		printf("星期三\n");
	}
	else if (week == 4)
	{
		printf("星期四\n");
	}
	else if (week == 5)
	{
		printf("星期五\n");
	}
	else if (week == 6)
	{
		printf("星期六\n");
	}
	else if (week == 7)
	{
		printf("星期天\n");
	}
	return 0;
}

如果使⽤switch语句改写,就可以是这样的:

#include <stdio.h>

int main()
{
	int week = 0;
	scanf("%d", &week);
	switch (week)
	{
	case 1:
		printf("星期一\n");
		break;
	case 2:
		printf("星期二\n");
		break;
	case 3:
		printf("星期三\n");
		break;
	case 4:
		printf("星期四\n");
		break;
	case 5:
		printf("星期五\n");
		break;
	case 6:
		printf("星期六\n");
		break;
	case 7:
		printf("星期天\n");
		break;
	}
	return 0;
}

注意
1.case 和后边的数字之间必须有空格
2. 每⼀个 case 语句中的代码执⾏完成后,需要加上 break ,才能跳出这个switch语句。

5.2 switch语句中的break

前⾯的代码中,如果我们去掉case语句中的break,会出现什么情况呢?
我们修改下:

#include <stdio.h>

int main()
{
	int week = 0;
	scanf("%d", &week);
	switch (week)
	{
	case 1:
		printf("星期一\n");
	case 2:
		printf("星期二\n");
	case 3:
		printf("星期三\n");
	case 4:
		printf("星期四\n");
	case 5:
		printf("星期五\n");
	case 6:
		printf("星期六\n");
	case 7:
		printf("星期天\n");
	}

	return 0;
}

运行上面代码,测试结果如下:
在这里插入图片描述
出问题了,怎么星期六星期天也被打印出来了,为什么呢?
原因是switch语句也是分⽀效果的,只有在switch语句中使⽤ break才能在跳出switch 语句,如果某⼀个 case 语句的后边没有 break 语句,代码会继续往下执⾏,有可能执⾏其他 case语句中的代码,直到遇到 break语句或者 switch 语句结束。就比如上⾯的代码就执⾏了 case 6 case 7中的语句。
所以在switch语句中 break语句是⾮常重要的,能实现真正的分⽀效果。
当然, break也不是每个 case语句都得有,这就得根据实际情况来看了。

比如下面这题:

  1. 输⼊1-5,输出的是“⼯作⽇”;
  2. 输⼊6-7,输出“休息⽇”。
#include <stdio.h>

int main()
{
 int day = 0;
 scanf("%d", &day);
 
 switch(day)
 {
	 case 1case 2:
	 case 3:
	 case 4:
	 case 5:
	 	printf("⼯作⽇\n");
	 	break;
	 case 6:
	 case 7:
		 printf("休息⽇\n");
		 break;
 }
 return 0;
}

上⾯的练习中,我们发现应该根据实际的情况,来在代码中觉得是否使⽤ break ,或者在哪⾥使⽤
break,才能正确完成实际的需求。

5.3 switch语句中的default

在第一段判断星期几的代码中,用户可能会输入其他数值,比如输入8,但是8在我们的代码中无法匹配case语句的值,这时候我们要么不做处理,要不就要在switch语句中加入default子句。

switch (表达式) 
	{
		 case1: 语句
		 case2: 语句
		 ........
		 default: 语句
	}

switch 后边的表达式的结果不是 值1 ,也不是 值2 的时候,就会执⾏default 后面的语句。
我们把打印星期的代码修改如下:

int main()
{
	int week = 0;
	scanf("%d", &week);
	switch (week)
	{
	case 1:
		printf("星期一\n");
	case 2:
		printf("星期二\n");
	case 3:
		printf("星期三\n");
	case 4:
		printf("星期四\n");
	case 5:
		printf("星期五\n");
	case 6:
		printf("星期六\n");
	case 7:
		printf("星期天\n");
	default: 
		printf("输入错误,退出\n");
	}
	return 0;
}

运行结果:
在这里插入图片描述

5.4 switch语句中的case和default的顺序问题

switch语句中case⼦句和default⼦句有要求顺序吗?default只能放在最后吗?
其实,在switch语句中case语句和default语句是没有顺序要求的,只要你的顺序是满⾜实际需求的就可以。
不过通常情况下都是把default⼦句放在最后处理的,这样更有助于代码的阅读。

本博客只为学习使用,如有错误请大家指出,感谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值