Consider that we need to work with the colours in a rainbow, e. g., to paint a rainbow on the screen. We thus have to work with seven colours, namely, violet, indigo, blue, green, yellow, orange and red. These colours can be represented using integer values starting with 0. This enables us to use various program constructs such as conditions or loops to process these colours. However, programs written using such code often become difficult to understand as can be seen from the statement given below.
color = 4;
Although we can add a comment on such a line, it would be much more readable if we directly use the colour names in our programs, as in
color = Yellow;
One solution is to use symbolic constants using the #define statements:
#define VIOLET 0
#define INDIGO 1
#define BLUE 2
#define GREEN 3
#define YELLOW 4
#define ORANGE 5
#define RED 6
This is inconvenient, particularly when there are a large number of constants to be defined. Moreover, program debugging is difficult as these symbolic constants are not available during the debugging phase.
A better solution to this problem is to declare an enumerated type containing enumerated constants. An enumerated type is a user-defined type with values that can be represented using names instead of integers. For example, we can use enumerated constants Jan, Feb, …,Dec to represent months rather than the integer numbers 1 to 12.
We’ll be covering the following topics in this tutorial:
Declaring Enumerated Types
The format to declare an enumerated type is
enum enum_type { EnumConst1, EnumConst2, … , EnumConstN } ;
This declares a type named EnumType and enumerated constants EnumConst1, EnumConst2, … , EnumConstN. These constants have consecutive integer values starting from 0.
Consider the following declaration for our rainbow example.
enum color {Violet, Indigo, Blue, Green, Yellow, Orange, Red};
This statement declares an enumerated type named color and seven enumerated constants, namely, Violet, Indigo, Blue, Green, Yellow, Orange and Red with consecutive values from 0 to 6. Note that these constants are written in capitalized case to distinguish them from variable names.
Like other declarations, enumerated types can be defined at the beginning of any function or block, with the only requirement that the declaration must precede their use. However, such local declarations will restrict their use to that function or block only. A better approach is to define enumerated types at the beginning of the program, immediately after the #include statements, enabling their use in subsequent programs (structure declarations and functions).
The enumerated data types are useful in numerous programming situations where we refer to the individual items by specific names rather than integer numbers. For example, the names of days and months, keywords of a programming language, program menu items, educational qualifications, class obtained in examination, names of animals and birds, models of various products such as cars, mobiles, processors, soap and so on. Consider the declarations of several enumerated types given below.
enum day {Sunday, Monday, Tuesday, Wednesday, Thursday,Friday, Saturday};
enum file_menu {New, Open, Close, Save, SaveAs, Print, Exit};
enum qualification {SSC, HSC, Diploma, BE, BTech, ME, MTech, PhD};
enum class {Dist, First, Second, Pass};
enum mobile_operator {Aircel, Airtel, BSNL, Docomo, Idea, RCom};
Readers are encouraged to use such enumerated types in their programs to improve program readability.
Variables of Enumerated Types
Once an enumerated type is declared, we can declare (and also initialize) variables of that type using the formats given below.
enum enum_type var1, var2, … ;
enum enum_type var1= enum_val1, var2 = enum_val2, … ;
Note that the keyword enum must precede the enumerated type name. Thus, once we declare enumerated type color as explained earlier, we can declare (and also initialize) variables of type color as shown below.
enum color clr;
enum color cl = Violet, c2 Red;
The declaration of an enumerated type and variables can also be combined. The variables are written between the closing brace and the semicolon. These variables can also be initialized. Consider the declaration given below.
enum dir {Up, Down, Left, Right} d1 = Left, d2 = Right, dir;
This statement declares an enumeration dir and three variables d1, d2 and dir. The variables d1 and d2 are initialized with the values Left and Right, respectively. Note that the name of an enumeration (dir) can also be used as a variable name. Observe that combining variable declarations with that of an enumeration makes the code somewhat difficult to read and should generally be avoided.
Further note that we can omit enumeration name in the above declaration as
enum {Up, Down, Left, Right} dl = Left, d2 = Right, dir;
However, this approach is suitable only if we do not have to subsequently use the enumeration name in our program, e. g., to declare more variables, to convert type using typecast, or to pass parameters to a function.
Specifying Values for Enumerated Constants
By default, the enumerated constants are assigned consecutive values starting from 0. However, we can specify the desired integer values for one or more enumerated constants. The subsequent constants are assigned the next integer values. For example, consider the declaration of enumerated type month given below.
enum month {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep,Oct, Nov, Dec};
The constant Jan is assigned value 1 and subsequent constants are assigned values from 2.
Now consider another declaration of enumerated type color:
enum color {Violet, Indigo, Blue=10, Green, Yellow=20, Orange, Red};
First, the constants Violet and Indigo are assigned values 0 and 1, respectively. As the constant Blue is assigned value 10, constant Green is assigned value 11. Also, as Yellow is assigned value 20, constants Orangeand Red are initialized with values 21 and 22, respectively.
Further note that the values assigned need not be in any specific order. Moreover, two or more constants may have same values as illustrated in the example given below.
enum subject {Physics=40, Chemistry, Biology, Algebra=40, Geometry};
Working with Enumerated Data
Consider the following variable declarations of enumerated types day and month whose declarations are given earlier in this section.
enum day d, dl, d2;
enum month m, ml, m2;
Since enumerated constants and variables are of integer type, we can perform most of the operations on enumerated entities (variables and constants) that we can perform on integer entities. Thus, we can assign values of integer as well as enumerated variables (and constants) to other enumerated variables. For example,
d1 = Monday;
d2 = d1;
m1 = 5; /* May */
However, we should be careful as C compilers will not give any error or warning if we assign incorrect values as shown below.
d1 = Feb;
m2 = 15;
/* d1 is assigned value 2, which is Tuesday */
/* invalid month */
We can use various arithmetic operators (+, -, *, /, %, ++, –) on enumerated entities. Some of these operations are particularly useful if the enumerated constants have consecutive integer values. For example, we can add or subtract an integer constant to an enumerated entity to obtain the subsequent or previous enumerated value, use – operator to determine the numbers of values between two enumerated entities and the ++ and – – operators to obtain the next and previous values, respectively. Consider the examples given below.
d = (d + 5) % 7;
m++;
/* week day 5 days after d */
/* next month */
Note that the C language does not perform any range check on the value being assigned to an enumerated variable.
We can use the scanf and printf functions to perform input/output operations on enumerated entities. For example,
scanf(“%d”, &m);
printf(“%d %d %d\n”, m, Monday, Feb);
Note that we should enter integer value for variable m and the printf statement will print integer values. Also note that some compilers may give a warning as the %d format expects an argument of type int * and not a pointer to enumerated type.
We can also use relational, equality and logical operators with enumeration entities. Consider, for example, the code segment given below to test the value of day d.
if (d == Sunday || d == Saturday)
printf(“Holiday”);
else if (d >= Monday && d <= Friday)
printf(“Weekday”);
else printf(“Invalid day”);
If the enumerated constants have consecutive values, we can process them using loops. For example, assuming that an array month is used to store month names as
char *month[] = {“—“, “January”, “February”, “March”, “April”, “May”, “June”, “July”, “August”, “September”, “October”, “November”, “December”};
we can use a for loop given below to print the month names.
for (m = Jan; m <= Dec; m++)
printf(” %s\n”, month[m]);
Observe that enumerated variable m is used as an array index.
We can use enumerated variables as function parameters and return values. For example, assuming that function is_leap is available to test whether a given year is leap or not, the function month_days given below determines the number of days in a given month.
int month_days(enum month m, int y)
{
static int mdays[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30,31, 30, 31);
return mdays[m] + (m ==Feb && is_leap(y)? 1 : 0);
}
We can declare arrays of enumerated type. For example, consider array months 30 that stores the months that have 30 days.
enum month months30[] = {Apr, Jun, Sep, Nov};
We can declare pointer variables of enumerated type. Consider the code segment given below.
enum month m = Jun, *pm;
pm = &m;
printf(“Month: %d Days: %d\n”, *pm, month_days(*pm, 2012));
Finally, we can use enumerated variables as structure members as illustrated in the declaration given below.
struct tv_serial {
char name[50];
enum day telecast_day[7];
};