C语言学习笔记(三)判断

判断(选择结构)

1. 做判断

还记得学习笔记(二)第1节中,我们介绍表达式的时候引入的计算时间差的小例子:

eg:输入两个时间,每个时间分别输入小时和分钟的值,然后输出两个时间之间的差,也以几小时几分表示。

如果直接分钟减分钟,小时减小时,会出现分钟借位的情况:1:40和2:10分的差???

思路:就用分别减的方案,减完后看看有没有借位,如果出现借位,小时数减1,分钟数加60

代码如下:

# include "stdio.h"

int main(){
    int hour1, min1;
    int hour2, min2;

    scanf("%d %d", &hour1, &min1);
    scanf("%d %d", &hour2, &min2);

    int h = hour2 - hour1;
    int m = min2 - min1;

    if (m < 0)
    {                       
        m = m + 60;
        h--;
    }
    printf("时间差是%d小时%d分。\n", h, m);
    return 0;
}

2. 判断的条件

首先,我们需要了解什么是关系运算
计算两个值之间的关系,所以叫做关系运算。C语言中的关系运算符(也叫比较运算符)如下:

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

注:

  1. 关系运算符的结果只有两个值:01当两个值的关系符合关系运算符的预期时,关系运算的结果为整数1,否则为整数0
    eg:printf("%d\n", 5 == 3); 输出结果为0
           printf("%d\n", 5 > 3); 输出结果为1
  2. 关系运算符的优先级比算术运算的低,但是比赋值运算的高。
  3. 判断是否相等的==!=的优先级比其他的低,而连续的关系运算是从左到右进行的。
    eg:5 > 3 == 6 > 4
    先判断5 > 3结果为1,再判断6 > 4结果为1,最后判断1 == 1结果为1,所以该表达式的结果为1
    eg:6 > 5 > 4
    先判断6 > 5结果为1,再判断1 > 4结果为0,所以该表达式的结果为0

下面通过一个例子更深刻的理解选择结构:

找零计算器需要用户做两个操作:输入购买的金额,输入支付的票面,而找零计算器则根据用户的输入做出相应的动作:计算并打印找零,或告知用户余额不足以购买。

思路:从计算机程序的角度看,这就是意味着程序需要读用户的两个输入,然后进行一些计算和判断,最后输出结果。流程图如下:

Created with Raphaël 2.3.0 开始 初始化 输入购买金额和支付票面 余额是否充足 输出找零金额 停止 提示用户余额不足 yes no

代码如下(此处代码有点小问题,下节会再讲):

#include "stdio.h"

int main(){
    // 初始化
    int price = 0;
    int bill = 0;
    // 读入金额和票面
    printf("请您输入金额及票面:");
    scanf("%d %d", &price, &bill);
    // 计算找零
    if (bill >= price)
    {
        printf("找零%d元。", bill - price);
    }
    printf("您的余额不足,请重新支付!");
    
    return 0;
}

上面代码中以两个斜杠“//”开头的语句就是注释,插入在程序代码中,用来向读者提供解释信息。它对于程序的功能没有任何影响,但是往往能使得程序更容易被人类读者理解。
延续数行的注释,要用多行注释的格式来写。多行注释由一对字符序列“/*”开始,而以“*/"结束,这种形式也可用于一行内的注释。
eg:int ak = 47 /*36*/, y = 9;

3. 否则的话

上面找零的例子代码其实是有问题的,因为无论你给的钱够不够都会输出"您的余额不足,请重新支付!"。这样给人的体验感很不好,有没有什么方法能够让程序在满足条件时做一件事,在不满足条件时做另一件事呢?

else :否则的话

找零代码更改如下:

#include "stdio.h"

int main(){
    // 初始化
    int price = 0;
    int bill = 0;
    // 读入金额和票面
    printf("请您输入金额及票面:");
    scanf("%d %d", &price, &bill);
    // 计算找零
    if (bill - price >= 0)
    {
        printf("找零%d元。", bill - price);
    } else{
        printf("您的余额不足,请重新支付!");
    }
    return 0;
}

下面我们再看一个例子:
比较两个数的大小。

#include "stdio.h"

int main(){
    int a, b;
    printf("请输入两个整数:");
    scanf("%d %d", &a, &b);

    int max = 0;
    if (a > b)
    {
        max = a;
    }
    printf("大的那个数是:%d", max);
    return 0;   
}

上面的程序有什么问题???
它没有解决b大于a的问题,当a > b的条件不成立时,程序就结束了,max没有得到值。

解决方案1:

#include "stdio.h"

int main(){
    int a, b;
    printf("请输入两个整数:");
    scanf("%d %d", &a, &b);

    int max = 0;
    if (a > b)
    {
        max = a;
    }
    if (b > a)
    {
        max = b;
    }
    
    printf("大的那个数是:%d", max);
    return 0;   
}

解决方案2:

#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", max);
    return 0;   
}

解决方案3:

#include "stdio.h"

int main(){
    int a, b;
    printf("请输入两个整数:");
    scanf("%d %d", &a, &b);

    int max = b;
    if (a > b)
    {
        max = a;
    }
    
    printf("大的那个数是:%d", max);
    return 0;   
}

上述3种方案各有优劣,方案1,做了两次判断,比较麻烦,方案二通俗易懂,方案3只做了一次判断,但不如前两种方案好理解。

4. if语句再探

一个基本的if语句由一个关键字if开头,跟上在括号里的一个表示条件的逻辑表达式,然后是一对大括号{}之间的若干条语句。如果表示条件的逻辑表达式的结果不是零,那么就执行后面跟着的这对大括号中的语句,否则就跳过这些语句不执行,而继续下面的其他语句。

if语句也可不加大括号{},如:

if (total > amount)
	total += amount + 10;

if语句这一行结束的时候并没有表示语句结束的;,而后面的赋值语句写在if的下一行,并且缩进了,在这一行结束的时候有一个表示语句结束的;。这表明这条赋值语句是if语句的一部分,if语句拥有和控制这条赋值语句,决定它是否要被执行。else同理。

注:if语句有没有{}的结果可能会不一样,强烈建议后面始终加{},防止出现错误!!!

5. 嵌套的if-else

在上面第3节中举了两个数比较大小的例子,用到了一个if-else结构:

#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", max);
    return 0;   
}

如果现在要求输入三个整数,输出其中最大的,应该怎么做?
具体思路如下:

Created with Raphaël 2.3.0 开始 输入三个整数 a > b ? a > c ? 输出max = a 停止 输出max = c b > c ? 输出max = b yes no yes no yes no

具体代码如下:

#include "stdio.h"

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

if的条件满足或者不满足的时候要执行的语句也可以是一条ifif-else语句,这就是嵌套的if语句。

注:在if或else后面总是用{},即使只有一条语句的时候。

6. 级联的if-else if

分段函数在数学中十分常见,现有如下分段函数:
f ( x ) = { − 1 ; x < 0 0 ; x = 0 2 x ; x > 0 f(x) = \left\{\begin{matrix} -1; & x<0\\ 0; & x=0 \\ 2x;& x>0 \end{matrix}\right. f(x)=1;0;2x;x<0x=0x>0
如何用程序实现输入输出呢?

#include "stdio.h"

int main(){
    int x, f;
    scanf("%d", &x);
    if (x < 0)
    {
        f = -1;
    }
    else if (x == 0)
    {
        f = 0;
    }
    else
    {
        f = 2 * x;
    }
    printf("f(%d)=%d", x, f);
    return 0;
    
}

上面程序中就包含级联的if-else if

if (exp1){
    stl1;
    }
else if (exp2){
    stl2;
    }
else{
    stl3;
    }

另外,分段函数的代码不建议写成如下形式:

#include "stdio.h"

int main(){
    int x;
    scanf("%d", &x);
    if (x < 0)
    {
        printf("%d", -1);
    }
    else if (x == 0)
    {
        printf("%d", 0);
    }
    else
    {
        printf("%d", 2 * x);
    }
    return 0;
    
}

该形式不是单一出口,每次形式固定,不具有灵活性!

7. 多路分支(switch-case)

我们需要在一些时候,当一个变量等于这个值时,做什么事情,等于另外一个值时,又做什么事情,我们可以用级联的if-else if去完成,如下例子所示:

#include "stdio.h"

int main(){
    int type;
    scanf("%d", &type);
    if (type == 1)
    {   
        printf("你好!");
    }
    else if (type == 2)
    {
        printf("早上好!");
    }
    else if (type == 3)
    {
        printf("晚上好!");
    }
    else if (type == 4)
    {
        printf("再见!");
    }
    else
    {
        printf("啊,什么啊?");
    }
    return 0;
    
}

这样的代码结构不是太好,如果运气好,type=1,直接运行第一个判断,如果运气不好,不等于1 2 3 4中的任何一个,就要逐一比较每个if里面的条件,每个都比较过后,执行最后一个else中的语句。
有没有什么方法能改变这种情况呢?请看下面的代码:

#include "stdio.h"

int main(){
    int type;
    scanf("%d", &type);

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

上述代码就是switch-case的用法,type等于几就执行相应的case里面的语句,而不需要像级联if-else if那样逐个比对判断条件。

注:

  1. 千万不要忘记每个case里面的break;语句,忘记了代码就会执行到下一个case中的语句,直到遇到break;或者return 0;!!!
  2. switch后面跟的控制表达式只能是整数型的结果,否则会报错!
    case后面跟的常量可以是常数,也可以是常数计算的表达式。
  3. switch语句可以看作是一种基于计算的跳转,计算控制表达式的值后,程序会跳转到相匹配的case(分支标号)处。分支标号只是说明switch内部位置的路标,在执行完分支中的最后一条语句后,如果后面没有break,就会顺序执行到下面的case里去,直到遇到一个break,或者switch结束为止。所以case并不是划分一段一段的标志,case只是一个入口,case不能阻值句子继续往下执行,只有break可以

下面举个例子巩固一下:
本题要求编写程序将一个百分制成绩转换为五分制成绩。转换规则:

  • 大于等于90分为A;
  • 小于90且大于等于80为B;
  • 小于80且大于等于70为C;
  • 小于70且大于等于60为D;
  • 小于60为E。

代码如下:

#include "stdio.h"

int main(){
    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;
}

上述代码不符合之前所说的“单一出口”原则,后续学过字符串处理后再做优化。

  • 20
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值