前言
这节课是全面线下课,不过也和结课的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()的方法之前也有介绍呢:
文件结尾
计算机操作系统要以某种方式判断文件的开始和结束。 检测文件结尾的一种方法是, 在文件末尾放个特殊的字符标记文件结尾。在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类型,但最好还是用更通用的形式。
Comments NOTHING