• Aucun résultat trouvé

ENUMERATED SCALAR TYPES

Dans le document Turbo Tutor A Self-Study (Page 121-126)

Good programming style means being considerate of other program-mers who may have to read and understand your code. For example, if you want to use a variable to hold a day of the week in your program, you could declare a variable DayOjWeek of type integer, and then use numbers for the days. But which should be the first day of the week, Sunday or Monday? And, should the fIrst day of the week be repre-sented by a 0 or a 1? If another programmer tries to modify your program, that person will have to determine what number stands for which day.

The way to address these potential problems is not to declare DayOj

~ek to be of type integer. Instead, you can declare a type specifically for the purpose of holding a day of the week, and enumerate, or list, the values it can have:

progral Day_Of_Week_Example;

type

Days = (Monday,Tuesday,Wednesday,Thursday, Friday,Saturday,Sunday);

var DayOfWeek : Days;

begin

DayOfWeek := Thursday;

if DayOfWeek = Saturday then

Writeln('It"s Saturday. Why are you at work?');

end.

Now there is absolutely no confusion over which days are represented by which numbers; they are represented by their actual names. This way, any Pascal programmer who looks at your program will know that the value Thursday is assigned to the variable DayOjWeek.

As you can see from the example, to declare a scalar type you must first give an identifier for the type, then list, in order, identifiers for all of the values the type can have. You can declare scalar types for just about any set of values, including those with no inherent order. However, if order is important, you must declare your list of values from the first to the last.

In a Pascal program, you defme user.,..defined types in the declaration part, in the section called the type definition part. The syntax of this part of the program is shown in Figure 10-1.

type definitlonpart

~

identifier

~

Figure 10-1 Syntax Diagram of Type Definition Part

Each type definition names the type to be defmed, then tells the compiler the details of the type. An enumerated scalar type is a simple type (see Figure 10-2). The unshaded part of this diagram shows the syntax for the specification of an enumerated scalar type.

simple type -~.

Figure 10-2 Syntax Diagram of Simple Type

It is important to remember that when you list the values of an enumerated type, you are in fact declaring the names of those values as identifiers. It is therefore not legal to declare:

type

Days = (Monday,Tuesday,Wednesday,Thursday, Friday,Saturday,Sunday);

DaysOff = (Saturday,Sunday);

because to do so would be to declare Saturday and Sunday twice. In Pascal, each identifier must have one, and only one, type.

Ordinal Values

All enumerated scalar types (and, indeed, all scalar types) are inherently ordered. In other words, there is a lowest value, a highest value, and a number of distinct values in between. In the data type Days in the previous example, Monday is the lowest value and Sunday is the highest value. Tuesday through Saturday are the values between the lowest and highest values. The lowest value is considered to have an

Defined Scalar Types 103

ordinal value of 0, while the highest value has an ordinal value equal to the total number of values defined, minus 1 (because we started counting at 0). For example, here are the ordinal values of the type Days:

Element Ordinal Value

Monday 0

Tuesday 1

Wednesday 2

Thursday 3

Friday L;

Saturday 5

Sunday b

Standard Functions for Scalar Types

To simplify the use of enumerated types, and scalar types in general, the Pascal language provides certain functions or operations that let you manipulate objects of these types. In particular, these functions help you to fmd:·

• The value that comes before a value of the type (its predecessor).

• The value that comes after a value of the type (its successor).

• The position of a value in the list of values in the type defmition.

Here's a scenario that will help explain why this information might be useful. Imagine that in your program you have defined the type Days and two variables of that type, DayOjWeek and NextDay:

type

Days = (Monday,Tuesday,Wednesday,Thursday, Friday,Saturday,Sunday);

var DayOfWeek, NextDay : Days;

..

Now suppose that somewhere in your program you want to set NextDayequal to the day following DayOjWeek. How do you do it?

Well, . one thing you cannot do is attempt to add 1 to the value of DayOjWeek. The statement

NextDay := DayOfWeek + 1;

will cause the compiler to give you the error message "Type Mismatch Error" -and rightly so. The operation of addition is not defmed for objects of the type Days. Yet, we know intuitively that we want an operation that somehow adds one to a day of the week, finding its

successor in the list of weekdays. Pascal comes to the rescue by providing exactly this operation in the form of the Suee (for successor) function. Using this function, we can write

NextDay := Succ(DayOfWeek);

and achieve the desired effect. If DayOjWeek has the value Tuesday, NextDay is assigned the value Wednesday; ifit's Monday, NextDay will become Tuesday, and so on. A fonction is an operation that takes one or more values (called parameters, or sometimes arguments) and uses them to produce a new value. (The sine function, for instance, takes an angle and returns a number that is related to that angle.) In the previous example, we made the function Suee work on the parameter DayO}

Week to produce (or return) a new value, which was the next value in the type Days. The new value was then assigned to the variable NextDay.

The Sua function is one of three predefined "standard" functions that manipulate objects of scalar types; the other two are Pred and Ord.

As you might have already guessed, the Pred function does exactly the reverse of what the Suee function does: it returns the predecessor of the value given to it as a parameter. The Ord function returns the ordinal value of its parameter.

Here are some examples of the results of using these functions. Given that at a particular instant DayOjWeek = Wednesday, then:

pred(DayOfWeek) start with an ordinal value of O. For values of type integer, Ord returns the actual integer value, so there really is no reason to use Ord with integer types (or byte types, for that matter). After all, you can look at the integer and see its ordinal value! In the earlier examples, we also demonstrated that it is perfectly legal to nest functions-that is, to apply a function to the result of another. The expression Pred(Pred(DayO}

Week)) is a convenient way to get the day two days before DayOjWeek.

Defined Scalar Types 105

Cyclical Enumerated Types-Avoiding Range Errors

One thing to watch out for when using Succ and Pred is the problem of searching for a nonexisting successor or predecessor of an existing value. For instance, suppose the variable DayOjWeek in the previous example had the value Sunday, and you tried to assign

NextDay := Succ(DayOfWeek);

What would happen? Well, Turbo Pascal has no way of knowing that the days of the week run in a cycl~that is, that the "successor" of the last value of the type is the first value of the type. So instead, it tries to assign to NextDay a value with the ordinal value 7 (one more than the ordinal value of Sunday, which is 6).

The result of this assignment depends on the conditions present when you compiled your program. If you tell the compiler to range-check (explained in the next section), it will realize that there is no "successor"

for Sunday, and will stop the program and display an error message. If the compiler is not range-checking (which is the default), it will not catch the error, and your program will behave erratically.

Neither of these is a desirable condition. To achieve the correct result, use an if statement to handle the special case:

if DayOfWeek = Sunday then NextDay Monday else

NextDay := Succ(DayOfWeek);

While we haven't described the if statement in detail yet, the preceding one is very close to what actually needs to be done. If DayOjWeek has the value Sunday, then we want to explicitly set NextDay to the value Monday; otherwise, the Succ function will provide the correct value.

Exercises Rewrite the previous code fragment to set the variable Yesterday to the day before DayOjWeek. How do you handle Sun-day?(Solutions are in Appendix B.)

Of course, the same situation can arise even if the enumerated type in question is not cyclical-though it is less likely. If you defined the type Rank = (Peon, Manager, SeniorManager, VicePresident,

President, Chairperson);

and tried to find the next rank after Chairperson, the same type of error could occur. You must construct your program so that this does not happen.

Range-Checking

While defined scalar types are designed to help you restrict the values of your variables to fall within certain predetermined limits, Turbo Pascal does not enforce those limits unless it is specifically told to do so. For

instance, the previous example, in which we attempted to take the successor of the last value of an enumerated type, would not cause an error message in Turbo Pascal unless the feature called range-checking was enabled.

Range-checking is turned on by a special kind of comment called a compiler directive. A compiler directive consists of a comment in which the first character is a dollar sign ($) and the remaining characters fit the pattern(s) of one or more legal directives.

The compiler directive that turns on range-checking is {$R +}. We recommend that you put this directive before the program heading of every program you write; it will almost certainly save you many hours of frustrated debugging. Only if your program must run at maximum speed, or if it is about to overflow memory, should you omit this directive or use the directive {$R-} to turn range-checking off.

Note that your programs will compile and run faster with range-checking off. However, since turning range-range-checking off may hide bugs, we recommend it only for well-tested programs that are being published as finished products.

Dans le document Turbo Tutor A Self-Study (Page 121-126)