C语言程序设计学习笔记:P3-判断

本系列博客用于记录学习浙江大学翁恺老师的C语言程序设计,系列笔记链接如下:
C语言程序设计学习笔记:P1-程序设计与C语言
C语言程序设计学习笔记:P2-计算
C语言程序设计学习笔记:P3-判断
C语言程序设计学习笔记:P4-循环
C语言程序设计学习笔记:P5-循环控制
C语言程序设计学习笔记:P6-数据类型
C语言程序设计学习笔记:P7-函数
C语言程序设计学习笔记:P8-数组
C语言程序设计学习笔记:P9-指针
C语言程序设计学习笔记:P10-字符串
C语言程序设计学习笔记:P11-结构类型
C语言程序设计学习笔记:P12-程序结构
C语言程序设计学习笔记:P13-文件
C语言程序设计学习笔记:P14-链表


一、判断

1.1 做判断

问题

问题引出: 上篇博客我们有一个例子,计算两个时间的差值。我们知道,如果直接将时间的小时和分钟分别相减,会出现分钟借位的情况:如1点40分和2点10分的差。针对这种情况,上篇博客我们的处理方案是将两个时间转为分钟,然后进行整数的相减。但是现在我就想用分别相减的方案,该怎么做呢?
解决方案: 这时我们会想,能不能判断出当前是否需要进行分钟的借位?如果需要借位,我们就做出相应的调整。于是,我们写出相应的代码如下所示:

代码实现

#include <stdio.h>

int main()
{
	int hour1, minute1;
	int hour2, minute2;
	scanf_s("%d %d", &hour1, &minute1);
	scanf_s("%d %d", &hour2, &minute2);

	int ih = hour2 - hour1;
	int im = minute2 - minute1;
	if (im < 0) {
		im = 60 + im;
		ih--;
	}
	printf("时间差是%d小时%d分。\n", ih, im);
	return 0;
}

运行结果

在这段代码中,我们用了C语言中的条件判断。这里我们用的是if,如果im<0,那么说明分钟数进行减法运算时发生了借位。那么我们要将im加上60,给它补回去,同时让ih减1。如果im>=0,则不进行以上操作。我们运行一下,进行测试,可以看出结果正确。
在这里插入图片描述


if语句的作用

在程序执行过程中,这个if语句究竟如何起作用的呢?我们不妨设断点来查看一下。我们首先在if语句那一行设置一个断点,然后单步调试执行。
在这里插入图片描述
由于断点之前有两个scanf,所以我们首先需要输入两个时间。
在这里插入图片描述
此时我们可以看出各个im和ih的值已经计算出来了,而im的值小于0。
在这里插入图片描述
然后我们继续单步调试,使代码继续运行两行。此时我们可以看出if语句中的操作已经执行了,im和ih已经得到正确的值。
在这里插入图片描述
我们再次测试不用借位的情况,计算11点40和10点20的差值。此时各个变量的值如下所示。
在这里插入图片描述
我们再次向下调试一行,发现直接跳过if语句。
在这里插入图片描述
因此,if的使用原理就是:
if ( 条件成立 ) {

}

如果条件成立,则执行大括号里面的所有内容。如果不成立,则不执行大括号里面的内容。


1.2 判断的条件

在上面的代码中,我们在if语句的那个括号内使用了一个小于(<)符号,用来计算两个值之间的关系,所以这种运算符叫做关系运算符。C语言的关系运算符如下表所示:

运算符意义
==相等
!=不相等
>大于
>=大于或等于
<小于
<=小于或等于

注: 切记,=符号是赋值,==才是判断是否相等。


示例

关系运算符的结果只有两个:0和1。如果这个关系成立,就是1。如果这个关系不成立,就是0。我们来看以下三个例子:
在这里插入图片描述
运行,可以看出结果正确。
在这里插入图片描述


关系运算符的优先级

既然关系运算符也是运算符,那么我们上篇博客说过,运算符都是有优先级的。所有的关系运算符的优先级比算术运算的低,但是比赋值运算的高。举例如下:
7 >= 3 + 4 首先计算3+4的值,然后判断7 >= 7,结果为1。
int r = a>0; 首先计算a>0的结果(1或0),然后将结果赋值给r。
而在所有的关系运算符中,他们的优先级也不是相同的。判断是否相等的==!=的优先级比其他的低,同时连续的关系运算是从左到右进行的。举例如下:
5 > 3 == 6 > 4 这是在判断5>3和6>4的结果是否相等。
6 > 5 > 4 首先计算6>5的结果为1,然后计算1>4的结果为0。最终结果为0
a == b == 6 首先计算a==b的结果,然后计算其结果与6是否相等。最终结果一定为0
a == b > 0 首先判断b是否大于0,然后判断a是否等于b>0的结果。


1.3 找零计算器

示例:

上篇博客我们写过一个计算找零的代码,现在我们将其完善一下。找零计算器需要用户做两个操作:输入购买的金额,输入支付的票面,而找零计算器则根据用户的输入做出相应的动作:计算并打印找零,或告知用户余额不足以购买。从计算机程序的角度看,这就是意味着程序需要读用户的两个输入,然后进行一些计算和判断,最后输出结果。

基础代码实现

#include <stdio.h>

int main()
{
	//	初始化
	int price = 0;
	int bill = 0;
	//	读入金额和票面
	printf("请输入金额:");
	scanf("%d", &price);
	printf("请输入票面:");
	scanf("%d", &bill);
	//	计算找零
	printf("应该找您:%d\n", bill - price);

	return 0;
}

注释

在这段代码中,我们以两个斜杠//开头的语句把程序分成了三个部分:
1、初始化
2、读入金额和票面
3、计算并打印找零

----这样开头的东西我们叫做注释(comment)。注释插入在程序代码中,用来向读者提供解释信息。它们对于程序的功能没有任何影响,但是往往能使得程序更容易被人类读者理解。
----两个斜杠符号//开头的只能注释单行,我们还有注释多行的符号:/* */。多行注释由一对字符序列/*开始,而以*/结束。用法实例如下:

多行注释符号用法

/*
int a;
int b;
int c;
int d;
*/

1.4 否则的话

改进

刚才的代码并没有去判断我们的票面够不够。也就是说,如果票面小于商品的金额,我们不应该找钱,否则找出来就是负数。因此,我们需要一个机制:当条件成立时,我们做什么。当条件不成立时,我们做什么。这个机制叫做else。因此当条件不满足时,我们可以使用else,输出“你的钱不够”。

完整代码实现

#include <stdio.h>

int main()
{
	//	初始化
	int price = 0;
	int bill = 0;
	//	读入金额和票面
	printf("请输入金额:");
	scanf("%d", &price);
	printf("请输入票面:");
	scanf("%d", &bill);
	//	计算找零
	if ( bill >= price ) {
		printf("应该找您:%d\n", bill - price);
	} else {
		printf("你的钱不够\n");
	}

	return 0;
}

运行结果

我们运行一下,分别测试票面足够和票面不够两种不同的情况,可以发现结果正确。
在这里插入图片描述
在这里插入图片描述


示例:比较两个数的大小

根据所学的知识,我们可以使用不同的方法来实现这个功能。这两种方案中,第一种方案较好,很明了。第二种方案虽然代码量少一些,但是不容易让人直接看得懂。

方案一代码:

#include <stdio.h>

int main()
{
	int a,b;
	printf("请输入两个整数:");
	scanf("%d %d", &a, &b);	
	int max = 0;
	if ( a > b ) {
		max = a;
	}
	else{
		max = b;
	}
	printf("大的那个是%d\n", max);
	return 0;
}

方案二代码:

#include <stdio.h>
int main()
{
	int a,b;
	printf("请输入两个整数:");
	scanf("%d %d", &a, &b);
	int max = b;
	if ( a > b ) {
		max = a;
	}
	printf("大的那个是%d\n", max);
	return 0;
}

1.5 if语句再探

if的两种形式

if的一般形式
通过前面的学习我们已经知道一个基本的if语句由一个关键字if开头,跟上在括号里的一个表示条件的逻辑表达式,然后是一对大括号{}之间的若干条语句。如果表示条件的逻辑表达式的结果不是零,那么就执行后面跟着的这对大括号中的语句,否则就跳过这些语句不执行,而继续下面的其他语句。
if的另外一种形式
值得小心的是,if语句还有另外一种形式,没有大括号,而是紧跟着一行代码。而这行代码就是条件成立时执行的东西。
在这里插入图片描述


示例:

用户输入工作的小时数,我们帮他计算薪水。我们有一些固定的值,每小时的薪水是8.25,每周工作时间为40小时。如果超过标准工作时间,需要支付1.5倍的工资。

代码实现

#include <stdio.h>

int main()
{
	const double RATE = 8.25;  
	const int STANDARD = 40;   
	double pay = 0.0;
	int hours;

	printf("请输入工作的小时数: ");
	scanf("%d", &hours);
	printf("\n");
	if (hours > STANDARD)
   		pay = STANDARD * RATE + 
   			(hours-STANDARD) * (RATE * 1.5);
	else
   		pay = hours * RATE;
	printf("应付工资: %f\n", pay);

	return 0;
}

示例:

输入一个成绩,判断是否及格,及格的分数线设置为60。

代码实现

#include <stdio.h>

int main()
{
	const int PASS=60;
	int score;

	printf("请输入成绩: ");
	scanf("%d", &score);
	
	printf("你输入的成绩是%d.\n", score);
	if ( score < PASS )
		printf("很遗憾,这个成绩没有及格。");
	else {
		printf("祝贺你,这个成绩及格了。");
		printf("再见\n");
	}

	return 0;
}

小测验

1、以下语句是否可以通过编译:
在这里插入图片描述
答案: 可以

2、以下语句是否表示n属于[1,10]:
在这里插入图片描述
答案:错误

3、写出程序的输出结果:
在这里插入图片描述
答案:1

4、写出程序的输出结果:
在这里插入图片描述
答案:1

5、写出程序的输出结果:
在这里插入图片描述
答案:1


二、分支

2.1 嵌套的if-else

嵌套的if语句

前面我们写了一个求两个数最大值的代码,而现在如果我有三个数要求出其中的最大值,我该怎么做?我们的方法是:首先比较a和b的大小。如果a大,则比较a和c的大小。如果b大,则比较b和c的大小。流程如下:
在这里插入图片描述
当if的条件满足或者不满足的时候要执行的语句也可以是一条if或if-else语句,这就是嵌套的if语句。

代码实现

#include <stdio.h>

int main()
{
	int a,b,c;
	scanf("%d %d %d", &a, &b, &c);
	int max = 0;
	if ( a>b ) {
		if ( a>c ) {
			max = a;
		} else {
			max = c;
		}
	} else {
		if ( b>c ) {
			max = b;
		} else {
			max = c;
		}
	}
	printf("The max is %d\n", max);
	
	return 0;
}

由于if语句中需要执行的代码只有一行,那么也可以删除掉if语句中的大括号,代码如下:

#include <stdio.h>

int main()
{
	int a,b,c;
	scanf("%d %d %d", &a, &b, &c);
	int max = 0;

	if ( a>b ) 
		if ( a>c ) 
			max = a;
		else 
			max = c;		
	else 
		if ( b>c ) 
			max = b;
		else 
			max = c;
	
	printf("The max is %d\n", max);

	return 0;
}

if与else的对应关系

在上面代码中的嵌套if语句中,有好几个else,那么每个else对应哪个if呢?实际上,else总是和最近的那个if匹配。同样的,我们在代码中会看到各种各样的缩进,但是缩进格式不能暗示else的匹配。比如下面这种情况,这个else实际匹配的是if (count <20)
在这里插入图片描述
但是如果加上大括号就不一样了,此时else匹配的就是if (code == READY)
在这里插入图片描述
因此,在使用if语句时,建议在if或else后面总是用{},即使只有一条语句的时候。


2.2 级联的if-else

级联的if-else

使用方法:
if ( 条件1 )
语句1;
else if ( 条件2 )
语句2;
else
语句3;

现在我有一个分段函数,我们用if-else来解决。
在这里插入图片描述

代码实现

if (x<0){
	f = -1;
}else if(x==0){
	f=0;
}else{
	f=2*x;
}

2.3 if-else的常见错误

1、忘了大括号
现在有个案例。如果年龄大于60岁,则薪水增加为原来的1.2倍,同时将薪水的值打印出来。

if ( age > 60 )
	salary = salary * 1.2;
	printf("%f",salary);

可是我们没加大括号,导致是否年龄大于60岁,都会输出薪水值。因此,永远在if和else后面加上大括号,即使当时后面只有一条语句。

if( age > 60 )
{
	salary = salary * 1.2;
	printf("%f",salay);
}

2、在if后面多加了分号
在下面这段代码中,我们在if语句后面加了分号。

#include <stdio.h>
int main()
{
	int age = 55;
	double salary = 4000;

	if (age > 60);
	{
		salary = salary * 1.2;
		printf("%f\n", salary);
	}
	return 0;
}

运行,发现我们输入的age小于60,但是仍然打印了新的薪水值。
在这里插入图片描述
这是因为对输入了一个分号导致程序变成了以下这种情况。即if后面有一条语句,可是这条语句什么都不做。因此,这条if什么都不做就结束了。然后下面的那些大括号就是一些正常的语句。

if (age > 60)
    ;
{
	salary = salary * 1.2;
	printf("%f\n", salary);
}

3、错误使用==和=
if只要求()里的值是零或非零。在这段代码中,我们只有一个等号,这就是个赋值,而赋值就是个表达式。这个表达式也会有个结果,这个结果就是b。但它还会有个副作用,那就是把b的值给a。但是它一定不会去判断b是否等于a。只要b的值不是0,这个if就是成立的,顺便还把a的值给改了。

if ( a = b )
{
	printf("A=B");
}

我们举例来看一下。

#include <stdio.h>
int main()
{
	int age = 55;
	double salary = 4000;
	
	//这里我们把==改为=
	if (age = 60);  
	{
		salary = salary * 1.2;
		printf("%d %f\n", age, salary);
	}
	return 0;
}

此时age被赋值为60,同时执行了括号内的内容。
在这里插入图片描述


一些代码风格

为了保证if语句的正确性,一定要注意不要犯以上三种错误。同时,在if和else之后必须加上大括号形成语句块。大括号内的语句缩进一个tab的位置,使得结构更加清晰。下面三种代码风格均可以,知道遵循代码规则即可。
在这里插入图片描述


2.4 多路分支

在前面我们使用了级联的if-else进行分段函数的计算。但有时候我们也会存在这种情况,比如当我的变量等于某一个值时执行对应的操作。这里我有一个案例,当type值不同时,输出不同的语句。

if ( type==1 )
	printf("你好");
else if ( type==2)
	printf("早上好");
else if ( type==3 )
	printf("晚上好");
else if ( type==4 )
	printf("再见");
else
	printf("啊,什么啊?");

对于这种情况,如果运气不好我输入的type的值≥5,那么会逐次执行各个if语句。于是我们就可以写出这样的代码:

switch ( type ) {
case 1:
	printf("你好");
	break;
case 2:
	printf("早上好");
	break;
case 3:
	printf("晚上好");
	break;
case 4:
	printf("再⻅见");
	break;
default:
	printf("啊,什么啊?");
}

这段代码做的内容是:根据type值取匹配各个case后面的值。如果type==1,那么我们就做case 1:后面的内容,直到遇到break。如果type不等于1、2、3、4,那我们做default后面的句子。这便是switch-case语句,它的使用如下所示:

switch ( 控制表达式 ) {
case 常量:
	语句;
case 常量:
	语句;
default:
	语句;
}

使用switch-case时的注意事项

①控制表达式只能是整数型的结果,常量可以是常数,也可以是常数计算的表达式。
②根据表达式的结果,寻找匹配的case,并执行case后面的语句,一直到break为止。
③在执行完对应case中的最后一条语句后,如果后面没有break,就会顺序执行到下面的case里去,直到遇到一个break,或者switch结束为止。
④如果所有的case都不匹配,那么就执行default后面的语句。如果没有default,那么就什么都不做。

针对以上需要注意的地方,我们举例说明。

switch ( type )
{
case 1:
case 2:
	printf("你好\n");
	break;
case 3:
	printf("晚上好\n");
case 4:
	printf("再见\n");
	break;
default:
	printf("啊,什么啊?\n");
	break;
}

如果我们输入的type为1,而对应的case中什么都没有,然后顺序进入case2中去,打印出“你好”,结束。
在这里插入图片描述
如果我们输入的type为3,而对应的case中没有break,因此打印出“晚上好”后顺序进入case4中去,打印出“晚安”,结束。
在这里插入图片描述


示例1: 成绩转换。将100分的成绩转换为ABCDE五个等级。

#include <stdio.h>

int main()
{
	printf("输入成绩(0-100)");
	int grade;
	scanf("%d", &grade);
	grade /=10;
	switch ( grade ) {
	case 10:
	case 9:
		printf("A\n");
		break;
	case 8:
		printf("B\n");
		break;
	case 7:
		printf("C\n");
		break;
	case 6:
		printf("D\n");
		break;
	default:
		printf("F\n");
		break;
	}

	return 0;
}

示例2: 输出月份的英文。

#include <stdio.h>

int main()
{
	printf("请输入月份:");
	int month;
	scanf("%d", &month);
	switch ( month )
	{
		case 1: printf("January\n"); break;
		case 2: printf("February\n"); break;
		case 3: printf("March\n"); break;
		case 4: printf("April\n"); break;
		case 5: printf("May\n"); break;
		case 6: printf("June\n"); break;
		case 7: printf("July\n"); break;
		case 8: printf("August\n"); break;
		case 9: printf("September\n"); break;
		case 10:printf("October\n"); break;
		case 11:printf("November\n"); break;
		case 12:printf("December\n"); break;
	}

小测验

1、写出程序的输出:
在这里插入图片描述
答案:onetwo

2、写出程序的输出:
在这里插入图片描述
答案:ABC

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知初与修一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值