衡庐浅析·C语言程序设计·第三章·三种基本结构之选择结构

       本文适用于大学的期中期末考试、专升本(专接本、专插本)考试、408等考研预科。如有相关题目疑问或建议欢迎在评论区进行互动。

       转载请标明出处。


在上次的知识点章节我们学习了C语言三种基本结构中的顺序结构,也清晰的认识了C语言程序设计的基础框架。本章节我们将来学习三大基本结构的第二部分内容:选择结构。

选择结构

在顺序结构的学习中,我们介绍了其自上而下依次执行的结构特性,显然我们可以发现,这样的语句无法根据是否满足某个条件来决定是否执行指定的操作任务,也无法从给定的两种或多种操作之中执行其一。所以,我们需要学习这个章节的内容——选择结构来实现这样的具体问题。

if 语句

if 语句常常用来判定所给定的条件是否满足,根据判定的结果(真或假)决定是否执行或执行给出的几种操作之一。

其基本句式(单支结构)是:

if(表达式) 语句;  //表达式可以是任意类型任何形式,但其结果必须是1(真)或0(假)

若判断表达式的结果为逻辑真,则执行后面的语句,若为逻辑假则不执行。

 双支结构:

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

若判断表达式的结果为逻辑真,则执行语句1,若为逻辑假则执行语句2。

它还可以衍生为:

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

若判断表达式1的结果为逻辑真,则执行语句1,若为逻辑假则判断表达式2的结果;

若判断表达式2的结果为逻辑真,则执行语句2,若为逻辑假则执行语句3。

这样衍生下去,我们不难总结:

if(表达式1) 语句1;
else if(表达式2) 语句2;
else if(表达式3) 语句3;
……
else if(表达式n) 语句n;
else 语句n+1;

判断、执行语句相应迭代即可。

对于双支结构的if语句,我们常常可以用第二章所学习的三目条件运算符来等价,帮助自己更好理解、掌握、运用。

举个例子:

if(a > b) max = a;
else max = b;

等价于:

if(a > b) max = a;
if(a <= b) max = b;

等价于:

max = a > b ? a : b;

if语句在学习过程中往往比较容易,但其考试却常常成为的易错点、丢分点,究其原因,一般是我们没有深刻体会到某些基本特性,譬如:

else 总是与离其最近且尚未匹配的 if 配对。

举个例子,给出这样一段代码,你是否能判断出其中 if 和 else 是如何配对的?

int a = 1, b = 2, c = 3, d = 0;
if(a == 1)
if(b != 2)
if(c == 3) d = 1;
else d = 2;
else if(c != 3) d = 3;
else d = 4;
else d = 5;
printf("hello world!");

/* 在C语言中,并没有严格的缩进要求;此处不做缩进以更好的考察自己是否掌握该知识点 */

结果如下(同一颜色相互配对):

做这一类题目有一个技巧,即从第一个出现的 else 开始配对,一个 else 配对一个最近的 if ,遇到else if 则一直配对到下一个 else 出现为止,再进行下一轮配对。

同样有一些易错题,其判断语句括号内并不是 == 判断,而是赋值 = ,无论判断后语句是否执行,都会进行一次赋值。

if 语句的知识点到这里就学习的差不多了,再在此处列出两个例题一起巩固一下:

题目:

编写一个C程序,根据用户输入的月份(1-12),判断该月份是否为闰月,并且如果是在北半球的夏季(6-8月),则还需判断该月是否有特定的天文现象(夏至或立秋)。要求使用嵌套的 if 条件语句来实现。

要求:

  1. 用户输入月份(1-12)。
  2. 判断月份是否为闰月(2月)。
  3. 如果是6月、7月或8月,还需判断是否为夏至(6月21日或22日)或立秋(8月7日或8日)。
  4. 输出相应的结果。

解析

  1. 程序首先提示用户输入月份和日期。
  2. 使用嵌套的 if 语句来判断2月是否为闰月。如果是2月,进一步判断日期是否为2月28日或2月29日。
  3. 如果月份不是2月,程序检查月份是否在1月到12月的范围内。如果是,程序进一步检查是否为6月、7月、8月,并且日期是否符合夏至或立秋的条件。
  4. 如果月份是6月,并且日期在6月21日至6月22日之间,输出夏至信息。如果是8月,并且日期在8月7日至8月8日之间,输出立秋信息。
  5. 如果输入的月份不在有效范围内,程序输出无效月份信息。
答案:
#include <stdio.h>
int main()
{
  int month, day;
  printf("请输入月份和日期(例如:6 21): ");
  scanf("%d %d", &month, &day);
  if (month == 2)
  {
    // 2月是闰月的条件
    if (day == 28 || day == 29)
    {
      printf("%d月是闰月。\n", month);
    }
    else
    {
      printf("%d月不是闰月。\n", month);
    }
  }
  else if (month >= 1 && month <= 12)
  {
    if (month == 6 && (day >= 21 && day <= 22) || month == 7 || month == 8 && (day >= 7 && day <= 8))
    {
      if (month == 6 && day >= 21 && day <= 22)
      {
        printf("%d月%d日是夏至。\n", month, day);
      } 
      else if (month == 8 && (day >= 7 && day <= 8))
        {
          printf("%d月%d日是立秋。\n", month, day);
        }
      }
      else
      {
        printf("%d月没有特定的天文现象。\n", month);
      }
    }
    else
    {
      printf("输入的月份无效。\n");
    }
  return 0;
}

题目:

编写一个C程序,根据用户输入的年份、月份和日期,判断这一天是否为特殊节日。特殊节日的规则如下:

  1. 如果是1月1日,为新年。
  2. 如果是12月25日,为圣诞节。
  3. 如果是2月14日,为情人节。
  4. 如果是用户生日(用户可以输入自己的生日),则为“生日”。
  5. 如果是4月1日,为愚人节,但若年份是闰年且月份大于3,则愚人节不成立。
  6. 如果是11月的第四个星期四,则为感恩节。注:11月1日到11月28日不计算为感恩节。
  7. 如果输入的日期是13日,且该月有13日,但不是上述任何节日,则为“不吉利日”。

要求

  1. 用户输入年份、月份和日期。
  2. 程序判断并输出这一天是否为特殊节日,如果不是任何已知节日,输出“普通日”。

解析:

  1. 程序首先定义了一个 isLeapYear 函数来判断是否为闰年。
  2. 定义了一个 getDayOfWeek 函数来获取某一天是星期几,用于计算感恩节的日期。
  3. 用户输入年份、月份、日期和自己的出生月份、日期。
  4. 使用 if 条件语句来判断这一天是否为特殊节日。
  5. 对于愚人节,增加了一个额外的条件,如果是闰年且当前月份大于3月,则不认为是愚人节。
  6. 对于感恩节,计算11月的第四个星期四的日期,并判断是否为感恩节。
  7. 对于13日,增加了一个额外的条件检查,确保它不是已知的节日。
  8. 如果不是任何已知节日,则输出“普通日”。

答案:

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

int isLeapYear(int year)
{
  return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

int getDayOfWeek(int year, int month, int day)
{
  int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
  if (month < 3)
  {
    year--;
  }
  return (year + year / 4 - year / 100 + year / 400 + t[month - 1] + day) % 7;
}

int main()
{
  int year, month, day, birthMonth, birthDay;
  printf("请输入年份、月份和日期(例如:2023 10 10): ");
  scanf("%d %d %d", &year, &month, &day);
  printf("请输入您的出生月份和日期(例如:10 10): ");
  scanf("%d %d", &birthMonth, &birthDay);
  if (month == 1 && day == 1)
  {
    printf("新年快乐!\n");
  }
  else if (month == 12 && day == 25)
  {
    printf("圣诞快乐!\n");
  }
  else if (month == 2 && day == 14)
  {
    printf("情人节快乐!\n");
  }
  else if (month == birthMonth && day == birthDay)
  {
    printf("生日快乐!\n");
  }
  else if (month == 4 && day == 1)
  {
    if (isLeapYear(year) && month > 3)
    {
      printf("普通日\n");
    }
    else
    {
      printf("愚人节!\n");
    }
  }
  else if (month == 11 && day == 28 + (getDayOfWeek(year, month, 1) == 5 ? 1 : 0))
  {
    printf("感恩节快乐!\n");
  }
  else if (day == 13)
  {
    //检查是否是已知节日
    bool isKnownHoliday = (month == 1 && day == 13) || (month == 12 && day == 13);
    if (!isKnownHoliday)
    {
      printf("不吉利日...\n");
    }
    else
    {
      printf("普通日\n");
    }
  }
  else
  {
    printf("普通日\n");
  }
  return 0;
}

switch 语句

switch 语句常常用于多路分支选择的语言结构,它允许根据表达式的值选择执行不同的代码块。

其基本句式是:

switch(表达式)
{
case 常量表达式1:语句序列1 [break;];  //break 指结束本层 switch
case 常量表达式2:语句序列2 [break;];
……
case 常量表达式n:语句序列n [break;];
[default: 语句序列n+1;]  //default 用于对结构中 case 语句未覆盖的情况进行兜底
}

注意:

  • case 后的常量必须是整型或字符型,且不能重复
  • 最多只能有一条 default

switch 语句的执行方法是:

  1. 表达式求值switch 语句开始执行时,首先计算圆括号内的表达式的值。

  2. 寻找匹配的 case:程序会从第一个 case 开始查找,直到找到一个其常量表达式与 switch 表达式的值相等的 case

  3. 执行代码块:找到匹配的 case 后,程序会执行该 case 后面的代码块,直到遇到 break 语句。

  4. break 语句break 语句用于终止 switch 语句的执行。如果没有 break,程序将继续执行后面的 case 代码块,这称为 " fall through " 。

  5. 默认执行:如果没有找到匹配的 case,程序将执行 default 代码块(如果有的话)。default 可以省略,如果没有提供,并且没有匹配的 case,则 switch 语句什么也不做。

举个例子:

#include <stdio.h>
int main()
{
  int month = 3;
  switch (month)
  {
    case 1:
    case 2:
    case 3:printf("Winter\n");break;
    case 4:
    case 5:
    case 6:printf("Spring\n");break;
    case 7:
    case 8:
    case 9:printf("Summer\n");break;
    case 10:
    case 11:
    case 12:printf("Autumn\n");break;
    default:
    printf("Invalid month\n");
  }
  return 0;
}

/* 此 month 的值为3,故程序将打印 Winter */

另外关于 default 还需要注意一点:

当 default 不在最后一行时,编译器会将其暂存,若在后面的语句中没有找到 switch 后相等的变量,则将 default 作为入口;反之,若在后面的语句中找到了 switch 后相等的变量,则不将 default 作为入口。

在这里我们同样举一个 switch语句 的经典例子,来结束本章节的学习:

#include <stdio.h>
int main()
{
  int grade;
  printf("请输入学生的成绩(0-100): ");
  scanf("%d", &grade);
  switch (grade / 10)
  {
    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;
    case 5:
    case 4:printf("等级: E\n");break;
    case 3:
    case 2:
    case 1:printf("等级: F\n");break;
    case 0:printf("没有成绩输入。\n");break;
    default:printf("无效的成绩。\n");
  }
  return 0;
}

这个例子中,程序首先提示用户输入一个 0 到 100 之间的整数,代表学生的成绩。然后,程序使用 switch 语句根据成绩的十位数(即成绩除以10的结果)来决定输出哪个等级:

  • case 10 和 case 9:成绩在90分以上,等级为A。
  • case 8:成绩在80到89分,等级为B。
  • case 7:成绩在70到79分,等级为C。
  • case 6:成绩在60到69分,等级为D。
  • case 5 和 case 4:成绩在50到59分,等级为E。
  • case 3case 2 和 case 1:成绩在0到49分,等级为F。
  • case 0:没有成绩输入,即输入的是0。
  • default:如果输入的成绩不在0到100之间,输出无效的成绩。

《衡庐浅析·C语言程序设计·第三章·三种基本结构之选择结构》部分到这里就结束了,我会在后续章节编写一些题目或分享一些典型的例子以巩固所学的知识点。下一个知识点章节我们将会学习C语言中三种基本结构之循环结构的相关知识,敬请期待,也欢迎大家在评论区进行互动!

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 22:28:02       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 22:28:02       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 22:28:02       45 阅读
  4. Python语言-面向对象

    2024-07-19 22:28:02       55 阅读

热门阅读

  1. 每类数据保留前n条(sql)

    2024-07-19 22:28:02       13 阅读
  2. 慢查询&sql&索引优化

    2024-07-19 22:28:02       15 阅读
  3. [C/C++入门][ifelse]15、判断奇偶数

    2024-07-19 22:28:02       16 阅读
  4. 99:PostgreSQL开启SQL语句日志收集

    2024-07-19 22:28:02       18 阅读
  5. 数学黑洞6174

    2024-07-19 22:28:02       18 阅读
  6. 日文医学文献pdf怎么翻译

    2024-07-19 22:28:02       16 阅读