Showing posts with label enum. Show all posts
Showing posts with label enum. Show all posts

Tuesday, August 31, 2010

Enum in c++

The problem: representing series of values

It is very common to have a series of values that need to be represented. For example, to simulate a traffic light requires representing three values (red, yellow, and green), but there is no built-in C++ color datatype.

Use integer values to represent colors, for example red as 0, yellow as 1, and green as 2. There is nothing "green" about the value 2, and it could just as easily be represented by some other number. However, it is common to start a series at zero and continue up by ones.

The danger of magic numbers

Use of these "magic" numbers in the source code makes the code unreadable. For example,
x = 1;
What does this do, assign the number one or the color yellow to x?

Use of numbers is also very error prone - it is easy to mistakenly use the wrong one and making changes to the numbers and making updates to all references is difficult.

Use names instead of numbers

A better solution is to create named constants for each of the values. By convention, these named constants are uppercase.
const int RED    = 0;
const int YELLOW = 1;
const int GREEN = 2;
Now it's easy to distinguish between assignment of the number 1 and the color yellow.
int y;
int x;
. . .
y = 1; // assigns the integer one
x = YELLOW; // assigns yellow (which happens to be 1).
There is still the problem that we declare x as an int altho it's a color.

The enum type declaration provides a solution

C++ uses the enum statement to assign sequential integer values to names and provide a type name for declaration.
enum TrafficLightColor {RED, YELLOW, GREEN};
. . .
int y;
TrafficLightColor x;
. . .
y = 1;
x = YELLOW;
The enum declaration creates a new integer type. By convention the first letter of an enum type should be in uppercase. The list of values follows, where the first name is assigned zero, the second 1, etc.

Type checking prevents some erroneous assignments

The compiler may issue an error message or warning if you try to assign one kind of enum to a different kind. It also allows some dangerous types of assignments.
enum TrafficLightColor {RED, YELLOW, GREEN};
enum Gender {MALE, FEMALE};
TrafficLightColor x;
int i;
. . .
x = YELLOW; // good
i = x; // Legal, but bad style. Assigns the integer representation.
i = (int)x; // As above, explicit casting is better style.
x = (TrafficLightColor)2; // Legal, but very dangerous. No checking.

x = FEMALE; // BAD, Compiler may give error or warning.
x = 5; // BAD, Compiler may give error or warning.
 

Setting enum values

It's possible to control the values that are assigned to each enum constant. If a value is assingned to a constant, each successive constant without a value is assigned a value one greater than the previous. enum Day {MON=1, TUE, WED, THU, FRI, SAT, SUN}; The value of MON is one, TUE is two, etc instead of starting at zero. Another use of specific values is to create sets. Explicitly setting the values to powers of two represents each as separate bit. These values can then manipulated using the bit operations (&, |, ^ and ~).
enum Day {MON=1, TUE=2, WED=4, THU=8, FRI=16, SAT=32, SUN=64}; const int WEEKDAY = MON+TUE+WED+THU+FRI; . . . Day today; // This will have one of the values in it. . . . if ((today & WEEKDAY) != 0) . . .

Enum I/O

I/O of enums uses their integer values, not their names. This is not what is desired normally, so extra programming is required on input and output to use the names instead of integer values. The extra work for enum I/O means that they are often not used for simple programs.

Other languages

Java will have type-safe enums in version 1.5. Currently it requires programmers to explicitly declare each name as a constant ints. C# provides enums with additional facilities, eg to get names and check values.

The enum keyword is used to create an enumerated type named name that consists of the elements in name-list. The var-list argument is optional, and can be used to create instances of the type along with the declaration. For example, the following code creates an enumerated type for colors:
enum ColorT {red, orange, yellow, green, blue, indigo, violet};
...
ColorT c1 = indigo;
if( c1 == indigo ) {
cout << "c1 is indigo" << endl;
}
In the above example, the effect of the enumeration is to introduce several new constants named red, orange, yellow, etc. By default, these constants are assigned consecutive integer values starting at zero. You can change the values of those constants, as shown by the next example:
enum ColorT { red = 10, blue = 15, green };
...
ColorT c = green;
cout << "c is " << c << endl;
When executed, the above code will display the following output:
c is 16
Note that the above examples will only work with C++ compilers. If you're working in regular C, you will need to specify the enum keyword whenever you create an instance of an enumerated type:
enum ColorT { red = 10, blue = 15, green };
...
enum ColorT c = green; /* note the additional enum keyword */
printf( "c is %d\n", c );
Alternatively, add a typedef to bring C and C++ on par:
typedef enum ColorT { red = 10, blue = 15, green } ColorT;
...
ColorT c = green; /* no more additional enum keyword */
printf( "c is %d\n", c );

 

Sunday, December 6, 2009

. operator in enum

1)typedef enum errorType{warning, error, exception,}error;
main()
{
error g1;

g1=1;
printf("%d",g1);
}
Answer
Compiler error: Multiple declaration for error
Explanation
The name error is used in the two meanings. One means that it is a
enumerator constant with value 1. The another use is that it is a type name
(due to typedef) for enum errorType. Given a situation the compiler
cannot distinguish the meaning of error to know in what sense the error is
used:
error g1;
g1=error;
// which error it refers in each case?
When the compiler can distinguish between usages then it will not
issue error (in pure technical terms, names can only be overloaded in
different namespaces).
Note: the extra comma in the declaration,
enum errorType{warning, error, exception,}
is not an error. An extra comma is valid and is provided just for
programmer’s convenience.

2) typedef struct error{int warning, error, exception;}error;
main()
{
error g1;
g1.error =1;
printf("%d",g1.error);
}
Answer
1
Explanation
The three usages of name errors can be distinguishable by the compiler at
any instance, so valid (they are in different namespaces).
Typedef struct error{int warning, error, exception;}error;
This error can be used only by preceding the error by struct kayword as in:
struct error someError;
typedef struct error{int warning, error, exception;}error;
This can be used only after . (dot) or -> (arrow) operator preceded by the variable
name as in :
g1.error =1;
printf("%d",g1.error);
typedef struct error{int warning, error, exception;}error;
52
This can be used to define variables without using the preceding struct keyword
as in:
error g1;
Since the compiler can perfectly distinguish between these three usages, it is
perfectly legal and valid.
Note
This code is given here to just explain the concept behind. In real
programming don’t use such overloading of names. It reduces the readability of
the code. Possible doesn’t mean that we should use it!