在实际问题中,有些变量的取值被限定在一个有限的范围内。例如,一个星期内只有七天,一年只有十二个月,一个班每周有六门课程等。如果把这些量说明为整型、字符型或其他类型,显然都是不妥当的。为此,C语言提供了一种称为“枚举”的类型。在“枚举”类型的定义中列举出所有可能的取值,被说明为该“枚举”类型的变量取值不能超过定义的范围。
应该说明的是,枚举类型是一种基本数据类型,而不是一种构造类型(它不能再分解为任何基本类型),只是枚举的定义与结构的定义十分相似而已。
用关键字enum来表示枚举,枚举是一个被命名为整数常数的集合,这些常数指定了所有的类型已被定义的合法值。其一般形式为:
enum 枚举名 { 枚举表 } 变量表;
枚举名和变量表是选择项。例如定义一个coin的枚举,money属于这种类型。
enum coin { penny, nickel, dime, quarter, half_dollar, dollar };enum coin money;
除非进行了初始化,否则第一个枚举符号的值为0,第二个为1,依次类推。因此
printf ( /"%d %d /", penny, dime );
将在屏幕上显示0和2两个值。由此可见,一个枚举其实是将每个符号用它们所对应的整数来代替。例如:
printf ( /"The number of nickel in a quarter is %d/", quarter+2 );
按enum定义,quarter=3,所以quarter+2=5。输出为:
The number of nickel in a quarter is 5
【例10.5】找出下面程序中的错误。
#include <stdio.h>enum weekday{ sun,mou,tue,wed,thu,fri,sat }a;void main(){ sun=5; thu=1; printf ( /"wed is %dn/", wed ); printf ( /"sat is %dn/", sat );}
【解答】枚举值是常量,不是变量。不能在程序中用赋值语句再对它赋值。
//改正的程序#include <stdio.h>enum weekday{ sun = 5,mou,tue,wed,thu = 1,fri,sat }a;void main(){ printf ( /"wed is %dn/", wed ); printf ( /"sat is %dn/", sat );}
程序运行结果如下:
wed is 8sat is 3
【例10.6】找出下面程序中的错误。
#include <stdio.h>enum weekday{ sun,mou,tue,wed,thu,fri,sat }a,b,c;void main(){ a=/"mou/"; b=/"wed/"; c=/"fri/"; printf ( /"a is %dn/", a ); printf ( /"b is %dn/", b ); printf ( /"c is %dn/", c );}
【解答】枚举元素是整型常量,既不是字符常量,也不是字符串常量,所以使用时不能加单或双引号。
//改正的程序#include <stdio.h>enum weekday{ sun,mou,tue,wed,thu,fri,sat }a,b,c;void main(){ a=mou; b=wed; c=fri; printf ( /"a is %dn/", a ); printf ( /"b is %dn/", b ); printf ( /"c is %dn/", c );}
运行结果如下:
a is 1b is 3c is 5
【例10.7】下面的程序是否正确?
#include <stdio.h>enum weekday{ sun,mou,tue,wed,thu,fri,sat }a,b,c;void main(){ a=1; b=3; c=5; printf ( /"a is %dn/", a ); printf ( /"b is %dn/", b ); printf ( /"c is %dn/", c );}
【解答】视编译系统而定。有的系统允许把数值直接赋予枚举变量,而有的系统不允许这样赋值。如一定要把数值赋予枚举变量,则必须用强制类型转换。下面两种语句
b=(enum weekday)3; b=(enum )3;
都可将数值3赋给枚举变量b,也就是将序号为3的枚举元素赋予枚举变量b,相当于语句
b=wed;
【例10.8】分析下面程序的输出结果。
#include <stdio.h>enum fiv { a,b,c,d,e} m[15], j;void main(){ int i; j=a; for(i=0;i<15;i++){ m[i]=j; j++; if (j>e) j = a; } for(i=0;i<15;i++){ switch(m[i]) { case a: printf(/" %2d %ct/",i,/'a/'); break; case b: printf(/" %2d %ct/",i,/'b/'); break; case c: printf(/" %2d %ct/",i,/'c/'); break; case d: printf(/" %2d %ct/",i,/'d/'); break; case e: printf(/" %2d %cn/",i ,/'e/'); break; default: break; } }}
【解答】m是枚举数组,下标也是从0开始。为它赋值是从0开始,依次到e,也就是4。然后从0开始再次循环赋值。下标和值的关系如下:
下标0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 值0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
switch用m数组的值作为跳转依据。m有5个不同的值,对应a,b,c,d,e,打印循环的i值是0~14,并5个一组分别对应字符a,b,c,d,e。由此可以给出如下输出结果。
0 a 1 b 2 c 3 d 4 e 5 a 6 b 7 c 8 d 9 e10 a 11 b 12 c 13 d 14 e
【例10.9】编写一个简单的从给定2014年某日得到星期几的程序,要求输入和输出的格式如下:
Input month day:5 25today is sun(7)
【解答】使用枚举
enum weekday{ mou=1, tue, wed, thu, fri, sat, sun} ;
定义星期一至星期天,为了兼顾习惯,将周一初始化为1,则周日为7。
因为只考虑2014年全年,这就可以简单地从2014年1月1日是星期几作为依据进行编程。假设给定的月为month,日期为day,先计算month-1的天数,再加上本月的day-1天,就是总天数alldays。求星期几是用%7,但这没有考虑1月1日已经是星期几的条件。假设1月1日为origin_day,则((alldays+origin_day)%7)就得到星期几。注意在枚举中定义星期天为7,这里计算的星期天是0,所以需要转换。可以继续使用已有变量alldays,使用
alldays = ((alldays + origin_day) % 7);if (alldays == 0) return 7;
语句即可实现。“return alldays”可以满足其他6天。
输出可以设计一个函数
void print_today(today)
来实现。使用switch将7种情况区分开来即可实现各自的输出。下面给出完整的程序。
#include <stdio.h>enum weekday get_weekday(int, int);void print_today(int);enum weekday{ mou=1, tue, wed, thu, fri, sat, sun};void main(){ int month, day; enum weekday today; printf(/"Input month day:/"); scanf(/"%d%d/", &month, &day); today = get_weekday(month, day); print_today(today);}enum weekday get_weekday(int month, int day){ int m[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int i=0, alldays = 0, origin_day = 3; for( i=1; i < month; i++) { alldays += m[i-1]; } alldays += day-1; alldays = ((alldays + origin_day) % 7); if (alldays == 0) return 7; return alldays;}void print_today(int today){ switch(today) { case 1: printf(/"today is %s(%d)n/", /"mou/",today); break; case 2: printf(/"today is %s(%d)n/", /"tue/",today); break; case 3: printf(/"today is %s(%d)n/", /"wed/",today); break; case 4: printf(/"today is %s(%d)n/", /"thu/",today); break; case 5: printf(/"today is %s(%d)n/", /"fri/",today); break; case 6: printf(/"today is %s(%d)n/", /"sat/",today); break; case 7: printf(/"today is %s(%d)n/", /"sun/",today); break; }}
程序运行示范如下:
Input month day:1 1today is wed(3)Input month day:2 14today is fri(5)Input month day:3 8today is sat(6)Input month day:5 25today is sun(7)Input month day:8 5today is tue(2)Input month day:11 24today is mou(1)Input month day:12 31today is wed(3)