Enumerated Types

An enumerated type is a type which includes in its definition a list of all of the allowed values for variables of that type. As a programmer, you can define types relevant to the context of your program to make it more readable. A program about the planets could use:

type
  TPlanet = (Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto);
  TGasGiant = Jupiter .. Neptune;
var
  Planet : TPlanet;

Any of the listed planets could be assigned to Planet. A card game program might use TSuit = (Clubs, Diamonds, Hearts, Spades); .

Note the syntax: values in the list are NOT in quotes.

The order in which the values are listed is important for the ordinal functions ord, pred, succ, low, and high described below. Enumerated types, characters, most integer types and subranges of these three types are ordinals. TGasGiant is an example of a subrange. For an ordinal, each value except the first has a unique predecessor (obtained by applying the pred function to it) and each value except the last has a unique successor (returned by the succ function).

The ord function returns the ordinality (usually the order) of the value, beginning with 0 for the first value in an enumerated type. Using the examples above, ord(Clubs) equals 0 and ord(Saturn) equals 5. Note that when a subrange is declared, the ord function returns the ordinality of the base type. For the planets, Saturn is the sixth value in the base type TPlanet, giving an ordinality of 5 (and not an ordinality of 1 resulting from Saturn being the second value of the subrange TGasGiant). When the ord function is applied to a character, its ASCII value is returned, e.g. ord('A') equals 65.

An enumerated-type value such as Mercury can be used as an index to a suitably declared array e.g.

var
  PlanetDiameters : array [Mercury .. Pluto] of integer; 
begin 
  PlanetDiameters[Mercury] := 5000;

An enumerated-type variable such as Planet can be used as a stepper variable in a loop e.g.

for Planet := Mercury to Earth do

and as a decision variable in a case statement e.g.

case Planet of
  Mercury : writeln('Approx. diameter of Mercury in km: ', PlanetDiameters[Mercury]);
  Venus :Earth :end;

An example of an assignment is Planet := Venus;. After this assignment, succ(Planet) returns Earth and pred(Planet) returns Mercury.

The demonstration program uses TMonth, a commonly used enumerated type. The program shows how to declare the subranges TMonthQuarter1 and TSpringMonth. In order to demonstrate various coding possibilities, a different method is used to calculate the total rainfall for each of the four seasons.

The following code uses the functions low and high to return the first and last values, respectively, in TSpringMonth.

for SpringMonth := low(TSpringMonth) to high(TSpringMonth) do ...

The equivalent code for summer is more straightforward:

for Month := June to August do

The code for autumn uses a repeat-until loop and the function succ, and the total for winter is calculated simply by summing the relevant monthly totals.

program EnumeratedTypes;
{$APPTYPE CONSOLE}
uses
  SysUtils;
type
  TMonth =(January, February, March, April, May, June, July, August,
         September, October, November, December);
  TMonthQuarter1 = January .. March;
  TSpringMonth = March .. May;
const
  AverageLondonRainfall : array [January .. December] of integer =
                          (61, 36, 50, 42, 45, 46, 46, 44, 43, 73, 45, 59);
  MonthNames : array [January .. December] of string =
     ('January', 'February', 'March', 'April', 'May', 'June',
      'July', 'August', 'September', 'October', 'November', 'December');
var
  Month: TMonth;
  MonthQuarter1 : TMonthQuarter1;
  SpringMonth : TSpringMonth;
  SpringTotal, SummerTotal, AutumnTotal, WinterTotal, MonthNum : integer;
begin
  //Monthly
  writeln('The average monthly rainfall (mm) in London is as follows.');
  for Month := January to December do
    begin
      writeln(MonthNames[Month] :9, ': ' ,AverageLondonRainfall[Month]);
    end;
  writeln;
  //Spring
  SpringTotal := 0;
  for SpringMonth := low(TSpringMonth) to high(TSpringMonth) do
    begin
       SpringTotal := SpringTotal + AverageLondonRainfall[SpringMonth];
    end;
  writeln('Total average rainfall (mm) for Spring: ', Springtotal);
  //Summer
  SummerTotal := 0;
  for Month := June to August do
    begin
       SummerTotal := SummerTotal + AverageLondonRainfall[Month];
    end;
  writeln('Total average rainfall (mm) for Summer: ',SummerTotal);
  //Autumn
  AutumnTotal := 0;
  Month := August;
  repeat
     Month := succ(Month);
     AutumnTotal := AutumnTotal + AverageLondonRainfall[Month];
  until Month = November;
  writeln('Total average rainfall (mm) for Autumn: ', AutumnTotal);
   //Winter
  WinterTotal := AverageLondonRainfall[December] + AverageLondonRainfall[January] +
                 AverageLondonRainfall[February];
  writeln('Total average rainfall (mm) for Winter: ',WinterTotal);
  writeln;
  //Selected month
  write('Which month in the first quarter? Type 1 for Jan, 2 for Feb, 3 for Mar. ' );
  readln(MonthNum);
  writeln;
  case MonthNum of
    1: MonthQuarter1 := January;
    2: MonthQuarter1 := February;
    3: MonthQuarter1 := March;
  end;
   writeln('Average rainfall (mm) in London for ',MonthNames[MonthQuarter1],
                ':  ',AverageLondonRainfall[MonthQuarter1]);
  readln;
end.

Chistopher Winward makes impressive use of enumerated types in his calculator.

Features introduced:
  • Declaration of enumerated type
  • Functions ord, pred, succ, low, and high for use with ordinal types
  • Subranges
  • Use of an enumerated-type value as
    • the value of an array index
    • a value in a control expressions in a loop
    • a decision value in a case statement
  • Use of an enumerated-type variable as
    • an array index
    • a stepper variable in a loop
    • a decision variable in a case statement

Experimenting

  1. In Pascal, Boolean is an enumerated type. Try using the expressions low(MyBoolean) and high(MyBoolean) and apply the functions ord, succ and pred to Boolean variables.
  2. Find out what happens when you apply the pred function to a variable holding the first value in an enumeration.
  3. Write a program based on planet data to use all of the features introduced in this section. The user should be able to select a planet then obtain some data about it. Declare a subrange TInnerPlanet with values Mercury, Venus, Earth and Mars.
  4. Look through the programs you have written to find one which could be made easier to read by the use of at least one enumerated type, then modify the code accordingly.
  5. Write a program from scratch to practise what you have learned from this section.
Programming - a skill for life!

Pascal Programming Tutorials