在实际问题中,有些变量的取值被限定在一个有限的范围内。例如,一个星期内只有七天,一年只有十二个月,一个班每周有六门课程等。如果把这些量说明为整型、字符型或其他类型,显然都是不妥当的。为此,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
)