9.6 使用枚举类型
在C语言中,如果一个变量只有几种可能的值,则可以定义为枚举(enumeration)类型。所谓“枚举”就是指把可能的值一一列举出来,变量的值只限于列举出来的值的范围内。以下将详细介绍如何使用枚举类型。
第9章 用户自己建立数据类型
声明枚举类型
声明枚举类型用 enum
开头。例如:
enum Weekday {sun, mon, tue, wed, thu, fri, sat};
以上声明了一个枚举类型 enum Weekday
。然后可以用此类型来定义变量。例如:
enum Weekday workday, weekend;
其中,workday
和 weekend
被定义为枚举变量,花括号中的 sun, mon, …, sat
称为枚举元素或枚举常量。它们是用户指定的名字。枚举变量和其他数值型量不同,它们的值只限于花括号中指定的值之一。
使用枚举变量
例如,枚举变量 workday
和 weekend
的值只能是 sun
到 sat
之一:
workday = mon; // 正确,mon是指定的枚举常量之一
weekend = sun; // 正确,sun是指定的枚举常量之一
weekend = monday; // 不正确,monday不是指定的枚举常量之一
枚举常量的命名
枚举常量是由程序设计者命名的,用什么名字代表什么含义,完全由程序员根据自己的需要而定,并在程序中作相应处理。
不带名字的枚举类型
也可以不声明有名字的枚举类型,而直接定义枚举变量,例如:
enum {sun, mon, tue, wed, thu, fri, sat} workday, weekend;
枚举类型的一般形式
声明枚举类型的一般形式为:
enum [枚举名] {枚举元素列表};
其中,枚举名应遵循标识符的命名规则,上面的 Weekday
就是合法的枚举名。
注意事项
-
枚举常量处理: C编译器对枚举类型的枚举元素按常量处理,故称枚举常量。不要因为它们是标识符(有名字)而把它们看作变量,不能对它们赋值。例如:
sun = 0; // 错误,不能对枚举元素赋值 mon = 1; // 错误,不能对枚举元素赋值
-
枚举元素的整数值: 每一个枚举元素都代表一个整数,C语言编译器按定义时的顺序默认它们的值为0, 1, 2, 3, 4, 5…。在上面的定义中,
sun
的值自动设为0,mon
的值为1,依此类推。如果有赋值语句:workday = mon;
相当于:
workday = 1;
枚举常量是可以引用和输出的。例如:
printf("%d", workday); // 将输出整数1
-
显式指定枚举元素的数值: 也可以在定义枚举类型时显式地指定枚举元素的数值,例如:
enum Weekday {sun = 7, mon = 1, tue, wed, thu, fri, sat} workday, weekend;
指定枚举常量
sun
的值为7,mon
为1,以后顺序加1,tue
的值为2,依此类推。 -
枚举元素的比较: 枚举元素可以用来作判断比较。例如:
if (workday == mon)… if (workday > sun)…
枚举元素的比较规则是按其在初始化时指定的整数来进行比较的。如果定义时未人为指定,则按上面的默认规则处理,即第1个枚举元素的值为0,故
mon > sun
,sat > fri
。
使用枚举类型的示例
例9.12
口袋中有红、黄、蓝、白、黑5种颜色的球若干个。每次从口袋中先后取出3个球,问得到3种不同颜色的球的可能取法,输出每种排列的情况。
解题思路:球只能是5种颜色之一,而且要判断各球是否同色,可以用枚举类型变量处理。设某次取出的3个球的颜色分别为 i
, j
, k
。根据题意,i
, j
, k
分别是5种色球之一,并要求3球颜色各不相同,即:i ≠ j
, i ≠ k
, j ≠ k
。可以用穷举法,即把每一种组合都试一下,看哪一组符合条件,就输出 i
, j
, k
。
算法表示:
#include <stdio.h>
int main() {
enum Color {red, yellow, blue, white, black};
// 声明枚举类型 enum Color
enum Color i, j, k, pri;
// 定义枚举变量 i, j, k, pri
int n, loop;
n = 0;
for (i = red; i <= black; i++)
for (j = red; j <= black; j++)
if (i != j) {
for (k = red; k <= black; k++)
if ((k != i) && (k != j)) {
n = n + 1;
printf("%-4d: ", n);
// 输出当前是第几个符合条件的组合
for (loop = 1; loop <= 3; loop++) {
switch (loop) {
case 1: pri = i; break; // 第1球的颜色赋给pri
case 2: pri = j; break; // 第2球的颜色赋给pri
case 3: pri = k; break; // 第3球的颜色赋给pri
default: break;
}
// 根据球的颜色输出相应的文字
switch (pri) {
case red: printf("%-10s", "red"); break;
case yellow: printf("%-10s", "yellow"); break;
case blue: printf("%-10s", "blue"); break;
case white: printf("%-10s", "white"); break;
case black: printf("%-10s", "black"); break;
default: break;
}
}
printf("\n");
}
}
printf("Total: %5d\n", n);
return 0;
}
程序分析: 在程序各行的注释中已说明了各语句的作用。请仔细分析。在输出时,注意输出的字符串 "red"
与枚举常量 red
并无内在联系,输出 "red"
等字符完全是人为指定的。枚举常量的命名完全为了使人易于理解,它们并不自动地代表什么含义。例如,不因为命名为 red
,就代表“红色”,用其他名字也可以。用什么标识符代表什么含义,完全由程序设计者决定,以便于理解为原则。
有人说,不用枚举常量而用常数0代表“红”,1代表“黄”……不也可以吗?是的,完全可以。但显然用枚举变量(red
, yellow
等)更直观,因为枚举元素都选用了令人“见名知义”的名字。此外,枚举变量的值限制在定义时规定的几个枚举元素范围内,如果赋予它其他值,就会出现出错信息,便于检查。