在实际问题中,有些变量的取值被限定在一个有限的范围内。例如,一个星期内只有七天,一年只有十二个月,一个班每周有六门课程等。如果把这些量说明为整型、字符型或其他类型,显然都是不妥当的。为此,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 8 sat 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 1 b is 3 c 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 e 10 a 11 b 12 c 13 d 14 e
【例10.9】编写一个简单的从给定2014年某日得到星期几的程序,要求输入和输出的格式如下:
Input month day :5 25 today 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 1 today is wed (3 ) Input month day :2 14 today is fri (5 ) Input month day :3 8 today is sat (6 ) Input month day :5 25 today is sun (7 ) Input month day :8 5 today is tue (2 ) Input month day :11 24 today is mou (1 ) Input month day :12 31 today is wed (3 )