在實際問題中,有些變量的取值被限定在一個有限的範圍內。例如,一個星期內只有七天,一年只有十二個月,一個班每週有六門課程等。如果把這些量說明為整型、字符型或其他類型,顯然都是不妥當的。為此,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 )