前言

这节课是全面线下课,不过也和结课的15周只剩5周了~这节课老师上课讲了switch语句、单字符I/O:getchar()和putchar()、以及队列的清空、文件和重定向等。


Switch语句

switch翻译过来就是开关的意思,那就说明了switch语句有像开关一样的功能。在C语言中,switch可用于多重选择判断,一个 switch 语句允许测试一个变量等于多个值时的情况。每个值称为一个 case,且被测试的变量会对每个 switch case 进行检查。

其基本语句如下:

switch(expression){
    case constant-expression  :
       statement(s);
       break; /* 可选的 */
    case constant-expression  :
       statement(s);
       break; /* 可选的 */
 
    /* 可以有任意数量的 case 语句 */
    default : /* 可选的 */
       statement(s);
}

而在执行时:

  • switch 语句中的 expression 是一个常量表达式,必须是一个整型或枚举类型。
  • 在一个 switch 中可以有任意数量的 case 语句。每个 case 后跟一个要比较的值和一个冒号(英文)。
  • case 的 constant-expression 必须与 switch 中的变量具有相同的数据类型,且必须是一个常量或字面量。
  • 当被测试的变量等于 case 中的常量时,case 后跟的语句将被执行,直到遇到 break 语句为止。
  • 当遇到 break 语句时,switch 终止,控制流将跳转到 switch 语句后的下一行。
  • 不是每一个 case 都需要包含 break。如果 case 语句不包含 break,控制流将会 继续 后续的 case,直到遇到 break 为止。
  • 一个 switch 语句可以有一个可选的 default case,出现在 switch 的结尾。default case 可用于在上面所有 case 都不为真时执行一个任务。default case 中的 break 语句不是必需的。

例如:

/* animals.c -- uses a switch statement */
#include<stdio.h> 
#include<ctype.h> 
int main(void)
{
    char ch;

    printf("Give me a letter of the alphabet, and I will give ");
    printf("an animal name\nbeginning with that letter.\n");
    printf("Please type in a letter; type # to end my act.\n");
    while ((ch = getchar()) != '#')
    {
        if('\n' == ch)
            continue;
        if (islower(ch))     /* lowercase only          */
            switch (ch)
            {
                case 'a' :
                      printf("argali, a wild sheep of Asia\n");
                      break;
                case 'b' :
                      printf("babirusa, a wild pig of Malay\n");
                      break;
                case 'c' :
                      printf("coati, racoonlike mammal\n");
                      break;
                case 'd' :
                      printf("desman, aquatic, molelike critter\n");
                      break;
                case 'e' :
                      printf("echidna, the spiny anteater\n");
                      break;
                case 'f' :
                      printf("fisher, brownish marten\n");
                      break;
                default :
                      printf("That's a stumper!\n");
            }                /* end of switch           */
        else
            printf("I recognize only lowercase letters.\n");
        while (getchar() != '\n')
              continue;      /* skip rest of input line */
        printf("Please type another letter or a #.\n");
    }                        /* while loop end          */
    printf("Bye!\n");
  
    return 0;
}

这是一个典型的使用switch语句的代码,我们输入的字符是哪个就跳到哪一行开始。 但是和我们一般所想的不同,如果没有break的话,就会继续顺序执行下去。

例如:

switch (ch)
{
    case 'a' :
    case 'b' :
        printf("babirusa, a wild pig of Malay\n");
        break;
}

 当我们输入ch是'a'的时候,就会跳到case 'a'这一行开始,但是这个case下没有break语句,就会继续顺序执行,那我们最后输出就是:babirusa, a wild pig of Malay.、

所以我们一般来说会根据需求添加break。

当然我们也可以用if语句替代它们,但是当选择过多时,switch的优势就出来了。


清空队列

这里的情况队列是指清空输入的残余量对下一次输入的影响。就像上面的animal.c这个程序一样,我们读入的是一个字符,但如果我们输入的是:abc呢?,这时候只读取了a,而bc被留在了缓存器中,下次再次读取时先读取了缓存器中的残余内容,就会对结果造成影响。下面我们来看下一张图,了解下程序运行读入的过程:

因为在C语言中,存储是缓存输入的。因为非缓存输入的话就像人类讲话一样,立刻反馈,会造成很多操作无法进行。

像之前一样,我们输入了“abc”,只读入了一个,但我们下一次又输入一个新的字符,这时候我们就要先清空队列了。

操作也很简单:

while (getchar() ! = '\n')
    continue; /*跳过输入行的其余部分*/

 循环从输入中读取字符, 包括按下Enter 键产生的换行符。注意, 函数的返回值并没有赋给ch, 以上代码所做的只是读取并丢弃字符。由千最后丢弃的字符是换行符, 所以下一个被读取的字符是下一行的首字母。


getchar()和putchar()

getchar()和putchar()每次只处理一个字符。你可能认为这种方法实在太笨拙了, 毕竟与我们的阅读方式相差甚远。但是, 这种方法很适合计算机。而且, 这是绝大多数文本(即, 普通文字)处理程序所用的核心方法。

而使用getchar()和putchar()的方法之前也有介绍呢:

【C语言学习之路】第九节课——字符输入输出、字符函数以及逻辑与条件运算符


文件结尾

计算机操作系统要以某种方式判断文件的开始和结束。 检测文件结尾的一种方法是, 在文件末尾放个特殊的字符标记文件结尾。在Windows系统中我们一般可以用打CTRL+Z表示文件结束,但不同的系统的操作方式可能不同。

在<stdio.h>中定义了一个常量EOF(End Of Files)表示文件的结尾。

#define EOF (-1)

为什么是-1?因为getchar()函数的返回值通常都介千0~127, 这些值对应标准字符集。但是, 如果系统能识别扩展字符集, 该函数的返回值可能在0~255之间。无论哪种情况, - 1都不对应任何字符,所以, 该值可用于标记文件结尾。

那我们怎么使用EOF呢?例如:

/* echo_eof.c -- repeats input to end of file */
#include<stdio.h> 
int main(void)
{
    int ch;

    while ((ch = getchar()) != EOF)
        putchar(ch);
  
    return 0;
}

· 不用定义 EOF, 因为 stdio.h 中已经定义过了。
· 不用担心 EOF 的实际值, 因为 EOF 在 stdio.h 中用#define 预处理指令定义, 可直接使用, 不必再编写代码假定 EOF 为某值。
· 变量ch的类型从char变为int,因为char类型的变量只能表示0~255的无符号整数,但 是EOF的值是-1。不过getchar()函数实际返回值的类型是int,所以它可以读取EOF字 符。如果实现使用有符号的char类型,也可以把ch声明为char类型,但最好还是用更通用的形式。

这里的一切都有始有终,却能容纳所有的不期而遇和久别重逢。
最后更新于 2024-01-14