| Introduction
|
Aims
| In almost every programming job, there is some task that needs to be done over and over again. For example: The job of processing a file of records is an iteration of the task - get and process record. The job of getting the sum of a stream of numbers is an iteration of the task - get and add number. These jobs are accomplished using iteration constructs. Other computer languages support a variety of looping constructs, including Repeat, While, and For loops. Although COBOL has a set of looping constructs that is just as rich as other languages - richer in some cases - it only has one iteration verb. In COBOL, all iteration is handled by the PERFORM verb.
Iteration constructs and their COBOL equivalents
This tutorial demonstrates how the PERFORM verb is used to create Repeat loops, While loops and For loops. It will also demonstrate how the PERFORM is used to transfer control to an open subroutine.
|
Objectives
| By the end of this unit you should -
|
Prerequisites
| Introduction to COBOL Declaring data in COBOL Basic Procedure Division Commands Selection Constructs
|
| PERFORM..Proc
|
Introduction
| If you have written programs in another language, you will probably have come across the idea of a subroutine; a block of code that is executed, when invoked by name. What you may not have realized is that there are essentially two types of subroutine.: Open Subroutines If the language you learned was C or Modula-2, you are probably familiar with closed subroutines. If you learned BASIC, you may be familiar with open subroutines. Open subroutines. Although an open subroutine. is normally executed by invoking it by name, it is also possible, unless the programmer is careful, to fall into it from the main program. In BASIC, the GOSUB command allows programmers to implement open subroutines. Closed subroutines. In C and Modula-2, Procedures and Functions implement closed subroutines. COBOL subroutines.
|
PERFORM format 1 syntax |
Unless it is otherwise instructed, a computer running a COBOL program processes the statements of the program in sequence, starting at the top of the program and working its way down until the STOP RUN is reached. The PERFORM verb is is one way of altering the sequential flow of control in a COBOL program. The PERFORM verb can be used for two major purposes;
While the other formats of the PERFORM verb implement various types of iteration, the format shown here is used to transfer control to an out-of-line block of code. The block of code may be one or more paragraphs, or one or more sections.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
How this format works |
This format of the PERFORM verb, transfers control an out-of-line block of code. When the end of the block is reached, control reverts to the statement (not the sentence) immediately following the PERFORM. 1stProc and EndProc are the names of paragraphs or sections. When the PERFORM..THRU is used, the paragraphs or sections from 1stProc to EndProc are treated a single block of code. COBOL programmers typically use this format of the PERFORM to divide a program into open subroutines. These subroutines are not as robust as the user-defined Procedures or Functions found in other languages, but when COBOL programmers require that kind of partitioning, they use contained or external subprograms. Open subroutines. are useful because they allow a programmer to code a subroutine. without the formality or overhead involved in coding a Procedure or Function. PERFORM general notes.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Why use this format? |
This format of the PERFORM verb is used to make programs more readable and maintainable. When we can identify a block of code in the program that performs some specific task (e.g. Prints the report headings) this format allows us to replace the details of how the task is being accomplished with a name that indicates what is being done (e.g. PERFORM PrintReportHeadings). We should use this format of the PERFORM to divide our programs into a hierarchy of tasks and sub-tasks.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PERFORM..PROC example |
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Self Assessment Questions |
Now that you understand how this version of the PERFORM works, test your understanding by referring to the example program above and answering the following questions.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Using the PERFORM..THRU | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Introduction |
Although the PERFORM..THRU has dangers, as outlined above, it can be a useful construct for dealing with errors. Sometimes we need to stop executing a paragraph if an error is detected. The PERFORM..THRU provides a mechanism which allows us to do this. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Coping with errors |
In the program fragment below, the programmer does not want to execute the remaining statements in the paragraph if an error is detected. The solution he has adopted, based on nested IF statements, is somewhat cumbersome.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Using the PERFORM..THRU |
In the program fragment below, the PERFORM..THRU is used to deal with detected errors in a more elegant manner. When the statement PERFORM SumSales THRU SumSalesExit is executed, both paragraphs will be performed as if they were one paragraph. The GO TO jumps to the exit paragraph which, because the paragraphs are treated as one, is the end of the block of code. This technique allows the programmer to skip over the code he does not want executed if an error is detected. The EXIT statement in the SumSalesExit paragraph is a dummy statement. It has absolutely no effect on the flow of control. It is in the paragraph merely to conform to the rule that every paragraph must contain at least one sentence and in fact it must be the only sentence in the paragraph. It may be regarded as a comment.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PERFORM..THRU restrictions |
The PERFORM..THRU and GO TO are dangerous constructs which, if used unwisely, will make your programs very difficult to read, understand and maintain. Because of this, the PERFORM..THRU should only be used to set up a paragraph exit as in the example above and it should only cover two paragraphs. No other use of the PERFORM..THRU is acceptable. This is also the only time the GO TO should be used.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PERFORM..TIMES | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Introduction |
The PERFORM..TIMES format has no real equivalent in most programming languages. This format allows a block of code to be executed a specified number of times.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PERFORM..TIMES Syntax |
This format of the PERFORM executes a block of code RepeatCount number of times before returning control to the statement following the PERFORM. Like the remaining formats of the PERFORM, this format allow two types of execution.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
In-line vs Out-of-line |
In-line execution The block of code to be executed starts at the keyword PERFORM and ends at the keyword END-PERFORM (see example program below). Out-of-line execution Some guidelines Where out-of-line code is executed by a format 1 PERFORM, the code should perform some specific function and that function should be identified by the paragraph name chosen. Where an out-of-line paragraph consists of 5 statements or less, there should be a good reason for placing these statements in a separate paragraph. Programmers should try to achieve a balance between in-line and out-of-line code. The program should not be too fragmented, nor too monolithic.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example |
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Self Assessment Questions |
Examine the program above and write out what it will display on the screen. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PERFORM..UNTIL | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Introduction |
This format of the PERFORM is used where the while and do/repeat constructs are used in other languages. It causes a block of code to be iteratively executed until some terminating condition is reached.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PERFORM..UNTIL syntax |
Notes The WITH TEST AFTER phrase causes the PERFORM to act do/repeat loop and the condition is tested after the loop body is entered. The WITH TEST BEFORE phrase is the default and so is rarely explicitly stated.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
How the PERFORM..UNTIL works |
The flowcharts below show how the PERFORM..UNTIL works. As you can see the terminating condition is only checked at the beginning of each iteration (PERFORM WITH TEST BEFORE) or at the end of each iteration (PERFORM WITH TEST AFTER). The terminating condition is only checked at the beginning of each iteration (PERFORM WITH TEST BEFORE) or at the end of each iteration (PERFORM WITH TEST AFTER). If the terminating condition is reached in the middle of the iteration, the rest of the loop body will still be executed; although the terminating condition has been reached, it cannot be checked until the current iteration has finished. Although the PERFORM WITH TEST BEFORE is often said to be equivalent to a while loop, this is not entirely true. In a while loop, the condition is tested to see whether the iteration should continue (for example, while(Letter != 's') ) but in a PERFORM, the condition is tested to see if the iteration should stop (For example, PERFORM WITH TEST BEFORE UNTIL Letter = "s") .
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TEST BEFORE Vs TEST AFTER |
Beginning programmers often ask; when should they use the WITH TEST BEFORE loop, and when should they use the WITH TEST AFTER. There really isn't a cookbook answer to this. It's a matter of experience. But we can identify some circumstances, when it is better to use the WITH TEST BEFORE, than the WITH TEST AFTER. When you need to process a stream of data items, and don't know the size of the stream, and can't detect the end of the stream until you attempt to retrieve the next item, then a test before loop, is the best construct to use. If the end of the stream can be detected when the last item is retrieved, then the appropriate construct is probably a test after loop.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The "read ahead" technique |
Processing a stream of data items of undetermined length, is a common operation in COBOL, because sequential files fall into this category. A useful strategy known as the “read ahead” has been developed for processing sequential files. The central idea of the "read ahead" is that, because the end of the file cannot be detected until an attempt is made to read a record, the Read must be positioned as the last statement in the record processing loop. You can see how this works in the processing template below. With the “read ahead” strategy we always try to stay one data item ahead of the processing. So the Read outside the loop, reads the first record and this record is processed inside the loop. The Read inside the loop, reads the next, and all the succeeding records. When the inside Read detects the end of file, it sets a Condition Name that immediately causes the loop to halt.
This approach to processing a sequential file has two main advantages.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PERFORM..UNTIL comment |
The primary concern of a programmer who creates a loop should be - will the loop terminate. Much of the work of proofs of program correctness goes into proving that the loops in a program are going to terminate. It seems curious then, that in most programming languages the loop condition concentrates on, not whether the loop will end, but on whether the loop will keep going. COBOL is one of the few languages that gets this right. In COBOL, the loop body is executed until the terminating condition is reached. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PERFORM..VARYING | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Introduction |
The PERFORM..VARYING is used to implement counting iteration. It is similar to the For construct in languages like Modula-2, Pascal and C. However, these languages permit only one counting variable per loop instruction, while COBOL allows up to three. Why three? Earlier versions of COBOL only allowed tables with a maximum of three dimensions, and the PERFORM..VARYING was a mechanism for processing them.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PERFORM..VARYING syntax |
Notes The item after the VARYING phrase is the most significant counter, the counter following the first AFTER phrase is the next most significant, and the last counter is the least significant. The least significant counter must go though all its values and reach its terminating condition before the next most significant counter can be incremented. The item after the FROM, is the starting value of the counter. The item after the BY, is the step value of the counter. This can be negative or positive. If a negative step value is used, the counter should be signed (PIC S99, etc.). When the iteration ends, the counters retain their terminating values. As before, when no WITH TEST phrase is used, the WITH TEST BEFORE is assumed. Though the condition would normally involve some evaluation of the counter, it is not mandatory. For instance, the statement that follows is perfectly valid:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PERFORM..VARYING using one counter Example |
The example animation below demonstrates how a simple PERFORM..VARYING, using only one counter, work. Pay particular attention to when the counter is incremented. In the example note that the condition Idx1 = 3 results in only two passes through the loop body.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PERFORM..VARYING using two counter Example |
This example animation demonstrates how a PERFORM..VARYING, with two counters, works. Note how the counter Idx2 must go through all its values and reach its terminating value before the Idx1 counter is incremented. An easy way to think about this is to think of it as a mileage counter. In a mileage counter, the units counter must go through all its values 0-9 before the tens counter is incremented, and the tens counter must go through all its values before the hundreds counter is increment. Note that the first counter mentioned in the PERFORM is the most significant and the next is the next most significant etc.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PERFORM..VARYING Example Program |
In the example program simulates the mileage counter mentioned above. Examine this program an then attempt to answer the Self Assessment Question which follow.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Copyright NoticeThese COBOL course materials are the copyright property of Michael Coughlan. All rights reserved. No part of these course materials may be reproduced in any form or by any means - graphic, electronic, mechanical, photocopying, printing, recording, taping or stored in an information storage and retrieval system - without the written permission of the author. (c) Michael Coughlan Last updated : March
1999 mailto:michael.coughlan@ul.ie | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||