So far, most of the data types you have seen have been numerical
(Integer
, Float
). In this section you will be
introduced to the important concept of enumeration types. An enumeration
type is defined by a list of values taking the form of identifiers. These
types are called enumeration types because their values are enumerated,
or given in a list. An enumeration type is useful in representing a fixed
set of values that are not numerical, such as the days of the week, the
months of the year, the years (freshman, sophomore, junior, senior) in a high
school or college career, or the expenditure categories in an accounting
program. Ada encourages you to use enumeration types by providing a small but
useful set of operations on them and also an input/output package that makes it
easy to read enumeration values from a keyboard or disk file and display them
on the screen.
In many programming situations, the standard data types and their values are
inadequate. For example, in a budget program we might want to distinguish among
the following categories of expenditures: entertainment, rent, utilities, food,
clothing, automobile, insurance, and miscellaneous. We could always assign an
arbitrary code that associates entertainment with a character value of
'e'
, rent with a character value of 'r'
, and so on.
However, enumeration types allow us to specify the set of values directly. For
example, the enumeration type Expenses
declared below has eight
possible values enclosed in parentheses:
TYPE Expenses IS (entertainment, rent, utilities, food, clothing, automobile, insurance, miscellaneous); ExpenseKind : Expenses;The variable
ExpenseKind
(type Expenses
) can contain any
of the eight values listed after Expenses IS
. The values, called
enumeration literals, associated with an enumeration type are generally
identifiers and therefore must conform to the syntax of identifiers. The type
declaration must precede any variable declaration that references it.
The enumeration type Days
has the values Monday
,
Tuesday
, and so on:
TYPE Days IS (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday);
SYNTAX
DISPLAY
Enumeration Type Declaration
TYPE enumeration-type IS
(identifier-list);
TYPE Class IS (Freshman, Sophomore, Junior,Senior);
Freshman
is less than Sophomore
;
Junior
is greater than Freshman
. It is permissible for the same enumeration literal to appear in several enumeration types, just as it is permissible for the same numerical value to appear in several numerical types. It is, for example, possible to define the three types
TYPE Traffic_Light_Colors IS (Red, Yellow, Green);
TYPE Primary_Paint_Colors IS (Red, Yellow, Blue);
TYPE Primary_TV_Colors IS (Red, Blue, Green);in the same program without causing difficulties for the compiler.
The order relationship between the values of an enumeration type is fixed when
the type is declared. Each literal has a position in the type, given as
a value of type Natural
. For type Days
, the first
value in its list (Monday
) has position 0, the next value
(Tuesday
) has position 1, and so on.
An assignment statement can be used to define the value of a variable whose type is an enumeration type. The variable
Today : Days; --current day of the week Tomorrow : Days; --day after Todayspecifies that
Today
and Tomorrow
are type Days
and, therefore, can be assigned any of the values listed in the declaration for
type Day
. Consequently, the assignment statements
Today := Friday; Tomorrow := Saturday;assign the values
Friday
to variable Today
and
Saturday
to variable Tomorrow
.
An important aspect of Ada's type system is the notion of attributes. These are characteristics of a type or variable that can be queried by a program. For the case of enumeration types, six important attributes are:
First
, which gives the first or lowest value in the type;
Last
, which gives the last or highest value;
Pos
, which given a value in a type, gives its position in the
type;
Val
, which given a position in a type, gives the value in
that position;
Pred
, which given a value in a type, gives its
predecessor, that is, the value that precedes it in the type; and
Succ
, which, given a value in a type, gives its successor,
that is, the value that follows. Today
is Friday
and Tomorrow
is Saturday
.
Days'First is Monday Days'Last is Sunday Days'Pos(Monday) is 0 Days'Val(0) is Monday Days'Pos(Sunday) is 6 Days'Val(6) is Sunday Days'Pred(Wednesday) is Tuesday Days'Pred(Today) is Thursday Days'Succ(Tuesday) is Wednesday Days'Succ(Today) is Saturday
Because enumeration types are not cyclical (i.e., do not "wrap
around"), the queries Days'Pred(Monday)
and
Day'Succ(Sunday)
are undefined and would cause a run-time
exception--namely, the raising of Constraint_Error
--if attempted.
Similarly, if Tomorrow
had the value Sunday
,
Days'Succ(Tomorrow)
would cause an exception. Whether the
assignment statement
Tomorrow := Days'Succ(Today);would cause an exception depends on the value of
Today
; it cannot cause a compilation error because the value of
Today
is usually unknown at compilation time.
In the next chapter you will see some examples of how to use careful checking of values in order to prevent exceptions from being raised.
SYNTAX DISPLAY
Attribute Query
Traffic_Light_Colors'First Days'Succ(Wednesday) Days'Pos(Today)
One of the most convenient Ada features for using enumeration types
is a built-in input/output package for reading and displaying enumeration
literals. Within Ada.Text_IO
is a generic package
called Enumeration_IO
, which cannot be used immediately.
Instances must be created; each instance is "tailored" to read and
display exactly the literals in a specific enumeration type. For example, in a
program in which the type Days
is defined and the variable
declaration Today:Days
appears, we could write
PACKAGE Day_IO IS NEW Ada.Text_IO.Enumeration_IO(Enum=>Days);which would give us the ability to read a value from the keyboard into
Today
or to display the value of Today
on the screen, using procedure calls like
Day_IO.Get(Item => Today); Day_IO.Put(Item => Today, Width => 10);
In the case of Get
, the exception
Data_Error
is raised if the value entered on the keyboard is not
one of the seven literals in Days
. In this manner the input/output
system automatically checks the validity of the value entered, making sure that
it is a legal value in the enumeration type.
SYNTAX DISPLAY
Enumeration Get Procedure
instance.Get (Item => variable );
Day_IO.Get (Item => Some_Day);
Enumeration_IO
for
some enumeration type. The next string of characters entered at the keyboard is
read into variable (of the same enumeration type). Any leading blank
characters or RETURN
s are ignored. The first nonblank character
must be a letter, and the characters must form an identifier. The data string
is terminated when a nonidentifier character is entered or the space bar or
RETURN
key is pressed.
If the identifier read is not one of the literals in the enumeration type
for which instance was created, Data_Error
is
raised.
SYNTAX DISPLAY
Enumeration Put Procedure
instance.Put (Item => variable , Width => field
width, Set => Text_IO.Upper_Case
or Text_IO.Lower_Case);
Day_IO.Put (Item => Some_Day, Width => 5, Set => Lower_Case);
Width
positions on the screen. If the value would occupy
less than Width
positions, it is followed by the appropriate
number of blanks; if the value would occupy more than Width
positions, the actual number of positions is used. If Width
is
omitted, a compiler-dependent width is used by default. The standard values
Text_IO.Upper_Case
and Text_IO.Lower_Case
are used to
determine the form of the displayed value. If Set
is omitted, the
value is displayed in uppercase.
Case Study: Translating from English to French Color Names
Your roommate comes from France, and you are taking a watercolor-painting class together. You would like to have the computer give you some help in remembering the French names of the major colors, so that communication with your roommate will be easier. You'd like to enter an English color name on the keyboard and let the program display the corresponding French name. The English color names are white, black, red, purple, blue, green, yellow, and orange; the French color names are blanc, noir, rouge, pourpre, bleu, vert, jaune, and orange.
The French and English colors can be represented by two enumeration typesFrench_Colors
and English_Colors
and can be read and
displayed using two instances of Enumeration_IO
, which we will
call French_Color_IO
and English_Color_IO
.
Problem Data Types:
English colors, an enumeration type:
TYPE English_Colors IS (white, black, red, purple, blue, green, yellow, orange);
French colors, also an enumeration type:
TYPE French_Colors IS (blanc, noir, rouge, pourpre, bleu, vert, jaune, orange);
Problem Inputs:
English color (Eng_Color : English_Colors).
Problem Outputs:
French color (Fr_Color : French_Colors).
We were careful to list the French and English colors in the same order, sogiven an English color, the corresponding French color will be in the same position in the French color type. The program depends on this correspondence, which gives us the following algorithm.
1. Prompt the user to enter one of the eight English colors,
Eng_Color
.
2. Find the corresponding French color, Fr_Color
.
3. Display the French color.
The only step needing refinement is step 2. We can find the French color
corresponding to a given English one by using the Pos
and
Val
attributes. Since the French and English colors have
corresponding positions, we can find the position of the English color in its
type, then use that position to find the corresponding value in the French
type. To do this we shall use a program variable Position
of type
Natural
to store the color position within its type.
Step 2 Refinement
2.1. Save in Position
the position of Eng_Color
in
its type.
2.2. Save in Fr_Color
the corresponding value in the French
type.
This algorithm depends upon each of the French colors being in the same
position in its type as the corresponding English color. Since the number of
colors is relatively small, all the cases can be checked to be sure the two
color types were given correctly. We also need to test for invalid input, for
example, a word or other sequence of characters that is not an English color.
If an invalid token is entered, Data_Error
should be raised and
the program should halt.
The complete program is shown in Program
3.5. The program begins with a context clause for Text_IO
.
Within the program, the two color types are defined and instances of
Enumeration_IO
are created to read and display values of these
types. Finally, the sequence of statements implements the refined algorithm
just developed.
Program 3.5
WITH Ada.Text_IO; PROCEDURE Colors IS ------------------------------------------------------------------------ --| Displays a French color, given the corresponding English color --| Author: Michael B. Feldman, The George Washington University --| Last Modified: July 1995 ------------------------------------------------------------------------ TYPE English_Colors IS (white, black, red, purple, blue, green, yellow, orange); TYPE French_Colors IS (blanc, noir, rouge, pourpre, bleu, vert, jaune, orange); PACKAGE English_Color_IO IS NEW Ada.Text_IO.Enumeration_IO (Enum => English_Colors); PACKAGE French_Color_IO IS NEW Ada.Text_IO.Enumeration_IO (Enum => French_Colors); Eng_Color : English_Colors; Fr_Color : French_Colors; Position : Natural; BEGIN -- Colors Ada.Text_IO.Put (Item => "Please enter an English color > "); English_Color_IO.Get (Item => Eng_Color); Position := English_Colors'Pos(Eng_Color); Fr_Color := French_Colors'Val(Position); Ada.Text_IO.Put (Item => "The French color is "); French_Color_IO.Put (Item => Fr_Color, Set => Ada.Text_IO.Lower_Case); Ada.Text_IO.New_Line; END Colors;Sample Run
Please enter an English color > blue The French color is bleu
The sample run gives one test. To complete the test plan, run the other testsincluding one for invalid input.
Today
(type
Day
) is Thursday
before each operation.
a. Day'Pos(Monday) e. Day'Succ(Sunday) b. Day'Pos(Today) f. Day'Pred(Monday) c. Day'Val(6) g. Day'Val(0) d. Today < Tuesday h. Today >= Thursday
Copyright © 1996 by Addison-Wesley Publishing Company, Inc.