第3章 分支结构程序设计

运行环境以Dev-C++、Visual Studio 2022、MacOS的命令行和Xcode为主

1.关系表达式和逻辑表达式

  • 1.1 关系运算

    • 对两个数据值的大小进行比较的运算。判断它们是否符合给定条件:若符合,则结果为1(即真);否则结果为0(即假)

    • 用关系运算符连接两个表达式组成的式子称为关系表达式。一般情况下,关系运算符的优先级(6 7)低于算术运算符(1 3 4),高于赋值运算符(14)

    • 同优先级的关系运算符同时出现时从左向右进行运算,如a != b == c等价于 (a != b) == c

    • 表达式的值为真时结果为1,表达式的值为假时结果为0,例如x=(3>2);x的值为1;x=(3<2);x的值为0。

    关系运算符 含义 优先级
    < 小于 6
    <= 小于或等于 两者满足其一即可 6
    > 大于 6
    >= 大于或等于 两者满足其一即可 6
    == 等于 7
    != 不等于 7
    • 案例分析

      • 1.假设整型变量a、b、c的值为1 2 2,分析关系表达式a < b < c的执行结果
      // 1.在数学中,表达式 a < b < c 中是不成立的,因为1 < 2 < 2不成立
      // **2.在C语言中,表达式 a < b < c 中存在两个优先级相同的关系运算符 < ,会按照从左往右的顺序计算**
      // 2.1 首先计算 a < b 的值,即1 < 2,结果为真,这样表达式 a < b < c 就转换为 1 < c
      // 2.2 然后计算 1 < c 的值,即1 < 2,结果为真
      // 2.3 综上,表达式 a < b < c 的执行结果为真,即1
      

      • 2.现有变量age,若age在18-28之间为"青年",用关系表达式表示"青年"的年龄范围
      // 正确写法:age >= 18 && age <= 28
      // 错误写法:18 <= age <= 28,当 age=10 时,不符合"青年"的标准,但程序会打印青年。具体原因可参考上一题
      

      • 3.关于"=="的代码书写技巧
      int num = 3;
      if(num == 5) {
          printf("Y\n");
      }
      
      // 上述代码若将"=="误写为"=",编译器不会报错,但存在逻辑错误,因为程序的本意为判断num与5的值是否相等
      int num = 3;
      if(num == 5) {
          printf("Y\n");
      }
      
      // 如何避免上述错误,在写带有"=="的简单关系表达式时(只有一个变量和一个值),左边写常量,右边写变量。这样如果"=="误写为"=",编译器会直接报错
      int num = 3;
      if(num == 5) {
          printf("Y\n");
      }
      
  • 1.2 逻辑运算

    运算符 含义 优先级 结合方向 备注
    ! 逻辑非 2 单目运算符
    && 逻辑与 11 双目运算符
    逻辑或 逻辑或 12 双目运算符
    • 用逻辑运算符连接若干个表达式组成的算式称为逻辑表达式,根据运算符的优先级确定表达式的运算顺序

    • 基本运算特征

      • A&&B 只有在A和B均为真时结果才为真,否则结果为假

      • A||B 只有在A和B均为假时结果才为真,否则结果为真

      • !A 若A为真,则结果为假,否则结果为真

    • 短路运算特征

      • 若A为假,则A&&B的结果一定为假,B不会参与运算(注意B含++、--的场景)

        • 例如int a = 0, b = 4; a&&++b;执行完后b的值仍为4
      • 若A为真,则A||B的结果一定为真,B不会参与运算(注意B含++、--的场景)

        • 例如int a = 1, b = 0; a||b++;执行完后b的值仍为0

2.条件语句

  • 2.1 if语句

    • 一般形式
    if (表达式) {
        语句;
    }
    
    // 空语句
    if (表达式) {
        ;
    }
    
    // 与上述空语句等价
    if (表达式) ;
    
    • 执行逻辑:先对"表达式"求值,如果计算结果非0(为真),则执行其后的"语句",否则(即表达式的值为0)跳过其后的"语句"

    • 注意事项

      • 1."表达式"的类型可以为任何类型的表达式,理论上只要有值就可以

        • if(a == b) { 语句; } 只有在变量a和b的值相等时,才会执行"语句"

        • if(a = b) { 语句; } 将b的值赋值给a,整个"表达式"的值即a的值。若b = 0,则不执行"语句";若b != 0,则执行"语句"

        • if(a) { 语句; } 若a = 0,则不执行"语句";若a != 0,则执行"语句"

      • 2.区分表达式的值和变量的值,两个不一定相同。如表达式a=0的值为0,变量a的值也为0

      • 3.无论"语句"是单条语句还是复合语句,建议都把{}加上,以提升程序可读性,尤其是在后面复杂的选择结构中

      • 4.空语句,在一般格式部分已说明

    • 案例分析

      • 1.输入一个成绩score,如果成绩大于60,则显示"通过",否则不显示
      // 课本上的代码结构不严谨,按照以下代码书写
      #include <stdio.h>
      int main(){ 
          int  score = 0;
          printf("input score:");
          scanf("%d", &score );
          if(score >= 60) {
      	    printf("通过\n");
          }
      }
      
  • 2.2 if...else语句

    • 一般格式
    if (表达式) {
        语句1;
    }
    else {
        语句2;
    }
    
    // 空语句
    if (表达式) {
        ;
    }
    else {
        ;
    }
    
    // 与上述空语句等价
    if (表达式) ;
    else ;
    
    if (condition) {
        return x;
    }
    return y;
    
    // 与上述不带else的代码段等价
    if (condition) {
        return x;
    }
    else {
        return y;
    }
    
    • 执行逻辑:先对"表达式"求值,如果计算结果非0(为真),则执行"语句1",否则(即表达式的值为0)执行"语句2"

    • 注意事项

      • 1."语句1"和"语句2"可以是简单语句或复合语句,两者若有多条(不低于2)语句,应当加上{}。否则可能会报错,'else' without a previos 'if'(else 找不到前方的if)

      • 2.建议使用{}并使用缩进格式,以提高程序可读性

      • 3.空语句即花括号中只有一个分号;,没有其他内容

    • 案例分析

      • 1.输入一个成绩score,如果成绩大于60,则显示"通过",否则显示"未通过"
      #include <stdio.h>
      int main(){ 
          int  score = 0;
          printf("input score:");
          scanf("%d", &score);
          if(score >= 60) {
      	    printf("通过!\n");
          }
          else { // 执行此分支的前提为:score < 60
              printf("未通过, 继续努力!\n")
          }
      }
      
      • 2.输入年龄的值,如果低于18岁,打印未成年;否则打印已成年,可以打游戏
      // 错误示例,即使age = 10也会打印"可以打游戏",通过调试找出程序的bug
      #include <stdio.h>
      int main(){ 
          int  age = 0;
          scanf("%d", &age);
          if(age < 18) 
              printf("未成年!\n");
          else
              printf("已成年!\n");
              printf("可以打游戏!\n");
      }
      
      // 原因在于最后一条printf()语句不属于if...else结构,是独立的
      
  • 2.3 if语句的嵌套

    • 一般格式
    if (表达式1) {
        语句1;
    }
    else if (表达式2) {
        语句2;
    }
    else if (表达式3) {
        语句3;
    }
    else {
        语句4;
    }
    
    // 空语句
    if (表达式1) {
        ;
    }
    else if (表达式2) {
        ;
    }
    else if (表达式3) {
        ;
    }
    else {
        ;
    }  
    
    // 与上述空语句等价
    if (表达式1) ;
    else if (表达式2) ;
    else if (表达式3) ;
    else ;  
    
    • 执行逻辑

      • 1.先对表达式1求值,如果计算结果非0(为真),则执行"语句1",随后执行if嵌套后方的语句;否则进入第2步

      • 2.计算表达式2的值,如果计算结果非0(为真),则执行"语句2",随后执行if嵌套后方的语句;否则进入第3步

      • 3.计算表达式3的值,如果计算结果非0(为真),则执行"语句3",随后执行if嵌套后方的语句;否则进入第4步

      • 4.执行"语句4"

    • 注意事项

      • 1."语句1"到"语句4"只有可能执行其中一个,因为表达式本身就是互斥的

      • 2.建议使用{}并使用缩进格式,以提高程序可读性

      • 3.在嵌套的if语句中,else与其上最接近的不曾与else配对的if配对,除非用花括号来改变,如以下程序段

      // 程序段1  else与内层if配对
      if (x > 7) {
          if(x < 13) {   // 执行前提:x > 7 && x < 13
              printf("Left!\n");
          }
          else {        //执行前提:x >= 13
              printf("Right!\n");
          }
      }
      
      // 程序段2  else与外层if配对
      if (x > 7) {
          if(x < 13) {    // 执行前提:x > 7 && x < 13
              printf("Left!\n");
          }
      }
      else {         // 执行前提:x <= 7
          printf("Right!\n");
      }
      
    • 案例分析

      • 1.现有分段函数,当x < 1时,y = x;当1 =< x < 10时,y = 2x - 1;当x >= 10时,y = 3x - 10。编写程序输入x的值,输出对应y值
      // 题目共有3种不同的情况,应当选择if...else if...else多分支结构
      #include<stdio.h>
      int main(){ 
          float x = 0.0f, y = 0.0f;
          printf("input x:");
          scanf("%f", &x );
          if(x < 1) {
              y = x;
          }
          else  if(x < 10) { //隐含条件:x >= 1
              y = 2 * x -1;
          }
          else { //隐含条件:x >= 10
              y = 3 * x -10;
          }
          printf("y值为:%.2f\n", y );
      }
      
  • 2.4 条件表达式:又称三目运算符,由?:组成,要求有三个运算对象

    • 一般格式:表达式1 ? 表达式2 : 表达式3;
    t = A ? B : C  // 若A的结果为真(或非0),则将B的值赋值给t;若A的结果为假(或0)则将A的值赋值给t
    
    • 执行逻辑

      • 若表达式1的结果为真或非0,则条件表达式的值等于表达式2的值

      • 若表达式1的结果为假或零,则条件表达式的值为表达式3的值

    • 注意事项

      • 1.一条语句实现求两个数中较大的数:m = (x > y) ? x : y; 若x > y,则将x的值赋值给变量m,否则将y的值赋值给变量m。实际上就是简化版的if...else...语句

      • 2.优先级:条件运算符的优先级(13)高于赋值运算符(14),低于关系运算符(6 7)和算术运算符(1 3 4)

      • 3.结合性:右结合性,即自右向左,可理解为先从右边开始加括号。如 a == b ? (c = 0) : a > b ?(c = 2) : (c = -2) 等价于 a == b ? (c = 0) : (a > b ? (c = 2) : (c = -2))

    • 案例分析

      • 1.输入一个字母,判断它是否为大写英文字母,若是则转换为小写字母
      #include <stdio.h>
      int main() {
          char ch = 0;
          printf("input ch:");
          scanf("%c", &ch);
          ch = (ch >= 'A' && ch <= 'Z'? ch + 32 : ch);  // (ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122)
          printf("%c\n", ch);   // putchar(ch);
          return 0;
      }
      

3.多分支语句

  • 3.1 一般格式
switch (表达式) {
    case 常量表达式1:  // 'A' 2 3 4 2+3  'A'+1
        语句部分1;
        [break;]
    case 常量表达式2:
        语句部分2;
        [break;]
    case 常量表达式n:
        语句部分n;
        [break;]
    [default:  // 前面的n个实例都没匹配,就执行default语句
        语句部分n+1;]
}
  • 3.2 执行逻辑

    • 1.计算switch语句括号中的表达式

    • 2.将计算的结果依次与各case后的值比较

      • 一旦匹配成功,则马上执行相应的“语句部分”,若遇break,结束switch语句

      • 若均不匹配,则执行default(若有的话)后的语句部分

  • 3.3 注意事项

    • 1.[]内的语句为可选部分,switch后方的表达式一般是整形表达式或字符型表达式

    • 2.case标号是整型数(包括字符型)或整型常量表达式,不能是变量,每一个case常量表达式的值必须互不相同,以下示例均错误

    case 1.5: printf("hello");  // 1.5是浮点数,C语言中的浮点数大都是约数
    case 2:
    case 1+1:  // 即case 2
    
    int n = 4;
    case n:  // n为变量,不是常量
    
    • 3.执行break后,程序流程跳出(结束)switch结构,转而执行switch结构后面(右花括号}之后)的第一条语句

    • 4.若程序中相匹配的分支部分没有break语句,将会继续执行下一个case语句后面的程序段(即使此时case后方的常量表达式与switch后方的表达式结果不同),一直到出现break语句或switch结束为止

    • 5.case作为程序数据流的入口,break作为程序数据流的出口

    • 6.若没有default语句,最后一个case语句建议加上break,防止后续再加case语句导致不能跳出的情况;建议写上default语句,同时后方也加上break

    • 7.switch语句允许嵌套

  • 3.4 案例分析

    • 1.根据考试成绩的等级(A、B、C、D),输出“优秀”“良好”“及格”和“不及格”等评语
     // 分析:由于本题共有4种情形,属于多分支,故选用switch结构
    // 错误代码示范
    #include <stdio.h>
    int main() {
        char grade = 0;
        printf("input grage A、B、C or D:");
        scanf("%c", &grade);
        switch(grade) {
            case 'A':
                printf("优秀\n");
            case 'B':
                printf("良好\n");
            case 'C':
                printf("及格\n");
            case 'D':
                printf("挂科\n");
        } 
        return 0;
    }
    // 输入:C
    // 输出为:及格
    //        挂科
    // 当匹配上某条case语句中的常量后,因为不存在break,所以会按照顺序执行后面的所有语句,直到遇到break或者程序末尾才结束程序
    // 输入的C会先与case 'C'语句块匹配上,后面会继续匹配上case 'D'及其语句块,因此"挂科"也会被打印 
    
    
    // 正确代码示范
    #include  <stdio.h>
    int main(){
        char grade = 0;
        printf("input grage A、B、C or D:");		
        grade = getchar();  // scanf("%c", &grade);
        switch (grade) {
            case 'A':
                printf("优秀 \n");
                break;
            case 'B':
                printf("良好 \n");
                break; 
            case 'C':
                printf("及格 \n");
                break;
            default:
                printf("不及格 \n");
                break;
        }
        return 0;
    }
    
    • 2.多个switch标号共用一组语句
    #include <stdio.h>
    int main() {
        char grade = 0;
        printf("input grage A、B、C or D:");		
        grade = getchar();  // scanf("%c", &grade);
        switch (grade) {
            case 'A':
            case 'B':  // 只管匹配,不管打印
            case 'C': 
                printf("及格\n");
                break;
            case 'D':
                printf("不及格\n");
                break;
            default:
                printf("输入数据错误\n");
                break;
        }
        return 0;
    }
    
    • 3.输入一个1-7的正整数,打印星期几。如输入3,打印星期三。若超出范围,则提示"输入错误"
    // 分析:由于本题共有7种情形,属于多分支,故选用switch结构
    #include <stdio.h>
    int main() {
        int day = 0;
        scanf("%d", &day);
        switch(day) {
            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;
            default:
                printf("输入错误\n");
                break;
        }
        return 0;
    }
    
    • 4.输入一个1-7的正整数,如果输入的是1、2、3、4、5,则打印"weekday",输入6、7则打印weekend。若超出范围,则提示"输入错误"
    // 分析:由于本题共有2种情形,但输入情况有7种,选用switch结构。多个switch标号共用一组语句
    #include <stdio.h>
    int main() {
        int day = 0;
        scanf("%d", &day);
        switch(day) {
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                printf("weekday\n");
                break;
            case 6:
            case 7:
                printf("weekend\n")
            default:
                printf("输入错误\n");
                break;
        }
        return 0;
    }
    

4.分支结构程序设计

  • 1.从键盘输入两个整数,输出其中最大者
// 方法1:使用if...else...语句(推荐)
#include <stdio.h>
int main(){	
    int a = 0, b = 0, max = 0;
    printf("input a、b:");
    scanf("%d %d", &a, &b);
    if (a > b) {
        max = a;
    }
    else {
        max = b;
    } 
    printf("两者中最大值为:%d", max );
    return 0;
}

// 方法2:使用条件表达式(推荐)
#include <stdio.h>
int main(){	
    int a = 0, b = 0, max = 0;
    printf("input a、b:");
    scanf("%d %d", &a, &b);
    max = a > b? a : b;
    printf("两者中最大值为:%d", max );
    return 0;
}

// 方法3:使用两个并列的if语句(不推荐)
#include <stdio.h>
int main(){	
    int a = 0, b = 0, max = 0;
    printf("input a、b:");
    scanf("%d %d", &a, &b);
    if (a > b) {
        max = a;
    }
    if (a <= b) {
        max = b;
    } 
    printf("两者中最大值为:%d", max );
    return 0;
}
  • 2.从键盘输入两个整数,从小到大输出
#include <stdio.h> 
int main() {    
    int  a = 0, b = 0, tmp = 0;
    printf("input a、b:");
    scanf("%d %d", &a, &b);
    if (a > b) {
        tmp = a; 
        a = b;
        b = tmp;
    }
    printf("%d, %d", a, b);
    return 0;
}

// 代码借助中间变量tmp完成变量a、b值的交换。除此之外,还可以直接基于变量a、b作“加减”的方式完成,代码为:a = a + b; b = a - b; a = a - b;
  • 3.编写一个程序,判断一个字符是否为英文字母
#include <stdio.h>
int main() {
    char ch = 0;
    printf("input ch:");
    scanf("%c", &ch);  // ch = getchar();
    if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
        printf("%c是英文字母\n", ch );
    }
    else {
        printf("%c是其他字符\n", ch );
    }
    return 0;
}
  • 4.已知区域A是由半径为1的圆和半径为2的圆所围成的圆环。编写程序,输入x、y,若点(x, y)在圆环内,则输出TRUE;否则输出FALSE

    • 分析:题目的重点在于如何用数学表达式来表示圆环区域A

      • 圆心在原点,半径为r的圆的标准方程为x^2+y^2=r^2,因此圆心为原点,半径为1和2的圆可用方程x^2+y^2=1x^2+y^2=4来表示
      • 又因为区域A在内圆之外(x^2+y^2>=1),且在外圆之内(x^2+y^2<=4),则A可用1 <= x^2+y^2 <= 4来表示,转换为C语言表达式即为(x * x + y * y >= 1)&&( x * x + y * y <=4)

    image

#include <stdio.h>
int main() {
    int b = 0;
    float x = 0.0f, y = 0.0f, z = 0.0f;
    printf("input x、 y:"); 
    scanf("%f %f", &x, &y);
    z = x * x + y * y;
    b = (z >= 1) && (z <= 4); 
    if(b){
        printf("TRUE\n");
    }
    else{
        printf("FALSE\n");
    }
    return 0;
}
posted @ 2025-03-12 14:35  pycoder_666  阅读(72)  评论(0)    收藏  举报