Lecture 6: Programmer Defined Data Types I: enum, typedef and Structures


Enumerated Data Types

As a programmer, you will find that C++ is limited in the number of built in data types. This can be both a good and a bad feature. It is good since there are fewer to remember because many may not even be useful to your work. This is a bad feature because you are therefore limited in the number of data types that you can use. However C++ has the ability to add programmer defined data types. One of these techniques is to use: ENUMERATED DATA TYPES. Using this feature, the programmer may create an ordered data type that has only a finite number of values or literals. The general construct of enumerated data types is:

image from book

 enum tag {   member_list }; 

image from book

where tag is the name of the enumerated data type (Note: Any name may be used except keywords).

Variables can be defined to represent values of an enumerated data type in the same way that other variables are defined. For example:

image from book

 tag variableName; 

image from book

That is an enumerated data type: Boolean could be defined as follows:

image from book

 enum Boolean {FALSE, TRUE}; 

image from book

While a variable flag1 of the data type Boolean could be defined and initialized as follows:

image from book

 Boolean flag1 = TRUE; 

image from book

The variables of enumerated data types could then be used in a program as in the following:

image from book

 enum Boolean {FALSE, TRUE}; Boolean flag1 = TRUE; ...... if (flag1)     cout << "The goal was met.\n"; else     cout << "The goal was not met.\n"; 

image from book

Before the Boolean data type was added to Standard C++, the code above was a way to create this data type in Classical C++. In this example, FALSE and TRUE are called ENUMERATORS. These enumerators have by default the values 0 and 1 respectively. The enumerators are actually constant ints and are not variables. Therefore the enumerators have no memory addresses. In addition the enumerators can not be treated as integral variables by assigning them an integral value outside of the definition of the enumerated data type to which they belong.

 Note:  The current naming style recommends that the name of the enumerated data type begin with a capital letter and the remaining letters be in lower case. In addition, the enumerator names should be all in capital letters.

 Note:  Since any two enumerated data types have integer as enumerators, the "values" of these enumerators may be the same. However, no two enumerated data types may use the same name for its enumerators. That is the following two enumerated data type definitions could not be in the same program:

image from book

 enum Stype {RED, COUPE, SUDAN, SUV}; enum Color {WHITE, GREEN, RED, YELLOW, BLUE} 

image from book

because they both have the enumerator: RED.

By default the enumerators of an enumerated data type are constant ints that begin with the first enumerator having (by default) the value 0 and each consecutive enumerator has the integral value one more than the previous enumerator. However these rules may be overridden as can be seen in the following examples:

image from book

 enum Colors {BLACK=1, RED, YELLOW, GREEN, BLUE}; enum Position {NORTH, EAST=90, SOUTH=180, WEST=270}; enum Base {FIRST, SECOND=200, THIRD}; enum Value {ZERO, NULL=0, ONE, NUMERO_UNO=1}; 

image from book

For example BLACK is 1, RED is 2, YELLOW is 3, GREEN is 4 and BLUE is 5.

Instances of an enumerated data type may appear to be integral variables but they contain the enumerators instead. Therefore while you would expect to be able to perform arithmetic operations on these variables, you are only allowed to do this in certain cases. If the compiler lets you to perform arithmetic operations, the results of the operation, in some cases, must stay within the enumerators.

For example the following code would be illegal:

image from book

 enum Colors {BLACK=1, RED, YELLOW, GREEN, BLUE}; Colors myCar, theirCar; myCar = RED; theirCar = myCar + 1; 

image from book

The reason for this code not to be syntactically correct is that myCar + 1 would be 3. This is an integer and not one of the Colors' enumerators. Therefore this value may not be used to initialize the Colors' instance: theirCar.

Nor is it possible to treat the variables of an enumerated data type as integers. For example the following code is illegal:

image from book

 enum Colors {BLACK=1, RED, YELLOW, GREEN, BLUE}; Colors myCar, theirCar, hisCar; myCar = RED; hisCar = BLACK; theirCar = myCar + hisCar; 

image from book

Again this is illegal because the sum: myCar + hisCar would be 3 and the integer 3 may not be assigned to the Colors' instance: theirCar.

While the above use of enumerated variables as integers is illegal, it is possible in a limited way to use these variables as integers by converting them to integers using type casting as in the following:

image from book

 enum Colors {BLACK=1, RED, YELLOW, GREEN, BLUE}; int theValue; Colors myCar; myCar = RED; theValue = static_cast<int>(myCar) + 1; cout << theValue; 

image from book

where the output would be the value 3.

So the question arises: What can enumerated data types be used for? Part of the answer is that they may be used in a selection statement. Since enumerated data types are an ordered set of literals, enumerated variables may be used with relational operators as in the following example.

image from book

 enum Colors {BLACK=1, RED, YELLOW, GREEN, BLUE}; Colors myCar; myCar = RED; if(myCar > BLACK)    cout << "That is my car." << endl; 

image from book

Having the above code in a program would output the string: "That is my car."

While enumerated variables may not be initialized directly in arithmetic expressions, there two major uses are when using selection and repetition. That is, they may be used with relational operators. Thus they may be used with if/else statements, with the switch(), with the loops: for(), while() and do/while() when used in the relational operators as in the following selection example:

image from book

 enum Colors {BLACK=1, RED, YELLOW, GREEN, BLUE}; Colors myCar; myCar = RED; if(myCar > 1)    cout << "That is my car." << endl; 

image from book

Having the above code in a program would output the string: "That is my car.".

In addition to being used in if/then statements as above, they may also be used with a switch( ) as in the following example:

image from book

 enum Colors {BLACK=1, RED, YELLOW, GREEN, BLUE}; Colors myCar; myCar = RED; switch(myCar) {   case 1:     cout << "My car is black." << endl;     break;   case 2:     cout << "My car is red." << endl;     break;   case 3:     cout << "My car is yellow." << endl;     break;   case 4:     cout << "My car is green." << endl;     break;   case 5:     cout << "My car is blue." << endl;     break;   default:     cout << "My car is not one of the basic colors." << endl;     break; } 

image from book

The output of the above code would be the string: "My car is red."

In addition to being used in conditional statements and switch( ) statements, enumerated data types may also be used in loops. For example, they may be used in a while( ) as in the following:

image from book

 enum Colors {BLACK=1, RED, YELLOW, GREEN, BLUE}; Colors myCar; myCar = RED; while(myCar == 2) {   cout << "My car color is red" << endl;   myCar = GREEN; } cout << "My car is no longer red." << endl; 

or they may be used in a for( ) as in the following:

 enum Colors {BLACK=1, RED, YELLOW, GREEN, BLUE}; Colors myCar; for(myCar = BLACK ;myCar <= BLUE;myCar = static_cast<Colors>                                  (static_cast<int>(myCar) + 1)) {   switch(myCar)   {     case 1:       cout << "My car is black." << endl;       break;     case 2:       cout << "My car is red." << endl;       break;     case 3:       cout << "My car is yellow." << endl;       break;     case 4:       cout << "My car is green." << endl;       break;     case 5:       cout << "My car is blue." << endl;       break;     default:       cout << "My car is not one of the basic colors." << endl;       break;   } } cout << "My car is no longer one of the basic colors." << endl; 

image from book

The output of the above code would be that the color of myCar was each of the colors of the enumerated data type until finally the loop reaches its limit and exits the loop. Notice how type casting was required to make the for( ) loop work.

It is possible to use enumerators for function arguments. See enum6.cpp. A similar function may be defined to output of an enumerator value. While an enumerated data type may be used as an argument, it may not be used as a return of a function.

An enumerated data type may be defined without the tag. In this case the enumerators are called ANONYMOUS enumerators. For example:

image from book

 enum {FALSE, TRUE}closeQuarters; closeQuarters = FALSE; 

image from book

where closeQuarters is an instance of an enumerated data type with no name. Since this enumerated data type has no name, the only way that instances may be defined is by listing their names immediately after the ending brace and before the semicolon as was done in the example above.

While enumerated data types can be useful, in the current version of C++, they have a short coming with respect to I/O. For example:

image from book

 enum Position {NORTH, EAST=90, SOUTH=180, WEST=270}; Position aSwitch; do {   cout<<"Acceptable values are: 0,90,180 & 270\n";   cin>>aSwitch; }while(aSwitch!=NORTH && aSwitch!=EAST                       && aSwitch!=SOUTH && aSwitch!=WEST); cout<<"The position chosen was "<< aSwitch; 

image from book

The above code has a syntax error. In order to use enumerated data types for I/O, typecasting must be used so that the integral values are input and the integral values are output rather than using the enumerator instances.

For additional examples of enumerated data types see: ENUM1.CPP, ENUM2.CPP, ENUM3.CPP, ENUM4.CPP and ENUM5.CPP.

As discussed above, enumerators are effectively constant ints. In some of the examples above, enumerated data types in which the enumerators had the same integral value. One of my students said:

image from book

"Won't that cause a problem when two enumerators have the same value? How will the program be able to distinguish between these two?"

image from book

This thought had never occurred to me. So I decided to create a program using the enumerated data type that he had a question about. That is: Can the following be used in a program?

image from book

 enum Colors {green, blue, red, orange=2}; 

image from book

Notice that both red and orange have the constant value 2.

So I created a program: ed.cpp. Running this program, you can see that conditional statements do not work correctly, a for() loop and a switch() does not work correctly either. Therefore the conclusion from this experiment is:

image from book

In general two enumerators of an enumerated data type should not have the same integral value. For if they do, then many of the uses of enumerated data types will not work.

image from book




Intermediate Business Programming with C++
Intermediate Business Programming with C++
ISBN: 738453099
EAN: N/A
Year: 2007
Pages: 142

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net