• Aucun résultat trouvé

Procedures and

Dans le document Turbo Tutor A Self-Study (Page 146-154)

THE CASE STATEMENT

12 Procedures and

Functions

In previous chapters, you've seen procedures and functions (known collectively as subprograms) used in some of the sample programs.

You've been given a general idea of how they're used, and you're probably anxious to learn more. (Appendix C provides a complete list of standard Pascal procedures and functions.)

This chapter will teach you more. First, we'll describe the general concept of a subprogram, and then show you how (and where) to place them in your main program. We'll then cover the idea of scope, which determines what the identifiers used in a subprogram mean, and from where a subprogram may be called. We'll end with a discussion on parameters-the data objects you tell a subprogram to work on-and give you a taste of what you can do with them.

SUBPROGRAMS

You've learned that a Pascal program must have a program heading, a declaration part, and a statement part. You've also learned that each statement in the statement part is normally executed in order-from beginning to end-unless a conditional (if) or iterative statement (for, repeat ... until, or while) alters the flow of control.

The iterative statements that we've learned about are perfect for repeat-ing a statement, or group of statements. However, what do you do if you want to repeat a group of statements in several distinct places in your program, rather than only within the same loop?

Here's a simple example of a situation where a subprogram might come in handy. The following sequence of statements asks the user for a number, then checks the number to see if it is in range. If the number is in range, it is assigned to the variable New Number.

127

Writeln('Please enter an integer from "

'Minimum, , to " Maximum,': ');

Readln(Temporary);

{Temporary is of type integer, or a subrange thereof}

while (Temporary ( Minimum) or (Temporary ) Maximum) do begin

Writeln('The integer you have entered is out of range.');

Writeln('Please try again: ');

Readln(Temporary);

end;

New Number := Temporary;

{NewNumber is of type integer, or a subrange thereof}

Now, suppose there are several places in your program where you want to perform this same function-widely separated by tens or even hundreds of lines. You could copy all of the statements given here, exactly as shown, into each place; however, this would increase the size of both your source and executable ft.les. Also, if you wanted to make a change; you might need to ft.nd and alter every occurrence. Fortu-nately, the Pascal language provides a solution. Instead of copying the group of statements, you can give it a name, and cause the entire group to be executed by merely mentioning that name. Such a group of statements is called a subprogram.

The simplest kind of subprogral!l in Pascal is called a procedure. To create a procedure, you declare its name as an identift.er (as you declare all identift.ers), and present the compiler with the code that is to go by that name. The syntax of a procedure declaration is shown in Figure 12-1.

~G)~--- ••

Figure 12-1 Syntax Diagram of Procedure Declaration

Each procedure declaration contains the reserved word procedure, followed by the identift.er that is to be the name of that procedure.

Then, there appears an optional list of parameters (described more fully later), a semicolon, a procedure body, and a closing semicolon.

A procedure body is usually just a block-the exact same sequence of declaration part and statement part that comes after the heading of a program. This sequence reinforces the idea that procedures-and sub-programs in general-are really small sub-programs within a larger pro-gram. The syntax of the body is shown in Figure 12-2.

body

external declaration Figure 12-2 Syntax Diagram of Body

Where do you put subprograms in your program? In standard Pascal, you place them in the declaration part, after all other declarations and before the opening begin of your program. (Turbo Pascal, as you may remember, is more flexible, and lets you place them anywhere in the declaration part.) A subprogram can declare its own constants and variables, just like the main program. Can you declare a subprogram within a subprogram? Yes, you can, just like you would in a regular program. And you can declare subprograms within that subprogram, and so on, ad infinitum (well, not quite; all compilers have their limits).

Now, let's rewrite our earlier sequence of statements as a procedure and show how we might build a small program around them.

program Sample;

const Ten = 10;

var NewNumber, Index : integer;

procedure GetNumber;

{ Get a number from the user and store } { it in the global variable NewNumber } canst

Minimum 0;

Maximum = 25;

type

Response = Minimum .. Maximum;

{ A type for a legal response var

Temporary : Response;

{ A temporary place for the user's integer } begin {Statement Part of procedure GetNumber

Writeln('Please enter an integer from "

Minimum, ' to " Maximum, ': ');

Readln(Temporary);

while (Temporary ( Minimum) or (Temporary) Maximum) do begin

Writeln('The integer you have entered is not' 'between 0 and 25, ');

Writeln('inclusive. Please try again.');

Readln(Temporary);

end;

Procedures and Functions 129

NewNumber := Temporary;

end; { procedure GetNumber

begin { Statement Part of program Sample } GetNumber;

for Index := 1 to Ten do begin

GetNumber;

end;

GetNumber;

case NewNumber of

0: Writeln('You have selected option 0');

25: Wri teln ('This is option 25: ');

end;

end. { of progra~ Sample}

In this example, const, type, and var declarations have been deliber-ately included in the subprogram to demonstrate that the subprogram can indeed have these parts.

Besides avoiding code duplication, subprograms help to make a pro-gram easier to understand. Procedure names that specify a particular action to be taken can clarify a program, whereby the main actions of a program are shown in the statement part and the details of those actions are "hidden" in the functions and procedures. Changes and improvements that are made to subprograms can instantly have an effect on many other parts of the code-without any additional rewrit-ing. Also, when many people are at work on a program, each pro-grammer can write one or more subprograms, then allow them to be combined into the finished product. This modular approach allows each author to perfect his or her part of the program without having to directly modify the work of others.

SCOPE

Since it is possible to define and declare types, constants, and variables in the declaration part of a procedure, you may well ask: "What happens if an identifier is declared in the main program, and then another with the same name is declared in the subprogram? Or, what if two subprograms declare identifiers with the same names?"

Well, your first guess might be that the compiler would indicate an error, since each identifier can only refer to one thing if the program is to be unambiguous. However, if this were true, then the modular approach to programming would be difficult. Each programmer would have to know all of the names that every other programmer used, and combining their work might cause unexpected conflicts.

To avoid this problem, the concept of scope was developed. The Pascal scope rules specify, in a rigorous way, what object any identifier refers to at a given time. We'll cover the first two scope rules right now, and the third when we get to the section on recursion later in this chapter.

Scope Rule # 1: Each identifier has meaning only within the block in which it is declared, and only after the point in that block at which it is declared.

Thus, in the previous example, the variable Temporary only has mean-ing within the procedure GetNumber, and even then only after its declaration. By the same rule, the declarations

const

Minimum 0;

Maximum 25;

and type

Response = Minimum .. Maximum;

{A type for a legal response}

could not have occurred in the reverse order. If they had, the constants Minimum and Maximum would not have been defmed when the type Response was defined using them, and the compiler would have indi-cated an error.

Another consequence of the first scope rule is that the procedure GetNumber can refer to, and in fact assign a value to, variables that were declared before GetNumber in the declaration part of the program Sample. Thus, the statement

NewNumber := Temporary;

does what one would expect, and assigns the value of Temporary to the variable New Number, which was declared in the main program. An identifier like New Number, which is declared at a higher level and is accessible within GetNumber, is said to be global to the procedure GetNumber. The converse, however, is not true. In the main program, we could not write the statement

Temporary := NewNumber;

because the variable Temporary is not defined outside of GetNumber.

Temporary is said to be local to GetNumber, and is not visible outside of that block.

Procedures and Functions 131

Scope Rule #2: If a global identifier is redefined within a block, then the innermost (most deeply nested) defmition takes precedence from the point of declaration until the end of the block.

What does this mean? The following "skeleton" program will help to illustrate. following identifiers are visible:

identifier I defined in

compilers, ignores the program heading entirely, including the program name. } following identifiers are visible:

identifier I defined in

end; following identifiers are visible:

identifier : defined in following identifiers are visible:

identifier : defined in B, C, J, K, R, S, T, U : A

}

end. program A }

In each procedure within this program (and also within the statement part of the main program), we've listed which identifiers are visible and which objects they refer to.

To fully understand how this information is derived, it helps to "pre-tend" that you are the compiler, scanning the program from top to bottom. Each time you encounter a definition that overrides a previous one, you make a note of the new definition, and use it until the current block is exited. When you exit a block, all the identifiers declared locally within that block become undefined, and all the identifiers that were temporarily "hidden" by definitions in that block become visible once more.

Procedures and Functions 133

const

begin { Statement Part of procedure SetA }

A : = 1;

end; { procedure SetA}

begin { Statement Part of program Scope2 }

A : = 3;

SetA;

Writeln(A)

end. { program Scope2 }

Dans le document Turbo Tutor A Self-Study (Page 146-154)