Looping in the basic COBOL Program

These notes will supplement the PowerPoint presentation on looping. Please be sure to look at it and at the sample programs being discussed.

ADDDALP.CBL:

When we first started looking at programs, we looked at a program called ADDDA.CBL which added two numbers together and displayed the answer. That program is shown below.
       IDENTIFICATION DIVISION.
       PROGRAM-ID. ADDPROG.
       AUTHOR. GROCER.
      *ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  INPUT-AREA.
           05  GET-ACCEPT-ANS           PIC X       VALUE SPACES.
           05  FIRST-NUMBER             PIC 999     VALUE 0.
           05  SECOND-NUMBER            PIC 999     VALUE 0.
           05  ADD-ANS                  PIC 9999    VALUE 0.
       PROCEDURE DIVISION.
       MAINLINE.
           DISPLAY "ENTER THE FIRST NUMBER (UNDER 1000)".
           ACCEPT FIRST-NUMBER.
           DISPLAY "ENTER THE SECOND NUMBER (UNDER 1000)".
           ACCEPT SECOND-NUMBER.
           ADD FIRST-NUMBER TO SECOND-NUMBER
               GIVING ADD-ANS.
           DISPLAY "THE ANSWER IS " ADD-ANS.
           DISPLAY "PRESS ENTER TO END THE PROGRAM".
           ACCEPT GET-ACCEPT-ANS.
           STOP RUN.
The revised program we will discuss in this handout is ADDDALP.CBL. This program does the basic math program that we looked at and changes it so that it will keep adding two numbers together until the user decides to stop. The original program simply added two numbers together and the program ended. The difference between these two program is the PERFORM...UNTIL statement.

The PERFORM...UNTIL statement is this program is located in the MAINLINE and is written as:
          PERFORM B-100-PROCESS
              UNTIL GET-ACCEPT-ANS = "Q".
When the statement is executed, it checks the UNTIL first. If GET-ACCEPT-ANS is not equal to Q then the PERFORM does the named paragraph B-100-PROCESS. When all of the commands in that paragraph have been executed and the paragraph is done, control returns to the PERFORM statement. It again checks the UNTIL to see if GET-ACCEPT-ANS is equal to Q. If it is not, then it executes the PERFORM of B-100-PROCESS.

Note that at the bottom of B-100-PROCESS the user is asked to enter Q to end the program or just ENTER to continue. The answer that the user enters is stored in GET-ACCEPT-ANS. This means that the user is controlling the program and deciding when it has run enough times.

When the user finally enters Q, control drops to the next statement in the MAINLINE which is STOP RUN and the program is ended.
       MAINLINE.
           PERFORM B-100-PROCESS
              UNTIL GET-ACCEPT-ANS = "Q".
           STOP RUN.
The whole program is shown below:
       IDENTIFICATION DIVISION.
       PROGRAM-ID. ADDLOOP.
       AUTHOR. GROCER.
      *ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  INPUT-AREA.
           05  GET-ACCEPT-ANS     PIC X       VALUE SPACES.
           05  FIRST-NUMBER       PIC 999     VALUE 0.
           05  SECOND-NUMBER      PIC 999     VALUE 0.
           05  ADD-ANS            PIC 9999    VALUE 0.
       PROCEDURE DIVISION.
       MAINLINE.
           PERFORM B-100-PROCESS
              UNTIL GET-ACCEPT-ANS = "Q".
           STOP RUN.
       B-100-PROCESS.
           DISPLAY "ENTER THE FIRST NUMBER (UNDER 1000)".
           ACCEPT FIRST-NUMBER.
           DISPLAY "ENTER THE SECOND NUMBER (UNDER 1000)".
           ACCEPT SECOND-NUMBER.
           ADD FIRST-NUMBER TO SECOND-NUMBER
               GIVING ADD-ANS.
           DISPLAY "THE ANSWER IS " ADD-ANS.
           DISPLAY "PRESS Q FOLLOWED BY ENTER TO END THE PROGRAM".
           DISPLAY "PRESS ENTER ALONE TO CONTINUE".
           ACCEPT GET-ACCEPT-ANS.
Looking at it another way:

CREATE1.CBL:

This program uses the loop concepts discussed above but the rest of the processing is quite different. In this program, I am taking data in from the screen and using it to write a record on a file that I am creating. When the program ends, I will have a file of data that can be used by other programs.

To do this, I will need the ENVIRONMENT DIVISION to set up the file that I am going to create.
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT PAY-FILE
               ASSIGN TO "A:\PAY.DAT".
Since I am using the ENVIRONMENT DIVISION for files, the next line says INPUT-OUTPUT SECTION. The next line is where I state that what I am actually doing is controlling files. The line is FILE-CONTROL. The SELECT statement actually does the work. The SELECT statement gives the logical name of the file, the name that I will be using in my program and assigns that name to the actual physical file. In this example the actual file is PAY.DAT on the A drive so the physical name is PAY.DAT. The purpose of the SELECT statement is to make the connection between the logical file name and the physical file name so that when I talk about PAY-FILE in my program, the program knows that I am actually talking about the real file PAY.DAT which is being created on the A drive.

Next, I am going to introduce a new section into the DATA DIVISION. It is the FILE SECTION and it is where I describe the file that I set up in the SELECT statement.

       
       DATA DIVISION.
       FILE SECTION.
       FD  PAY-FILE
           DATA RECORD IS PAY-REC.
       01  PAY-REC.
           05  PAY-ID               PIC 9999.
           05  PAY-NAME             PIC X(20).
           05  PAY-TYPE             PIC X.
           05  PAY-RATE             PIC 999V99.
           05  PAY-HOURS            PIC 99.
FD stands for file description. Here is where I describe PAY-FILE. Notice that I am using the same logical name that I used in the SELECT statement. The option clause, DATA RECORD IS PAY-REC gives me additional information. Each of the records on the file called PAY-FILE is going to be named PAY-REC. The 01 level of the FD is where I give the name of the record and then I describe the individual fields on the record at the 05 level. The fields are:
If we add up the lengths of the fields, we get the length of the record. In this example the length is 32. As I set up a record to write on the file, I set it up under PAY-REC.

In the WORKING-STORAGE SECTION, I have defined a 01 WORK-AREA that contains one field named STOP-PROCESSING. I probably should have given this field an initial value of spaces (better coding). This is where the user answer about continuing the processing will be stored.

The entire program is shown below. After the program code, I will discuss the PROCEDURE DIVISION.
       IDENTIFICATION DIVISION.
       PROGRAM-ID. CREATE1.
       AUTHOR. GROCER
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT PAY-FILE
               ASSIGN TO "A:\PAY.DAT".
       DATA DIVISION.
       FILE SECTION.
       FD  PAY-FILE
           DATA RECORD IS PAY-REC.
       01  PAY-REC.
           05  PAY-ID               PIC 9999.
           05  PAY-NAME             PIC X(20).
           05  PAY-TYPE             PIC X.
           05  PAY-RATE             PIC 999V99.
           05  PAY-HOURS            PIC 99.
       WORKING-STORAGE SECTION.
       01  WORK-AREA.
           05  STOP-PROCESSING      PIC X.
       PROCEDURE DIVISION.
       MAINLINE.
                   PERFORM A-100-STARTUP.
           PERFORM B-100-PROCESS.
           PERFORM C-100-WRAPUP.
           STOP RUN.
       A-100-STARTUP.
           OPEN OUTPUT PAY-FILE.
       B-100-PROCESS.
           PERFORM B-200-LOOP
               UNTIL STOP-PROCESSING = "Y".
       B-200-LOOP.
           DISPLAY "ENTER IDENTIFICATION NUMBER".
           ACCEPT PAY-ID.
           DISPLAY "ENTER NAME".
           ACCEPT PAY-NAME.
           DISPLAY "ENTER JOB TYPE".
           ACCEPT PAY-TYPE.
           DISPLAY "ENTER PAY RATE"
           ACCEPT PAY-RATE.
           DISPLAY "ENTER HOURS WORKED".
           ACCEPT PAY-HOURS.
           WRITE PAY-REC.
           DISPLAY "PRESS ENTER TO CONTINUE".
           DISPLAY "PRESS Y FOLLOWED BY ENTER TO QUIT".
           ACCEPT STOP-PROCESSING.
       C-100-WRAPUP.
           CLOSE PAY-FILE.
In this program I am starting to develop a structure. This structure will be even stronger in the next program. First of all, I am developing a way to name my paragraphs. The first paragraph will continue to just have a name, in this case MAINLINE. Other paragraphs will be broken into type and level.

A program must accomplish three things:
To signify these tasks: The top level of paragraphs will be the 100 level. In this program there is only paragraph that is not at that level, it will be given the 200 number to indicate it is at the second level.

The MAINLINE controls the program. It controls setting things up, processing and wrapping up. It also terminates the program with the STOP RUN.

       MAINLINE.
           PERFORM A-100-STARTUP.
           PERFORM B-100-PROCESS.
           PERFORM C-100-WRAPUP.
           STOP RUN.
The A-100-STARTUP paragraph simply opens the file that we defined in the FILE SECTION. Notice that it opens it as OUTPUT because we are going to write the file. The name we used in the SELECT and again in the FD is now used in the open so that we can tie together the physical location of the file and its description as we open it.
       A-100-STARTUP.
           OPEN OUTPUT PAY-FILE.
Once the file is open, control returns to the MAINLINE which then executes B-100-PROCESS.

       B-100-PROCESS.
           PERFORM B-200-LOOP
               UNTIL STOP-PROCESSING = "Y".
This paragraph controls how much processing is done and when it will stop. In this example, the processing will stop when the user enters a Y and therefore STOP-PROCESSING will be equal to a Y. As long as this is not true the B-200-LOOP which processes data keyed in on the screen and writes it in a record on the disk file we have established will continue. Remember, the UNTIL is checked to determine whether or not to PERFORM the named paragraph.

The B-200-LOOP is where the data is brought in and the record is written. It is also where the user decides whether or not to stop the processing.
       B-200-LOOP.
           DISPLAY "ENTER IDENTIFICATION NUMBER".
           ACCEPT PAY-ID.
           DISPLAY "ENTER NAME".
           ACCEPT PAY-NAME.
           DISPLAY "ENTER JOB TYPE".
           ACCEPT PAY-TYPE.
           DISPLAY "ENTER PAY RATE"
           ACCEPT PAY-RATE.
           DISPLAY "ENTER HOURS WORKED".
           ACCEPT PAY-HOURS.
           WRITE PAY-REC.
           DISPLAY "PRESS ENTER TO CONTINUE".
           DISPLAY "PRESS Y FOLLOWED BY ENTER TO QUIT".
           ACCEPT STOP-PROCESSING.
This paragraph puts out DISPLAY commands that ask for data and then uses ACCEPT commands to take in the data and store it in the appropriate field on the record that is going to be written. When data has been stored for all five fields on the record, the WRITE command writes the record on the physical file on the disk. Note that when you WRITE you use the name of the record that is defined at the 01 level of the FD.

Then the program puts out two DISPLAY commands asking the user to decide whether to continue or stop processing. The user answer is taken in by the ACCEPT and stored in STOP-PROCESSING.

After the B-200-LOOP has been executed, control returns to the PERFORM...UNTIL where the decision is made as to whether or not to do the B-200-LOOP again. When the user finally decides to stop, they enter Y and the PERFORM...UNTIL stops executing the B-200-LOOP. At that point the B-100-PROCESS paragraph is complete and control returns to the MAINLINE.

The next paragraph in the MAINLINE executes C-100-WRAPUP.
       C-100-WRAPUP.
           CLOSE PAY-FILE.
The file that is being written is now closed. Note that when I open a file I need to specify whether it is INPUT or OUTPUT, but when I close the file I do not need to provide this information.

Control now returns to the MAINLINE and the STOP RUN is executed and the program ends.

READ1.CBL:

The next program will read the file that we created in the program above (CREATE1.CBL) and display the information on the screen.
       IDENTIFICATION DIVISION.
       PROGRAM-ID. READ1.
       AUTHOR. GROCER
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT PAY-FILE
               ASSIGN TO "A:\PAY.DAT".
       DATA DIVISION.
       FILE SECTION.
       FD  PAY-FILE
           DATA RECORD IS PAY-REC.
       01  PAY-REC.
           05  PAY-ID               PIC 9999.
           05  PAY-NAME             PIC X(20).
           05  PAY-TYPE             PIC X.
           05  PAY-RATE             PIC 999V99.
           05  PAY-HOURS            PIC 99.
       WORKING-STORAGE SECTION.
       01  WORK-AREA.
           05  EOF-IND              PIC X          VALUE "N".
           05  CONTINUE-ANS         PIC X          VALUE SPACES.
       PROCEDURE DIVISION.
       MAINLINE.
           PERFORM A-100-STARTUP.
           PERFORM B-100-PROCESS.
           PERFORM C-100-WRAPUP.
           STOP RUN.
       A-100-STARTUP.
           OPEN INPUT PAY-FILE.
       B-100-PROCESS.
           READ PAY-FILE
               AT END
                  MOVE "Y" TO EOF-IND.
           PERFORM B-200-LOOP
               UNTIL EOF-IND = "Y".
       B-200-LOOP.
           DISPLAY "THE ID IS " PAY-ID.
           DISPLAY "THE NAME IS " PAY-NAME.
           DISPLAY "THE PAY TYPE IS " PAY-TYPE.
           DISPLAY "THE PAY RATE IS " PAY-RATE.
           DISPLAY "THE HOURS WORKED IS " PAY-HOURS.
           DISPLAY " ".
           DISPLAY "PRESS ENTER TO CONTINUE".
           ACCEPT CONTINUE-ANS.
           READ PAY-FILE
               AT END
                  MOVE "Y" TO EOF-IND.
       C-100-WRAPUP.
           CLOSE PAY-FILE.
First, let's look at the ENVIRONMENT DIVISION. It looks the same as it did in CREATE1.CBL because I have decided to use the same logical name (note that I could have used a different logical name). The physical name has to be the same because it is talking about the actual file that is on the A drive.
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT PAY-FILE
               ASSIGN TO "A:\PAY.DAT".
The file is now being described in the FILE SECTION. Notice that because it is the same file I have to have the same PIC clauses that describe the length and type of data. I could have used different names for the fields since these are logical names internal to the program. I chose to use the same names in this program as I used in the previous program.
       DATA DIVISION.
       FILE SECTION.
       FD  PAY-FILE
           DATA RECORD IS PAY-REC.
       01  PAY-REC.
           05  PAY-ID               PIC 9999.
           05  PAY-NAME             PIC X(20).
           05  PAY-TYPE             PIC X.
           05  PAY-RATE             PIC 999V99.
           05  PAY-HOURS            PIC 99.
In the WORKING-STORAGE SECTION, I have two entries in WORK-AREA. The first of these is the EOF-IND. This is used to tell me when end of file has been reached on the file that I am now reading. If I only put 4 records on the file, end of file will be reached after I have processed the 4 records. When the user is looking at the information on the screen, I want them to have as much time as they need. When they want to move on to the next record, I will have them press enter. The ACCEPT clause needs a name and I used CONTINUE-ANS.

       WORKING-STORAGE SECTION.
       01  WORK-AREA.
           05  EOF-IND              PIC X          VALUE "N".
           05  CONTINUE-ANS         PIC X          VALUE SPACES.
In this program, the PROCEDURE DIVISION will process the data on the file by reading a record and displaying it on the screen. As in the last program, the control of processing is in MAINLINE.
       MAINLINE.
           PERFORM A-100-STARTUP.
           PERFORM B-100-PROCESS.
           PERFORM C-100-WRAPUP.
           STOP RUN.
The file is opened in A-100-STARTUP. This time I am going to read the file so it is opened as INPUT. Note that the name is the same as the logical name in the SELECT.
       A-100-STARTUP.
           OPEN INPUT PAY-FILE.
In the process routine, the record is READ. The syntax for the READ statement is to READ the file name that was defined in the SELECT and in the FD. There is then an AT END clause that tells what to do if the READ was unsuccessful, in other words, the READ was unable to read a record. In this example, if the READ can't read, it means there are no more records on the file so I am moving Y to the EOF-IND.

You will notice in this program that there are two read statements. The READ in B-100-PROCESS is what I call the initializing read. It reads the first record of the file. All other records will be read at the bottom of the B-200-LOOP. This is the suggested way to code a program. By separating the first read, we can quickly determine if there are no records on the file. In addition, we are prepared to process when we enter the B-200-LOOP.

By having the other READ at the bottom of the B-200-LOOP, the read is the last thing that we do before checking the PERFORMUNTIL to see if we should process another record. The PERFORMUNTIL checks the EOF-IND to see it has been set to Y before deciding whether or not to do the B-200-LOOP again. This makes for very smooth logic. The READ is the thing that potentially changes the indicator and it is done as the last thing in the B-200-LOOP right before the PERFORM checks the indicator to see if it should do the paragraph again!

       B-100-PROCESS.
           READ PAY-FILE
               AT END
                  MOVE "Y" TO EOF-IND.
           PERFORM B-200-LOOP
               UNTIL EOF-IND = "Y".
The loop is where the information is displayed on the screen. The information being displayed is taken from the record layout and so it contains the data that was just read. Notice that the ACCEPT lets the user decide when they have seen the data and are ready to continue. Remember, ACCEPT just sits there waiting for an answer.

As I explained above, the last thing in the B-200-LOOP is the READ statement. If the read is unsuccessful (meaning we have reached end of file), the AT END clause will move Y to the EOF-IND.

When B-200-LOOP is complete control returns to the PERFORM...UNTIL which will immediately check the EOF-IND to determine if the B-200-LOOP should be executed again or whether the processing of the loop is complete. If the processing is complete then the B-100-PROCESS paragraph is also done and control will return to MAINLINE.

       B-200-LOOP.
           DISPLAY "THE ID IS " PAY-ID.
           DISPLAY "THE NAME IS " PAY-NAME.
           DISPLAY "THE PAY TYPE IS " PAY-TYPE.
           DISPLAY "THE PAY RATE IS " PAY-RATE.
           DISPLAY "THE HOURS WORKED IS " PAY-HOURS.
           DISPLAY " ".
           DISPLAY "PRESS ENTER TO CONTINUE".
           ACCEPT CONTINUE-ANS.
           READ PAY-FILE
               AT END
                  MOVE "Y" TO EOF-IND.
The next thing in the MAINLINE is to do the C-100-WRAPUP. The only command in that paragraph is to close the file. Control then returns to the MAINLINE and STOP RUN ends the program.

       C-100-WRAPUP.
           CLOSE PAY-FILE.