Directory UMM :wiley:Public:college:cobol:

(1)

CHAPTER 13

Multiple -Le vel Arrays and Table s

OBJECTIVES

To familiarize you with

1.

How to establish a series of items using a double-level

OCCURS

clause.

2.

How to store data in a double-level or two-dimensional array.

3.

How to look up data stored in a double-level or two-dimensional table.

4.

How to access and manipulate data defined with a triple-level (or more)

OCCURS

clause.

CONTENTS

D

OUBLE

-L

EVEL

OCCURS C

LAUSE

Defining a Double-Level or Two-Dimensional

Array

Accessing a Double-Level or Two-Dimensional

Array

Using Nested PERFORMs

Using PERFORM ... VARYING ... AFTER

Self-Test

Using a Double-Level or Two-Dimensional

Array for Accumulating Totals

Loading Input Data into a Double-Level or

Two-Dimensional Array

Self-Test

Performing a Look-Up Using a Double-Level

OCCURS

Performing a Full Table Look-Up

Searching Only Part of a Table

Searching Elements in an Array

T

RIPLE

-L

EVEL

OCCURS C

LAUSE AND

M

ORE

E

ND

-

OF

-C

HAPTER

A

IDS

Chapter Summary

Chapter Self-Test

Practice Program

Review Questions

Debugging Exercises

Programming Assignments


(2)

1-AM-TEMP 2-AM-TEMP MIDNIGHT-TEMP

MIDNIGHT-TEMP

MIDNIGHT-TEMP 1-AM-TEMP 2-AM-TEMP 1-AM-TEMP 2-AM-TEMP

DAY 7 (SAT) DAY 2 (MON)

DAY 1 (SUN)

• • • • • • • • • • • •

TEMPERATURE-ARRAY

D

OUBLE

- L

EVEL

OCCURS C

LAUSE

When describing an area of storage, more than one level of

OCCURS

may be used. As

many as seven levels of

OCCURS

are permitted with COBOL 85, and as many as three

levels are permitted with COBOL 74.

Like a single-level

OCCURS

, multiple levels of

OCCURS

may be used for (1)

accumu-lating totals in an

array

or (2) storing a

table

for ‘‘look-up’’ purposes. We will look first

at multiple-level arrays and then at multiple-level tables.

De fining a Do uble - Le ve l o r Tw o - Dime ns io nal Array

Suppose we wish to establish in storage an array of hourly temperature readings for

Los Angeles or any other city

during a given week

. Once the array is established, we will

use it to perform various calculations. The array consists of 7

2

24 temperature

read-ings; that is, there are 24 hourly temperature readings for each of 7 days. The array is

represented as follows:

To define this array in

WORKI NG- STORAGE

with a

single

-level

OCCURS

would require

the following coding:

01 TEMPERATURE- ARRAY.

05 DAY- I N- WEEK OCCURS 7 TI MES.

10 1- AM- TEMP PI C S9( 3) . 10 2- AM- TEMP PI C S9( 3) . .

. .

10 11- PM- TEMP PI C S9( 3) . 10 MI DNI GHT PI C S9( 3) .

The ellipses or dots (...) indicate that 24 elementary items must be coded, which would

be rather cumbersome. Instead, we could use a

double-level

OCCURS

to define the array

as follows:

01 TEMPERATURE- ARRAY.

05 DAY- I N- WEEK OCCURS 7 TI MES. 10 HOUR OCCURS 24 TI MES.

15 TEMP PI C S9( 3) .

The following illustration shows how this array can be visualized in storage:

Hour

TEMPERATURE

-

ARRAY

Day-in-Week

1

A

.

M

.

2

A

.

M

.

3

A

.

M

.

4

A

.

M

.

. . .

11

P

.

M

. 12

MID

.

Day 1 (Sun)

. . .

Day 2 (Mon)

. . .

Day 3 (Tue)

. . .

Day 4 (Wed)

. . .

7

ROWS

Day 5 (Thu)

. . .

Day 6 (Fri)

. . .

Day 7 (Sat)

. . .


(3)

For each

DAY- I N- WEEK

, we have 24

HOUR

figures, each of which will consist of a

TEMP

(average or mean temperature for that hour) that is three integers long. Thus, this array

defines a storage area of 504 positions (7

2

24

2

3). This

two-dimensional array

is

estab-lished as follows:

1. The array will have 7

rows

as indicated by the first

OCCURS

clause:

05 DAY- I N- WEEK OCCURS 7 TI MES.

2. Within this array, each row will have 24

columns

, as indicated by the second

OCCURS

clause:

10 HOUR OCCURS 24 TI MES.

3. Each of the

elements

in this 7

2

24 array will be large enough to hold three integers,

as indicated by the subordinate entry:

15 TEMP PI C S9( 3) .

To access any of the temperature figures, we use the data-name on the

lowest

OCCURS

level

or any data-name subordinate to it. Either

TEMP

or

HOUR

could be used to access

the temperatures. Because

HOUR

contains only one elementary item,

TEMP

and

HOUR

refer

to the same area of storage. Thus, the array could also have been defined as follows:

Alternative Coding

01 TEMPERATURE- ARRAY.

05 DAY- I N- WEEK OCCURS 7 TI MES.

10 HOUR OCCURS 24 TI MES PI C S9( 3) .

We have added the

PI C

clause to the second

OCCURS

level data-name, thereby

elimi-nating the reference to the data-name

TEMP

.

We will use the entry

TEMP

throughout, however, since it is clearer. Note that we

could

not

use

DAY- I N- WEEK

for accessing a single field in the array, since each

DAY- I

N-WEEK

actually refers to 24 temperatures.

Using Subscripts with Double-Level OCCURS Entries

Since

TEMP

is defined with two

OCCURS

, we must use

two

subscripts to access any hourly

temperature. The first subscript specified refers to the first or

major

-level

OCCURS

clause,

which, in this example, defines the

DAY- I N- WEEK

. The second subscript refers to the

second or

minor

OCCURS

level, which, in this example, defines the

HOUR

. Thus,

TEMP

(

1,

6

) refers to the temperature for Sunday (the first row) at 6

A

.

M

. (the sixth column in the

array). Assuming there is data in the array, we can display the temperature for Tuesday

at noon with the following instruction:

DI SPLAY ’ TEMPERATURE FOR TUESDAY AT NOON I S ’ , TEMP ( 3, 12) .

Interactive Processing.

Recall that a

DI SPLAY

can be used to display messages on a

screen and is commonly used for interactive processing.

The first subscript can vary from 1 to 7 since there are seven rows, one for each day.

The second subscript varies from 1 to 24, since there are 24 columns, one for each hour

of the day. The following subscripts are

not

valid:

Invalid Subscripts

TEMP

(

8, 4

) The first subscript can vary from 1 through 7.

TEMP

(

6, 25

) The second subscript can vary from 1 through 24.


(4)

Hour

Temperature-Array

Day-in-Week

1

A

.

M

.

2

A

.

M

.

3

A

.

M

.

4

A

.

M

.

. . .

11

P

.

M

.

12

MID

.

Day 1 (Sun)

(1,1)

(1,2)

(1,3)

(1,4)

. . .

(1,23)

(1, 24)

Day 2 (Mon)

(2,1)

(2,2)

(2,3)

(2,4)

. . .

(2,23)

(2,24)

Day 3 (Tue)

(3,1)

(3,2)

(3,3)

(3,4)

. . .

(3,23)

(3, 24)

Day 4 (Wed)

(4,1)

(4,2)

(4,3)

(4,4)

. . .

(4,23)

(4, 24)

Day 5 (Thu)

(5,1)

(5,2)

(5,3)

(5,4)

. . .

(5,23)

(5, 24)

Day 6 (Fri)

(6,1)

(6,2)

(6,3)

(6,4)

. . .

(6,23)

(6, 24)

Day 7 (Sat)

(7,1)

(7,2)

(7,3)

(7,4)

. . .

(7,23)

(7, 24)

The following are rules for using a double-level

OCCURS

:

RULES FOR USING A DOUBLE-LEVEL OCCURS

1. If an item is defined by a

double-level

OCCURS

clause, it must be accessed by

two

subscripts.

2. The first subscript refers to the higher-level

OCCURS

; the second subscript

refers to the lower-level

OCCURS

.

3. The subscripts must be enclosed in parentheses.

4. Subscripts may consist of positive integers or data-names with positive

integer contents.

5. On most systems, the left parenthesis must be preceded by at least one space;

similarly, the right parenthesis must be followed by a period, if it is the end

of a sentence, or at least one space. The first subscript within parentheses is

followed by a comma and a space.

Examples of Invalid Coding

REASON IT IS INVALID (on some systems) TEMP ( 6, 23) There is no space after the comma TEMP( SUB1, SUB2) There is no space before the left

parenthesis, and there is a space after the left parenthesis

Acce s s ing a Do uble - Le ve l o r Tw o - Dime ns io nal Array

Example 1

Suppose we wish to print an average temperature for the entire week. We need to add all the

array entries to a total and divide by 168 (7

2

24). We can use

nested

PERFORM

s for this purpose.

The first

PERFORM

varies the major subscript, which we call

DAY- SUB

, and the second

PERFORM

varies the minor subscript, which we call

HOUR- SUB

:

600- AVERAGE- RTN. MOVE 0 TO TOTAL.

PERFORM 700- LOOP- ON- DAYS

VARYI NG DAY- SUB FROM 1 BY 1 UNTI L DAY- SUB > 7. COMPUTE WEEKLY- AVERAGE = TOTAL / 168.

WRI TE PRI NT- REC FROM OUT- REC AFTER ADVANCI NG 2 LI NES. 700- LOOP- ON- DAYS.

PERFORM 800- LOOP- ON- HOURS

VARYI NG HOUR- SUB FROM 1 BY 1 UNTI L HOUR- SUB > 24. 800- LOOP- ON- HOURS.


(5)

Using in-line

PERFORM

s with COBOL 85, we could code the above as:

800- AVERAGE- RTN. MOVE 0 TO TOTAL.

PERFORM VARYI NG DAY- SUB FROM 1 BY 1 UNTI L DAY- SUB > 7 PERFORM VARYI NG HOUR- SUB FROM 1 BY 1 UNTI L HOUR- SUB > 24

ADD TEMP ( DAY- SUB, HOUR- SUB) TO TOTAL END- PERFORM

END- PERFORM.

COMPUTE WEEKLY- AVERAGE = TOTAL / 168. WRI TE PRI NT- REC FROM OUT- REC

AFTER ADVANCI NG 2 LI NES.

When using nested in-line

PERFORM

s, there should be

no

periods until after the last

END- PER-FORM

. A period would be optional after the last

END- PERFORM

unless it was the last word in the

paragraph.

The PERFORM . . . VARYING with the AFTER Option

The following expanded format for the

PERFORM . . .

VARYI NG

will result in nested

PERFORM

s

without the need for two separate

PERFORM . . . VARYI NG

statements

:

Expanded Format

THROUGH

PERFORM

F

procedure-name-1

F

H

THRU

J

procedure-name-2

GG

BEFORE

WI TH TEST

H

JG

F

AFTER

identifier-3

identifier-2

VARYI NG

H

J

FROM

index-name-2

index-name-1

5

6

literal-1

identifier-4

BY

H

J

UNTI L

condition-1

literal-2

identifier-6

identifier-5

AFTER

FROM

index-name-4

F H

index-name-3

J

5

6

literal-3

identifier-7

BY

H

J

UNTI L

condition-2

G

...

literal-4

[ END- PERFORM]

*

*With COBOL 85 only.

This format is particularly useful for processing multiple-level arrays and tables. The

PERFORM . . . VARYI NG

varies the

major subscript

, and the

AFTER

clause varies the

minor

subscript.

Thus, we can simplify the preceding nested

PERFORM

as follows:

Alternative Coding

600- AVERAGE- RTN.

MOVE 0 TO TOTAL. PERFORM 700- LOOP1

VARYI NG DAY- SUB FROM 1 BY 1 UNTI L DAY- SUB > 7 AFTER HOUR- SUB FROM 1 BY 1 UNTI L HOUR- SUB > 24. COMPUTE WEEKLY- AVERAGE = TOTAL / 168.

WRI TE PRI NT- REC FROM OUT- REC AFTER ADVANCI NG 2 LI NES. 700- LOOP1.


(6)

The sequence of values that these subscripts take on is (1, 1), (1, 2) . . . (1, 24), (2, 1),

(2, 2) . . . (2, 24) . . . (7, 1) . . . (7, 24). That is, with the

PERFORM . . . VARYI NG . . . AFTER,

DAY- SUB

is initialized at 1 and

HOUR- SUB

is varied from 1 to 24. Then

DAY- SUB

is

incre-mented to 2 and

HOUR- SUB

is varied again from 1 to 24. This continues until

HOUR- SUB

is varied from 1 to 24 with

DAY- SUB

at 7.

Example 2

Interactive Processing.

Suppose we want to enable users to make inquiries from the

TEMPERATURE- ARRAY

:

WORKI NG- STORAGE SECTI ON.

01 WS- DAY PI C 9.

01 WS- HOUR. PI C 99. .

.

DI SPLAY ’ ENTER DAY OF WEEK ( 1 = SUN, . . . 7 = SAT) ’ . ACCEPT WS- DAY.

DI SPLAY ’ ENTER HOUR ( 1 = 1 A. M. , . . . 24 = MI DNI GHT) ’ . ACCEPT WS- HOUR.

DI SPLAY ’ THE TEMPERATURE I S ’ , TEMP ( WS- DAY, WS- HOUR) .

Example 3

Consider the following double-level array and assume that data has been read into it:

01 POPULATI ON- ARRAY.

05 STATE OCCURS 50 TI MES. 10 COUNTY OCCURS 10 TI MES.

15 POPULATI ON PI C 9( 10) .

This array defines 500 fields of data or 5000 characters. Each of the 50 states is divided into 10

counties, each with 10 characters. We have arbitrarily selected 10 counties per state, each with a

POPULATI ON

of

9( 10)

,

for illustration purposes only.

In reality, the number of counties per state

varies from state to state, and counties will have populations that have fewer than 10 digits.

A pictorial representation of the array is as follows:

County

POPULATION

-

ARRAY

State

County 1

County 2

.

.

.

County 10

1 (Alabama)

(1,1)

(1,2)

. . .

(1,10)

2 (Alaska)

(2,1)

(2,2)

. . .

(2,10)

.

.

.

.

.

.

.

.

.

. . .

. . .

. . .

.

.

.

50 (Wyoming)

(50,1)

(50,2)

. . .

(50,10)

Note:The numbers in parentheses represent the subscripts for each entry.

Suppose we wish to accumulate a total United States population. We will add all 10 counties

for each of 50 states. We access elements in the array by using the lowest level item,

POPULATI ON

.

POPULATI ON

must be accessed using

two

subscripts. The first defines the major level,

STATE

, and

the second defines the minor level,

COUNTY. POPULATI ON ( 5, 10)

refers to the population for

STATE 5

,

COUNTY 10

. The first subscript varies from 1 to 50; the second varies from 1 to 10.

To perform the required addition, we will first accumulate all

COUNTY

figures for

STATE 1

.

Thus, the second or minor subscript will vary from 1 to 10. After 10 additions for

STATE 1

are

performed, we will accumulate the

10 COUNTY

figures for

STATE 2

. That is, we will increment the

major subscript to 2 and then add

COUNTY ( 2, 1)

,

COUNTY ( 2, 2)

,

. . . COUNTY ( 2, 10)

before

we add the figures for

STATE 3

.

The required operations may be performed in two ways:

Using Nested PERFORMs

The minor loop increments the minor subscript (

COUNTY- SUB

) from 1 to 10. The major

loop increments the major subscript (

STATE- SUB

) from 1 to 50:


(7)

PERFORM 700- USA- TOT. .

. . 700- USA- TOT.

PERFORM 800- MAJ OR- LOOP

VARYI NG STATE- SUB FROM 1 BY 1 UNTI L STATE- SUB > 50. PERFORM 1000- PRI NT- TOTAL.

800- MAJ OR- LOOP.

PERFORM 900- MI NOR- LOOP

VARYI NG COUNTY- SUB FROM 1 BY 1 UNTI L COUNTY- SUB > 10. 900- MI NOR- LOOP.

ADD POPULATI ON ( STATE- SUB, COUNTY- SUB) TO TOTAL1. .

. .

With in-line nested

PERFORM

s, this would be coded as:

PERFORM VARYI NG STATE- SUB FROM 1 BY 1

UNTI L STATE- SUB > 50 PERFORM VARYI NG COUNTY- SUB FROM 1 BY 1

UNTI L COUNTY- SUB > 10 ADD POPULATI ON ( STATE- SUB, COUNTY- SUB)

TO TOTAL1 END- PERFORM END- PERFORM.

PERFORM 1000- PRI NT- TOTAL.

Using PERFORM . . . VARYING . . . AFTER

Using the

AFTER

option of the

PERFORM VARYI NG

, we can simplify the coding as follows:

Alternative Coding

PERFORM 700- USA- TOT. .

. . 700- USA- TOT.

PERFORM 800- ADD- POP

VARYI NG STATE- SUB FROM 1 BY 1 UNTI L STATE- SUB > 50 AFTER COUNTY- SUB FROM 1 BY 1 UNTI L COUNTY- SUB > 10. PERFORM 1000- PRI NT- TOTAL.

800- ADD- POP.

ADD POPULATI ON ( STATE- SUB, COUNTY- SUB) TO TOTAL1.

The following illustrates how this procedure could be coded using an in-line

PERFORM

:

PERFORM VARYI NG STATE- SUB FROM 1 BY 1 UNTI L STATE- SUB > 50 AFTER COUNTY- SUB FROM 1 BY 1 UNTI L COUNTY- SUB > 10 ADD POPULATI ON ( STATE- SUB, COUNTY- SUB)

TO TOTAL1 END- PERFORM

Using either routine, we vary the minor subscript first, holding the major subscript

constant. That is, when the major subscript is equal to 1, denoting

STATE

1, all counties

within that

STATE

are summed. Thus, we set

STATE- SUB

equal to 1 and vary

COUNTY-SUB

from 1 to 10.

STATE- SUB

is then set to 2, and we again vary

COUNTY- SUB

from 1 to

10, and so on.

The sequence of additions may also be performed as follows:

POPULATI ON ( 1, 1)

,

POPULATI ON ( 2, 1) , . . . POPULATI ON ( 50,

1)

;

POPULATI ON ( 1,

2)

,

POPULATI ON

( 2, 2) , . . . POPULATI ON ( 50, 2) , . . . POPULATI ON ( 50, 10)

. That is, we can add

the population figures for

COUNTY 1

in all 50 states, then

COUNTY 2

in all 50 states, and

so on. This means we vary the

major subscript first

, holding the minor subscript constant.

We set

COUNTY- SUB

equal to 1 and vary

STATE- SUB

from 1 to 50; we then increment


(8)

COUNTY- SUB

to 2 and vary

STATE- SUB

from 1 to 50 again, and so on. The following

coding illustrates how this procedure can be performed:

Alternative Coding

PERFORM 700- USA- TOT. .

. .

700- USA- TOT.

PERFORM 800- MAJ OR- LOOP

VARYI NG COUNTY- SUB FROM 1 BY 1 UNTI L COUNTY- SUB > 10. PERFORM 1000- PRI NT- TOTAL.

800- MAJ OR- LOOP.

PERFORM 900- MI NOR- LOOP

VARYI NG STATE- SUB FROM 1 BY 1 UNTI L STATE- SUB > 50. 900- MI NOR- LOOP.

ADD POPULATI ON ( STATE- SUB, COUNTY- SUB) TO TOTAL1.

All the routines illustrated result in the same accumulated population total.

Example 4

Let us establish an array that will contain 12 monthly totals for each of 25 salespeople in Lacy’s

Department Store. Each total represents the accumulated monthly sales amount transacted by a

salesperson. Thus, the first element in the array will be January’s sales total for Salesperson 1,

the second will be February’s sales total for Salesperson 1, and so on.

There are 25 salespeople, each having 12 monthly sales totals, and the salespeople are

num-bered from 1 to 25 consecutively. The

WORKI NG- STORAGE SECTI ON

entry for this array is as follows:

01 COMPANY- SALES- ARRAY.

05 SALESPERSON OCCURS 25 TI MES.

10 MONTH- AMT OCCURS 12 TI MES PI C 9( 4) .

The major-level

OCCURS

clause indicates that there are 25 salespeople represented in the array.

Each

of the 25 salespeople has

12

monthly sales totals. Thus the array has 300 fields, each four

positions long. We need not store month number or salesperson number since both vary

consec-utively: the former from 1 to 12 and the latter from 1 to 25. This array, then, is a direct-referenced

array.

Assume that data has already been stored in the array. We wish to print 12 lines of monthly

totals. Each line will contain 25 totals, one for each salesperson. Line 1 will contain 25 sales figures

for January. These include array elements

( 1, 1) . . . ( 25, 1)

or the January totals for

sales-persons 1 through 25. Line 2 will contain 25 sales totals for February, which would be

( 1, 2) . . . ( 25, 2) ,

and so on.

The format of each line to be printed is described in

WORKI NG- STORAGE

as follows:

The word

FI LLER

is required

with COBOL 74

WORKI NG- STORAGE SECTI ON. 01 SALES- LI NE.

05 PI C X.

05 I TEMX OCCURS 25 TI MES.

10 MONTHLY- SALESPERSON- TOTAL PI C ZZZ9.

10 PI C X.

05 PI C X( 6) .

We use a

single-level

OCCURS

clause

to describe the 25 sales totals within

SALES- LI NE

. Since

each line will contain 25 salesperson figures, only one

OCCURS

clause is necessary. The fact that

there will be 12 lines printed is

not

denoted by an

OCCURS

clause, but by repeating the print

routine 12 times.

OCCURS

clauses are used to denote repeated occurrences of

fields

, not

records

.

Note that

I TEMX

, which

OCCURS 25 TI MES

, consists of

two

fields,

MONTHLY- SALESPERSON- TOTAL

and a one-position blank or

FI LLER

area. This one-position area will separate each of the 25

amount fields to make the entire line more readable. If all the monthly salesperson totals

appeared next to one another, it would be difficult to read the line.

Using a nested

PERFORM

, the routine is as follows:

PERFORM 800- WRI TE- RTN

VARYI NG SUB2 FROM 1 BY 1 UNTI L SUB2 > 12. .

. .

800- WRI TE- RTN.


(9)

MONTH

SALESPERSON 1 2 3 4 5 6 7 8 9 10 11 12 1

2

25

• • •

Sales for

salesperson 1 salesperson 25Sales for

• • •

• • • • • •

COMPANY-SALES-ARRAY

SALES FOR MONTH 1

SALES FOR MONTH 12 PERFORM 900- MOVE- RTN

VARYI NG SUB1 FROM 1 BY 1 UNTI L SUB1 > 25. WRI TE PRI NT- REC FROM SALES- LI NE

AFTER ADVANCI NG 2 LI NES. 900- MOVE- RTN.

MOVE MONTH- AMT ( SUB1, SUB2) TO MONTHLY- SALESPERSON- TOTAL ( SUB1) .

What we have done is to take an array that consists of 25 rows and 12 columns and print it out

in an order different from the one in which it is stored:

We use the

same subscript

,

SUB1

, to reference the number of the salesperson accessed in

(1)

COMPANY- SALES- ARRAY

and in (2) the print line.

In the next section, we will consider how to

ADD

to fields in the array. We end that

section with the program that produces the output specified above.

SELF-TEST

Using the following

TEMPERATURE- ARRAY

, code the solutions to Questions 1–5:

01 TEMPERATURE- ARRAY.

05 DAY- I N- WEEK OCCURS 7 TI MES. 10 HOUR OCCURS 24 TI MES.

15 TEMP PI C S9( 3) .

1.

Find the average temperature for Sunday (Day 1).

2.

Find the average weekly temperature for 2

A

.

M

. (the second column).

3.

Find the day of the week and the hour when the temperature was highest. Also indicate what

the highest temperature was.

4.

Find the number of days when the temperature fell below 32

7

at any hour. Could a

PERFORM

. . . VARYI NG . . . AFTER

be used?

5.

Print the average hourly temperatures for each day of the week.

6.

Define a

COMPANY- SALES- ARRAY

that contains a name and 12 monthly amounts for each of

25 salespersons.

Solutions

1.

MOVE 0 TO TOTAL.

PERFORM 500- SUNDAY- AVERAGE

VARYI NG X2 FROM 1 BY 1 UNTI L X2 > 24. COMPUTE AVERAGE = TOTAL / 24.

DI SPLAY ’ AVERAGE TEMPERATURE FOR SUNDAY WAS ’ , AVERAGE. .

. .

500- SUNDAY- AVERAGE.


(10)

With COBOL 85, we can use an in-line

PERFORM

instead:

MOVE 0 TO TOTAL.

PERFORM VARYI NG X2 FROM 1 BY 1 UNTI L X2 > 24

ADD TEMP ( 1, X2) TO TOTAL END- PERFORM.

COMPUTE AVERAGE = TOTAL / 24.

DI SPLAY ’ AVERAGE TEMPERATURE FOR SUNDAY WAS ’ , AVERAGE.

2.

MOVE 0 TO TOTAL. PERFORM 2- AM- AVERAGE

VARYI NG X1 FROM 1 BY 1 UNTI L X1 > 7. COMPUTE AVERAGE = TOTAL / 7.

DI SPLAY ’ THE AVERAGE TEMPERATURE AT 2 AM WAS ’ , AVERAGE. .

. .

2- AM- AVERAGE.

ADD TEMP ( X1, 2) TO TOTAL.

With COBOL 85, we can use an in-line

PERFORM

instead:

MOVE 0 TO TOTAL.

PERFORM VARYI NG X1 FROM 1 BY 1 UNTI L X1 > 7

ADD TEMP ( X1, 2) TO TOTAL END- PERFORM.

COMPUTE AVERAGE = TOTAL / 7.

DI SPLAY ’ THE AVERAGE TEMPERATURE AT 2 AM WAS ’ , AVERAGE.

3.

MOVE 0 TO HOLD- I T, STORE1, STORE2. PERFORM 200- MAJ OR- LOOP

VARYI NG X1 FROM 1 BY 1 UNTI L X1 > 7. DI SPLAY ’ HI GHEST TEMPERATURE WAS ’ , HOLD- I T.

DI SPLAY ’ DAY OF WEEK OF HI GHEST TEMPERATURE WAS ’ , STORE1. I F STORE2 < 12

DI SPLAY ’ HOUR OF HI GHEST TEMPERATURE WAS ’ , STORE2, ’ AM’ ELSE I F STORE2 > 12 AND < 24

SUBTRACT 12 FROM STORE2

DI SPLAY ’ HOUR OF HI GHEST TEMPERATURE WAS ’ , STORE2, ’ PM’ ELSE I F STORE2 = 12

DI SPLAY ’ HOUR OF HI GHEST TEMPERATURE WAS NOON’ ELSE

DI SPLAY ’ HOUR OF HI GHEST TEMPERATURE WAS MI DNI GHT’ .

. .

200- MAJ OR- LOOP.

PERFORM 300- MI NOR- LOOP

VARYI NG X2 FROM 1 BY 1 UNTI L X2 > 24. 300- MI NOR- LOOP.

I F TEMP ( X1, X2) > HOLD- I T MOVE TEMP ( X1, X2) TO HOLD- I T MOVE X1 TO STORE1

MOVE X2 TO STORE2

END- I F.

We could replace the first

PERFORM

with the following and eliminate

200- MAJ OR- LOOP

entirely:

PERFORM 300- MI NOR- LOOP

VARYI NG X1 FROM 1 BY 1 UNTI L X1 > 7 AFTER X2 FROM 1 BY 1 UNTI L X2 > 24.


(11)

01 DAYS VALUE ’ SUNMONTUEWEDTHUFRI SAT’ .

05 DAY- OF- THE- WEEK OCCURS 7 TI MES PI C X( 3) .

The second

DI SPLAY

would then change as follows:

DI SPLAY ’ DAY OF WEEK OF HI GHEST TEMPERATURE WAS ’ , DAY- OF- THE- WEEK ( STORE1) .

For COBOL 74, the

WORKI NG- STORAGE

entry would require a

REDEFI NES

:

01 DAYS.

05 DAY- VALUE PI C X( 21)

VALUE ’ SUNMONTUEWEDTHUFRI SAT’ . 05 DAY- OF- THE- WEEK REDEFI NES DAY- VALUE

OCCURS 7 TI MES PI C X( 3) .

4.

MOVE 0 TO COUNTER. PERFORM 200- MAJ OR- LOOP

VARYI NG X1 FROM 1 BY 1 UNTI L X1 > 7.

DI SPLAY ’ NUMBER OF DAYS WHEN TEMPERATURE < 32 WAS ’ , COUNTER.

. . .

200- MAJ OR- LOOP.

MOVE ’ NO ’ TO FOUND. PERFORM 300- MI NOR- LOOP

VARYI NG X2 FROM 1 BY 1 UNTI L X2 > 24 OR FOUND = ’ YES’ .

300- MI NOR- LOOP.

I F TEMP ( X1, X2) < 32 ADD 1 TO COUNTER MOVE ’ YES’ TO FOUND

END- I F.

We use a field called

FOUND

to terminate processing of

300- MI NOR- LOOP

when we find an

hour in any day when the temperature falls below 32

7

. Because

FOUND

has one value

( ’ NO ’ )

when no match has been found, and another value

( ’ YES’ )

when a match occurs,

we call this field a switch or flag. Once we find a temperature lower than 32, we need not

check the rest of the hours during that day.

A

PERFORM . . . VARYI NG . . . AFTER

could

not

be used because

200- MAJ OR- LOOP

has an

operation to be performed

in addition to

varying the minor subscript. That is,

PERFORM . . . VARYI NG . . . AFTER

is used when you want to process all array elements together; when you

need to stop, print, or

MOVE ’ N0 ’ TO FOUND

before or after a row in an array is processed,

then this option cannot be used.

5.

Note:

Use

01 DAYS

established for Question 3 if an abbreviation for the day

( SUN . . . SAT)

is to print rather than the day number.

PERFORM 500- PRI NT- RTN

VARYI NG X1 FROM 1 BY 1 UNTI L X1 > 7. .

. .

500- PRI NT- RTN. MOVE 0 TO TOTAL. PERFORM 600- MI NOR- LOOP

VARYI NG X2 FROM 1 BY 1 UNTI L X2 > 24. MOVE DAY- OF- THE- WEEK ( X1) TO DAY- OUT. COMPUTE AVERAGE- OUT = TOTAL / 24. WRI TE PRI NT- REC FROM OUT- REC

AFTER ADVANCI NG 2 LI NES. 600- MI NOR- LOOP.

ADD TEMP ( X1, X2) TO TOTAL.

6.

01 COMPANY- SALES- ARRAY.

05 SALESPERSON OCCURS 25 TI MES.

10 NAME PI C X( 20) .


(12)

Us ing a Do uble - Le ve l o r Tw o - Dime ns io nal Array fo r Accumulating To tals

Suppose a company has 10 departments and five salespeople (numbered 1–5) within

each department. We wish to accumulate the total amount of sales for each salesperson

within each department:

01 DEPT- TOTALS.

05 DEPT OCCURS 10 TI MES.

10 SALESPERSON OCCURS 5 TI MES.

15 TOTAL- SALES PI C 9( 5) V99.

Before adding any data to a total area, we must ensure that the total area is initialized

at zero. To initialize an entire array at zero, we could code the following with COBOL

85:

MOVE ZEROS TO DEPT- TOTALS

. Alternatively, with COBOL 85 we can code:

01 DEPT- TOTALS VALUE ZEROS.

If your compiler permits you to reference

DEPT- TOTALS

in the

PROCEDURE DI VI SI ON

,

moving

ZEROS

to

DEPT- TOTALS

replaces all fields with 0; note, however, that

MOVE 0

TO DEPT- TOTALS

only moves a 0 to the leftmost position in the array. This is because

DEPT- TOTALS

, as a group item, is treated as an alphanumeric field; if you move a single

0 to an alphanumeric field, the 0 is placed in the leftmost position; all other positions

are replaced with blanks.

With COBOL 74, however, you may not reference the

01

array entry itself. In such

a case, you must code a full initializing routine prior to adding to

TOTAL- SALES

. We

will use either nested

PERFORM

s or a

PERFORM

with the

AFTER

option in our illustrations:

PERFORM 700- I NI TI ALI ZE- RTN

VARYI NG X1 FROM 1 BY 1 UNTI L X1 > 10 AFTER X2 FROM 1 BY 1 UNTI L X2 > 5. .

. .

700- I NI TI ALI ZE- RTN.

MOVE 0 TO TOTAL- SALES ( X1, X2) .

This routine, which initializes each

TOTAL- SALES

field separately, will run on all

computers; COBOL 85 compilers, however, will allow you to code

MOVE ZEROS TO

DEPT- TOTALS

.

Assume an input record has been created each time a salesperson makes a sale. Each

input record contains a department number called

DEPT- I N

, a salesperson number

called

SALESPERSON- NO- I N

, and an amount of sales called

AMT- I N

. There may be

nu-merous input records for a salesperson if he or she made more than one sale. The coding

to accumulate the totals after the array has been initialized at zero is as follows:

READ SALES- FI LE

AT END MOVE ’ NO ’ TO ARE- THERE- MORE- RECORDS

END- READ.

PERFORM 200- ADD- RTN

UNTI L ARE- THERE- MORE- RECORDS = ’ NO ’ . .

. .

200- ADD- RTN.

ADD AMT- I N TO TOTAL- SALES ( DEPT- I N, SALESPERSON- NO- I N) . READ SALES- FI LE

AT END MOVE ’ NO ’ TO ARE- THERE- MORE- RECORDS

END- READ.

As indicated previously, input fields may be used as subscripts. For correct

process-ing, a validation procedure should be used to ensure that (1)

DEPT- I N

is an integer

between 1 and 10 and (2)

SALESPERSON- NO- I N

is an integer between 1 and 5. We should

also check that

AMT- I N

is numeric:

200- ADD- RTN.

I F AMT- I N I S NUMERI C

AND ( DEPT- I N >= 1 AND <= 10)


(13)

SALESPERSON NO

1

DATE

6

5 11

MO DA YR 3

2

SALES AMOUNT

ADD AMT- I N TO TOTAL- SALES ( DEPT- I N, SALESPERSON- NO- I N) ELSE

DI SPLAY ’ ERROR’

END- I F.

READ SALES- FI LE

AT END MOVE ’ NO ’ TO ARE- THERE- MORE- RECORDS

END- READ.

At the end of the job, we wish to print 10 pages of output. Each page will contain

five lines, one for each salesperson in a given department. The full

PROCEDURE DI VI SI ON

is as follows:

PROCEDURE DI VI SI ON. 100- MAI N- MODULE.

OPEN I NPUT SALES- FI LE OUTPUT PRI NT- FI LE. MOVE ZEROS TO DEPT- TOTALS. READ SALES- FI LE

AT END MOVE ’ NO ’ TO ARE- THERE- MORE- RECORDS

END- READ.

PERFORM 200- ADD- RTN UNTI L NO- MORE- RECORDS. PERFORM 300- PRI NT- RTN

VARYI NG X1 FROM 1 BY 1 UNTI L X1 > 10. CLOSE SALES- FI LE

PRI NT- FI LE. STOP RUN.

200- ADD- RTN.

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * NOTE: AMT- I N, DEPT- I N, SALESPERSON- NO- I N ARE I NPUT FI ELDS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

I F AMT- I N I S NUMERI C

AND ( DEPT- I N >= 1 AND <= 10)

AND ( SALESPERSON- NO- I N >= 1 AND <= 5)

ADD AMT- I N TO TOTAL- SALES ( DEPT- I N, SALESPERSON- NO- I N) ELSE

DI SPLAY ’ ERROR’

END- I F.

READ SALES- FI LE

AT END MOVE ’ NO ’ TO ARE- THERE- MORE- RECORDS

END- READ.

300- PRI NT- RTN.

MOVE X1 TO DEPT- NO- ON- HDG- LI NE. WRI TE PRI NT- REC FROM HDG- LI NE

AFTER ADVANCI NG PAGE. PERFORM 400- LI NE- PRI NT

VARYI NG X2 FROM 1 BY 1 UNTI L X2 > 5. 400- LI NE- PRI NT.

MOVE X2 TO SALESPERSON- NO- OUT.

MOVE TOTAL- SALES ( X1, X2) TO TOTAL- OUT. WRI TE PRI NT- REC FROM SALES- LI NE- REC

AFTER ADVANCI NG 2 LI NES.

In this illustration, we assume that the values for

DEPT- I N

vary from 1–10 and the

values for

SALESPERSON- NO- I N

vary from 1–5. If either or both of these fields have

values other than 1–10 or 1–5 consecutively, then the numbers themselves must be

stored along with the

TOTAL- SALES

.

In the preceding section we considered a program that is to print 12 monthly sales

totals for 25 salespeople (see p. 510). The input consists of transaction records for the

previous year, each with the following format:


(14)

The full program for printing monthly sales totals that uses procedures discussed in

this section appears in Figure 13.1.

I DENTI FI CATI ON DI VI SI ON. PROGRAM- I D. FI G131. ENVI RONMENT DI VI SI ON. I NPUT- OUTPUT SECTI ON. FI LE- CONTROL.

SELECT SALES- FI LE ASSI GN TO ’ S1. DAT’ .

SELECT REPORT- FI LE ASSI GN TO PRI NTER ’ P1. OUT’ . DATA DI VI SI ON.

FI LE SECTI ON. FD SALES- FI LE

LABEL RECORDS ARE STANDARD. 01 SALES- REC.

05 SALESPERSON- NO- I N PI C 99. 05 SALES- AMT- I N PI C 999. 05 DATE- OF- TRANS.

10 MONTH- I N PI C 99.

10 DAY- I N PI C 99.

10 YEAR- I N PI C 99. FD REPORT- FI LE

LABEL RECORDS ARE OMI TTED.

01 PRI NT- REC PI C X( 132) .

WORKI NG- STORAGE SECTI ON.

01 MORE- RECS PI C X( 3) VALUE ’ YES’ . 01 COMPANY- SALES- ARRAY.

05 SALESPERSON OCCURS 25 TI MES.

10 MONTH- AMT OCCURS 12 TI MES PI C 9( 4) . 01 HEADI NG- REC.

05 PI C X( 30)

VALUE SPACES.

05 PI C X( 102)

VALUE ’ ANNUAL SALES REPORT’ . 01 COLUMN- HEADI NG.

05 PI C X( 43)

VALUE ’ S1 S2 S3 S4 S5 S6 S7 S8 ’ .

05 PI C X( 39)

VALUE ’ S9 S10 S11 S12 S13 S14 S15 S16 ’ .

05 PI C X( 50)

VALUE ’ S17 S18 S19 S20 S21 S22 S23 S24 S25’ . 01 SALES- LI NE.

05 PI C X.

05 I TEMX OCCURS 25 TI MES.

10 SALES- I TEM PI C ZZZ9.

10 PI C X.

05 PI C X( 6) .

01 SUB1 PI C 99.

01 SUB2 PI C 99.

PROCEDURE DI VI SI ON. 100- MAI N.

OPEN I NPUT SALES- FI LE OUTPUT REPORT- FI LE.

WRI TE PRI NT- REC FROM HEADI NG- REC AFTER ADVANCI NG PAGE.

WRI TE PRI NT- REC FROM COLUMN- HEADI NG AFTER ADVANCI NG 3 LI NES.

MOVE ZEROS TO COMPANY- SALES- ARRAY. READ SALES- FI LE

AT END MOVE ’ NO ’ TO MORE- RECS

END- READ.

PERFORM 200- CALC- RTN

UNTI L MORE- RECS = ’ NO ’ . PERFORM 800- WRI TE- RTN

VARYI NG SUB2 FROM 1 BY 1 UNTI L SUB2 > 12. CLOSE SALES- FI LE

REPORT- FI LE.

Figure 13.1

Program to print monthly

sales totals.


(15)

STOP RUN. 200- CALC- RTN.

I F MONTH- I N >= 1 AND <= 12

AND SALESPERSON- NO- I N >= 1 AND <= 25 ADD SALES- AMT- I N TO

MONTH- AMT ( SALESPERSON- NO- I N, MONTH- I N) ELSE

DI SPLAY ’ ERROR ’ , SALES- REC

END- I F.

READ SALES- FI LE

AT END MOVE ’ NO ’ TO MORE- RECS

END- READ.

800- WRI TE- RTN.

MOVE SPACES TO SALES- LI NE. PERFORM 900- MOVE- RTN

VARYI NG SUB1 FROM 1 BY 1 UNTI L SUB1 > 25. WRI TE PRI NT- REC FROM SALES- LI NE

AFTER ADVANCI NG 2 LI NES. 900- MOVE- RTN.

MOVE MONTH- AMT ( SUB1, SUB2) TO SALES- I TEM ( SUB1) .

Lo ading Input Data into a Do uble - Le ve l o r Tw o - Dime ns io nal Array

To load data such as temperatures or populations into an array, we may use a

READ

statement and then move the data to the array. In place of

READ

and

MOVE

statements,

we could use a

READ . . . I NTO

.

Consider again our

TEMPERATURE- ARRAY

from the beginning of this chapter:

01 TEMPERATURE- ARRAY.

05 DAY- I N- WEEK OCCURS 7 TI MES. 10 HOUR OCCURS 24 TI MES.

15 TEMP PI C S9( 3) .

Suppose we have seven input records, each with 24 three-position hourly

tempera-tures. The first input record to be loaded into the array is for Day 1 or Sunday, the

second is for Day 2 or Monday, and so on:

FD TEMP- FI LE

LABEL RECORDS ARE OMI TTED. 01 I N- REC.

05 HOURLY- TEMP OCCURS 24 TI MES PI C S9( 3) .

The

ARRAY- LOAD

routine could be executed as follows. We use subscript names here

that are more meaningful than

X1

and

X2

:

READ TEMP- FI LE

AT END PERFORM 600- ERR- RTN

END- READ.

PERFORM 200- ARRAY- LOAD

VARYI NG DAY- SUB FROM 1 BY 1 UNTI L DAY- SUB > 7 OR NO- MORE- RECORDS.

I F ARE- THERE- MORE- RECORDS = ’ YES’ OR DAY- SUB NOT > 7 PERFORM 600- ERR- RTN

END- I F.

. . .

200- ARRAY- LOAD.

PERFORM 300- MI NOR- LOAD

VARYI NG HOUR- SUB FROM 1 BY 1 UNTI L HOUR- SUB > 24. READ TEMP- FI LE

AT END MOVE ’ NO ’ TO ARE- THERE- MORE- RECORDS

END- READ.

300- MI NOR- LOAD.

MOVE HOURLY- TEMP ( HOUR- SUB) TO TEMP ( DAY- SUB, HOUR- SUB) .


(16)

STATE

NO COUNTYNO POPULATION-IN

1 2 3 4 5 14

COUNTY 1 POP

1 20 91 100

COUNTY 2 POP

COUNTY 10 POP • • •

11 10

10 491 500

STATE 1 POP

STATE 50 POP • • •

1

If there are not exactly seven records in

TEMP- FI LE

,

600- ERR- RTN

will be executed,

which terminates the job. The

END- READ

and

END- I F

scope terminators are valid with

COBOL 85; with older compilers omit the scope terminators and end the previous line

with a period.

SELF-TEST

Consider our population array:

01 POPULATI ON- ARRAY.

05 STATE OCCURS 50 TI MES. 10 COUNTY OCCURS 10 TI MES.

15 POPULATI ON PI C 9( 10) .

1.

Assume there are 500 input records with the following format:

Write a routine to load each record into the

POPULATI ON- ARRAY

.

2.

Assume the input records have the following format:

There are 50 such records, where the first record is for

STATE

1, the second is for

STATE

2,

and so on. Write a routine to load each record into the

POPULATI ON- ARRAY

.

3.

Assume the input records have the following format:

There are 10 such records, where the first record is for

COUNTY

1, the second is for

COUNTY

2,

and so on. Write a routine to load each record into the

POPULATI ON- ARRAY

.

4.

Suppose records were read with the format specified in Question 2 and we want to print a

report as follows:

STATE STATE- POP

1 . . . 50

Z, ZZZ, ZZZ, ZZZ. . . Z, ZZZ, ZZZ, ZZZ

What type of array would we need in

WORKI NG- STORAGE

to print the 50 state population

totals?

5.

Suppose records were read with the format specified in Question 3 and we want to print a


(17)

COUNTY POPULATI ON 1

. . . 10

Z, ZZZ, ZZZ, ZZZ. . . Z, ZZZ, ZZZ, ZZZ

What type of array would we need in

WORKI NG- STORAGE

to process the data?

Solutions

1.

PERFORM 500 TI MES

READ I N- FI LE

AT END DI SPLAY ’ NOT ENOUGH RECORDS’ STOP RUN

END- READ

I F STATE- NO >= 1 AND <= 50 AND COUNTY >= 1 AND <= 10 PERFORM 200- LOAD

ELSE

DI SPLAY ’ ERROR I N STATE OR COUNTY NO’

END- I F END- PERFORM.

200- LOAD.

MOVE POPULATI ON- I N TO POPULATI ON ( STATE- NO, COUNTY- NO) .

With COBOL 85, we can use a different in-line

PERFORM

instead:

PERFORM 500 TI MES READ I N- FI LE

AT END DI SPLAY ’ NOT ENOUGH RECORDS’ STOP RUN

END- READ

I F STATE- NO >= 1 AND STATE- NO <= 50 AND COUNTY >= 1 AND COUNTY <= 10

MOVE POPULATI ON- I N TO POPULATI ON ( STATE- NO, COUNTY- NO) ELSE

DI SPLAY ’ ERROR I N STATE OR COUNTY NO’

END- I F END- PERFORM.

2.

The input file is defined as follows:

FD I N- FI LE LABEL RECORDS ARE STANDARD. 01 I N- REC.

05 COUNTY- I N- POP OCCURS 10 TI MES PI C 9( 10) .

The procedure to input records with in-line

PERFORM

s is as follows:

PERFORM VARYI NG STATE- NO

FROM 1 BY 1 UNTI L STATE- NO > 50 READ I N- FI LE

AT END DI SPLAY ’ NOT ENOUGH I NPUT’ STOP RUN

END- READ

PERFORM VARYI NG COUNTY- NO

FROM 1 BY 1 UNTI L COUNTY- NO > 10 MOVE COUNTY- I N- POP ( COUNTY- NO)

TO POPULATI ON ( STATE- NO, COUNTY- NO)

END- PERFORM END- PERFORM.

3.

The input file is defined as follows:

FD I N- FI LE LABEL RECORDS ARE STANDARD. 01 I N- REC.

05 STATE- POP OCCURS 50 TI MES PI C 9( 10) .

The procedure to input records with in-line

PERFORM

s is as follows:

PERFORM VARYI NG COUNTY- NO

FROM 1 BY 1 UNTI L COUNTY- NO > 10 READ I N- FI LE


(18)

AT END DI SPLAY ’ NOT ENOUGH I NPUT’ STOP RUN

END- READ

PERFORM VARYI NG STATE- NO

FROM 1 BY 1 UNTI L STATE- NO > 50 MOVE STATE- POP ( STATE- NO)

TO POPULATI ON ( STATE- NO, COUNTY- NO)

END- PERFORM END- PERFORM.

4.

There would be no need to accumulate totals in an array at all. The 10 county population

figures for the first record would be added and printed as the

STATE- POP

for

STATE

1. The

next record would be read and the procedure repeated for

STATE

2.

5.

Records are entered in such a way that all input would need to be stored

before

any state

totals could print. The

POPULATI ON- ARRAY

specified at the start of the Self-Test would be

used.

Pe rfo rming a Lo o k- Up Us ing a Do uble - Le ve l OCCURS

Performing a Full Table Look-Up

We will use a double-level

OCCURS

entry to define a table and then use a

SEARCH

to

perform a table look-up.

Example

Assume that the following table has been loaded into storage:

01 I NVENTORY- TABLE.

05 WAREHOUSE OCCURS 50 TI MES. 10 I TEM- X OCCURS 100 TI MES.

15 PART- NO PI C 9( 4) . 15 UNI T- PRI CE PI C 999V99.

There are 50 warehouses, and each stores 100 items. Each warehouse stocks its own inventory,

which is different from the inventory at other warehouses. This means that a specific

PART- NO

will appear

only once

in the table. There are 5000 table records, each with a warehouse number,

part number, and unit price. The first table record refers to warehouse 1, part number 1; the next

to warehouse 1, part number 2; the 101st to warehouse 2, part number 1, and so on.

Suppose that input transaction records have the following format:

1- 4 PART- NO- I N 5- 6 QTY- ORDERED

For each

PART- NO- I N

in a transaction record, we need to look up the corresponding

PART- NO

in

the table and find its

UNI T- PRI CE

. We store the unit price for each part in the table and

not

in the

transaction record for the following reasons:

1. If each input transaction record contained a unit price, we would be keying unit price each

time a part was ordered. This would increase both keying costs and the risk of input errors.

2. Changes to unit prices can be more easily made to a relatively small number of table entries

than to a large number of input transaction records.

We store prices in an external table, which is in a file and is loaded in, rather than in an internal

table, which is established with

VALUE

clauses. External tables are used for this type of application

because the table elements themselves are likely to change with some frequency. That is, because

we anticipate that unit prices may change, we establish the

I NVENTORY- TABLE

as an external table

that can be changed, when needed, by a separate program. If we defined it as an internal table

with

VALUE

clauses, we would need to modify and recompile our look-up program each time a

change to unit price occurred.

The output from this program will be a printed transaction report. Each time a

PART- NO

is

ordered, we will print the

PART- NO

and the

TOTAL- AMT

of the transaction, where

TOTAL- AMT = QTY- ORDERED

(from the transaction record)

2

UNI T- PRI CE

(from the table). Since we will use a

SEARCH

, the table we have described must include the appropriate

I NDEXED BY

clauses with each


(19)

01 I NVENTORY- TABLE.

05 WAREHOUSE OCCURS 50 TI MES I NDEXED BY X1. 10 I TEM- X OCCURS 100 TI MES I NDEXED BY X2.

15 PART- NO PI C 9( 4) . 15 UNI T- PRI CE PI C 999V99.

The Identifier Used with the SEARCH Refers to the Lowest-Level OCCURS Entry

To

SEARCH

the table, we code

SEARCH I TEM- X . . .

because

I TEM- X

is the

lowest-level

OCCURS

entry

.

Note that

SEARCH I TEM- X

increments the lowest-level index only

. Hence if

X1

is set to 1 initially, the

SEARCH

will perform a look-up on items in warehouse 1 only,

that is (1, 1) through (1, 100). To search

all

warehouses, the

SEARCH

itself must be

exe-cuted from a

PERFORM . . . VARYI NG

that increments the major index,

X1

.

The routine would then appear as follows:

MOVE ’ NO ’ TO MATCH- FOUND.

PERFORM 500- SEARCH- I T VARYI NG X1 FROM 1 BY 1

UNTI L X1 > 50 OR MATCH- FOUND = ’ YES’ . I F MATCH- FOUND = ’ YES’

WRI TE OUT- REC FROM TRANS- REC- OUT AFTER ADVANCI NG 2 LI NES ELSE

PERFORM 600- NO- MATCH- ERR

END- I F.

. . .

500- SEARCH- I T. SET X2 TO 1.

SEARCH I TEM- XkˆˆˆˆˆˆUse lowest-level OCCURS level here

WHEN PART- NO- I N = PART- NO ( X1, X2)

MULTI PLY UNI T- PRI CE ( X1, X2) BY QTY- ORDERED GI VI NG TOTAL- AMT

MOVE ’ YES’ TO MATCH- FOUNDkˆˆEnables 500-SEARCH-IT to be

terminated properly when a match is found

END- SEARCH.

MATCH- FOUND

is a field that is initialized at

’ NO ’

and changed to

’ YES’

only when

the corresponding

PART- NO

in the table is found. We terminate

500- SEARCH- I T

when

a match is found

( MATCH- FOUND = ’ YES’ )

or the entire table has been searched

( X1 >

50) . 600- NO- MATCH- ERR

would be executed only if no match existed between the

PART-NO- I N

and a table entry.

The full program for this example appears in Figure 13.2.

I DENTI FI CATI ON DI VI SI ON.

PROGRAM- I D. FI G13- 2. *

ENVI RONMENT DI VI SI ON. I NPUT- OUTPUT SECTI ON. FI LE- CONTROL.

SELECT I NVENTORY- TABLE- I N ASSI GN TO DI SK1. SELECT TRANSACTI ON- FI LE ASSI GN TO DI SK2. SELECT REPORT- OUT ASSI GN TO SYS$OUTPUT. *

DATA DI VI SI ON. FI LE SECTI ON.

FD I NVENTORY- TABLE- I N

LABEL RECORDS ARE STANDARD. 01 I NVENTORY- TABLE- REC.

05 T- WAREHOUSE- NO PI C 99.

05 T- PART- NO PI C 9999.

05 T- UNI T- PRI CE PI C 999V99. FD TRANSACTI ON- FI LE

LABEL RECORDS ARE STANDARD. 01 TRANSACTI ON- REC.

05 PART- NO- I N PI C 9999.

05 QTY- ORDERED PI C 99.

Figure 13.2

Program to search a

double-level table.


(20)

Figure 13.2

(continued)

05 PI C X( 14) .

FD REPORT- OUT

LABEL RECORDS ARE OMI TTED.

01 OUT- REC PI C X( 132) .

WORKI NG- STORAGE SECTI ON. 01 WS- AREAS.

05 ARE- THERE- MORE- RECORDS PI C X( 3) VALUE ’ YES’ . 88 NO- MORE- RECORDS VALUE ’ NO ’ . 05 MATCH- FOUND PI C X( 3) VALUE ’ NO ’ . 01 I NVENTORY- TABLE.

05 WAREHOUSE OCCURS 50 TI MES I NDEXED BY X1. 10 I TEM- X OCCURS 100 TI MES I NDEXED BY X2.

15 PART- NO PI C 9( 4) . 15 UNI T- PRI CE PI C 999V99. 01 TRANS- REC- OUT.

05 PI C X( 9) VALUE SPACES.

05 PART- NO- OUT PI C 9( 4) .

05 PI C X( 5) VALUE SPACES.

05 QTY- OUT PI C 999.

05 PI C X( 5) VALUE SPACES.

05 TOTAL- AMT PI C $ZZZ, ZZZ. 99.

05 PI C X( 95) VALUE SPACES.

01 ERR- REC.

05 PI C X( 9) VALUE SPACES.

05 ERR- PART PI C 9( 4) .

05 PI C X( 5) VALUE SPACES.

05 PI C X( 114)

VALUE ’ PART NUMBER I S NOT I N TABLE’ . 01 HEADI NG- 1.

05 PI C X( 12) VALUE SPACES.

05 PI C X( 120)

VALUE ’ I NVENTORY REPORT’ . 01 HEADI NG- 2.

05 PI C X( 18)

VALUE ’ PART NO’ .

05 PI C X( 9) VALUE ’ QTY’ .

05 PI C X( 105)

VALUE ’ TOTAL AMT’ . *

PROCEDURE DI VI SI ON. 100- MAI N- MODULE.

PERFORM 700- I NI TI ALI ZATI ON- RTN. READ I NVENTORY- TABLE- I N

AT END MOVE ’ NO ’ TO ARE- THERE- MORE- RECORDS

END- READ.

PERFORM 200- TABLE- LOAD

VARYI NG X1 FROM 1 BY 1 UNTI L X1 > 50. MOVE ’ YES’ TO ARE- THERE- MORE- RECORDS. READ TRANSACTI ON- FI LE

AT END MOVE ’ NO ’ TO ARE- THERE- MORE- RECORDS

END- READ.

PERFORM 400- CALC- RTN UNTI L NO- MORE- RECORDS. PERFORM 800- END- OF- J OB- RTN. STOP RUN.

200- TABLE- LOAD.

PERFORM 300- LOAD- I T

VARYI NG X2 FROM 1 BY 1 UNTI L X2 > 100. 300- LOAD- I T.

I F T- WAREHOUSE- NO NOT EQUAL TO X1 DI SPLAY ’ TABLE I S NOT I N SEQUENCE’ CLOSE I NVENTORY- TABLE- I N

TRANSACTI ON- FI LE REPORT- OUT STOP RUN


(21)

Figure 13.2

(continued)

END- I F.

MOVE T- PART- NO TO PART- NO ( X1, X2) . MOVE T- UNI T- PRI CE TO UNI T- PRI CE ( X1, X2) . READ I NVENTORY- TABLE- I N

AT END MOVE ’ NO ’ TO ARE- THERE- MORE- RECORDS

END- READ.

400- CALC- RTN.

MOVE PART- NO- I N TO PART- NO- OUT. MOVE QTY- ORDERED TO QTY- OUT. MOVE ’ NO ’ TO MATCH- FOUND. PERFORM 500- SEARCH- I T

VARYI NG X1 FROM 1 BY 1 UNTI L X1 > 50

OR MATCH- FOUND = ’ YES’ . I F MATCH- FOUND = ’ YES’

WRI TE OUT- REC FROM TRANS- REC- OUT AFTER ADVANCI NG 2 LI NES ELSE

PERFORM 600- NO- MATCH- ERR

END- I F.

READ TRANSACTI ON- FI LE

AT END MOVE ’ NO ’ TO ARE- THERE- MORE- RECORDS

END- READ.

500- SEARCH- I T. SET X2 TO 1. SEARCH I TEM- X

WHEN PART- NO- I N = PART- NO ( X1, X2)

MULTI PLY UNI T- PRI CE ( X1, X2) BY QTY- ORDERED GI VI NG TOTAL- AMT

MOVE ’ YES’ TO MATCH- FOUND

END- SEARCH.

600- NO- MATCH- ERR.

MOVE PART- NO- I N TO ERR- PART. WRI TE OUT- REC FROM ERR- REC

AFTER ADVANCI NG 2 LI NES. 700- I NI TI ALI ZATI ON- RTN.

OPEN I NPUT I NVENTORY- TABLE- I N TRANSACTI ON- FI LE OUTPUT REPORT- OUT.

WRI TE OUT- REC FROM HEADI NG- 1 AFTER ADVANCI NG PAGE. WRI TE OUT- REC FROM HEADI NG- 2 AFTER ADVANCI NG 2 LI NES. 800- END- OF- J OB- RTN.

CLOSE I NVENTORY- TABLE- I N TRANSACTI ON- FI LE REPORT- OUT.

Note:Use scope t ermi nat ors (whi ch are i n col or) wi t h COBOL 8 5 onl y. Ot herwi se omi t t hem and end precedi ng l i nes wi t h a peri od.

Alternatively, we could use a

PERFORM . . .

VARYI NG . . .

AFTER

for searching the

table:

400- CALC- RTN.

MOVE PART- NO- I N TO PART- NO- OUT. MOVE QTY- ORDERED TO QTY- OUT. MOVE ’ NO ’ TO MATCH- FOUND. PERFORM

VARYI NG X1 FROM 1 BY 1

UNTI L X1 > 50 OR MATCH- FOUND = ’ YES’ AFTER X2 FROM 1 BY 1

UNTI L X2 > 100 OR MATCH- FOUND = ’ YES’ I F PART- NO- I N = PART- NO ( X1, X2)

MULTI PLY UNI T- PRI CE ( X1, X2) BY QTY- ORDERED

GI VI NG TOTAL- AMT MOVE ’ YES’ TO MATCH- FOUND


(22)

END- I F END- PERFORM.

I F MATCH- FOUND = ’ YES’

WRI TE OUT- REC FROM TRANS- REC- OUT AFTER ADVANCI NG 2 LI NES ELSE

PERFORM 600- NO- MATCH- ERR

END- I F.

READ TRANSACTI ON- FI LE

AT END MOVE ’ NO ’ TO ARE- THERE- MORE- RECORDS

END- READ.

Using the

PERFORM . . . VARYI NG . . . AFTER

, there is no need for the

SEARCH

in

500-SEARCH- I T

.

Searching Only Part of a Table

Suppose we wish to find the

UNI T- PRI CE

for an input

PART- NO- I N

stored at

WAREHOUSE

5

. There is no need to search the entire table, just those entries within

WAREHOUSE 5

.

Using the preceding

I NVENTORY- TABLE

, we could code the

SEARCH

as follows:

SET X2 TO 1.

SEARCH I TEM- Xkˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ

AT END PERFORM 700- ERR- RTN WHEN PART- NO- I N = PART- NO ( 5, X2)

DI SPLAY UNI T- PRI CE ( 5, X2)

END- SEARCH.

We use I TEM-X here.

The maj or i ndex X1 i n t he WHEN cl ause i s repl aced wi t h 5 because

we do not want i t t o vary.

We

SEARCH I TEM- X

, not

WAREHOUSE

, because we are looking for an item within a

specific warehouse, warehouse 5 in this instance.

DEBUGGING TIP

If we code:

01

I NVENTORY- TABLE.

05

WAREHOUSE OCCURS 50 TI MES I NDEXED BY X1.

10

I TEM- X OCCURS 100 TI MES I NDEXED BY X2.

15

PART- NO

PI C 9( 4) .

15

UNI T- PRI CE

PI C 999V99.

.

.

.

300- SEARCH.

SET X1, X2 TO 1.

SEARCH I TEM- X

.

.

.

the

PART- NO

s that will be searched are (1, 1) (1, 2) ... (1, 100). The major-level

index,

X1

, will

not

be varied. If we want to

SEARCH

the entire table (all warehouses

and all items), we need to code:

PERFORM 300- SEARCH

VARYI NG X1 FROM 1 BY 1

UNTI L X1 > 50.

.

.

.

300- SEARCH.

SET X2 TO 1.

SEARCH I TEM- X

.

.

.


(23)

If we code:

SET X1, X2 TO 1.

SEARCH WAREHOUSE

.

.

.

the

PART- NO

s searched will be (1, 1) (2, 1) ... (50, 1). That is, only the major-level

index,

X1

, will be varied, not the minor index,

X2

.

Searching Elements in an Array

A

SEARCH

can also be used with a multiple-level array for finding specific values in the

array. Consider the following double-level array:

01 ARRAY1.

05 STATE OCCURS 50 TI MES I NDEXED BY X1.

10 DI STRI CT OCCURS 10 TI MES I NDEXED BY X2. 15 POPULATI ON PI C 9( 10) .

To search an entire array such as the preceding, we use a

PERFORM . . . VARYI NG

,

which varies the major index and where the module being performed includes a

SEARCH

:

PERFORM VARYI NG X1

FROM 1 BY 1 UNTI L X1 > 50 SET X2 TO 1

SEARCH DI STRI CT .

. . END- PERFORM

Searching an Array until a Match is Found

In this example, we assume that there are precisely 10 districts per state. Each state,

then, has 10 districtwide population figures. Suppose there is

only one district

within the

United States with a population of 123,000 and we want to print its state and district

number. To do this, we must search the entire array until a match is found. When we

find a match, we want to print the values of the indexes since

X1

contains the state

number and

X2

the district number.

A

PERFORM . . . VARYI NG

is coded to increment the major index. The paragraph that

is performed will have a

SEARCH

that varies the minor index. That is, the statement

SEARCH DI STRI CT . . .

varies

X2

, the minor index, from 1 by 1 until a match is found

or

X2

exceeds 10.

X1

,

the major index, remains constant

in the

SEARCH

, at whatever value

it was initially set to. The

PERFORM . . . VARYI NG

will increment this major subscript.

Thus, to

SEARCH

the array until a ‘‘hit’’ or match is found, we would have:

SET is used in place of MOVE to transmit X1 and X2 to an output area

MOVE ’ NO ’ TO MATCH- FOUND. PERFORM 500- SEARCH- RTN

VARYI NG X1 FROM 1 BY 1

UNTI L X1 > 50 OR MATCH- FOUND = ’ YES’ . I F MATCH- FOUND NOT = ’ YES’

DI SPLAY ’ NO MATCH’

END- I F.

500- SEARCH- RTN. SET X2 TO 1. SEARCH DI STRI CT

WHEN POPULATI ON ( X1, X2) = 123000 SET X1- OUT TO X1


(24)

DI SPLAY X1- OUT, X2- OUT MOVE ’ YES’ TO MATCH- FOUND

END- SEARCH.

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Each SEARCH will test POPULATION (X1, 1) - POPULATION * * (X1, 10). The X1 index remains constant and is not * * incremented by the SEARCH. It is incremented by the * * PERFORM ... VARYING. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Each time through

500- SEARCH- RTN

,

X1

is set by the

PERFORM

, first to 1, then to 2,

and so on. Then, in

500- SEARCH- RTN

itself,

X2

is set to 1 before the array is actually

searched. Thus, the first execution of

500- SEARCH- RTN

will search the entries

( 1, 1) ,

( 1, 2) , . . . ( 1, 10)

. If no match is found, the entries

( 2, 1) , ( 2, 2) , . . . ( 2, 10)

will be searched the second time through

500- SEARCH- RTN

. This continues until a match

occurs (i.e., a district population

4

123000), or the array has been completely searched.

If a match is found, we want to print the values of the indexes, since

X1

will contain

the state number and

X2

, the district number.

X1

and

X2

, as indexes, cannot be used in

a

DI SPLAY

statement, so we must copy their contents to other fields using a

SET

instruc-tion. To move the contents of an index to other fields such as

X1- OUT

and

X2- OUT

, we

use the

SET

statement,

not

the

MOVE

statement.

Alternatively, we could use a

PERFORM . . . VARYI NG . . . AFTER

:

MOVE ’ NO ’ TO MATCH- FOUND.

PERFORM 500- SEARCH- RTN VARYI NG X1 FROM 1 BY 1

UNTI L X1 > 50

OR MATCH- FOUND = ’ YES’ AFTER X2 FROM 1 BY 1

UNTI L X2 > 10

OR MATCH- FOUND = ’ YES’ . 500- SEARCH- RTN.

I F POPULATI ON ( X1, X2) = 123000 SET X1- OUT TO X1

SET X2- OUT TO X2 DI SPLAY X1- OUT, X2- OUT

END- I F.

Searching an Entire Array for Multiple Matches

We can search the entire array for specific conditions

even after a match is found

. Suppose

we wish to find the total number of districts within the United States that have

popu-lations in excess of 100,000. In this instance, we want to continue our

SEARCH

even after

we find a ‘‘hit’’, that is, a district with a population greater than 100,000. To continue

searching a table after a ‘‘hit’’ or match, it is best to use a

PERFORM . . . VARYI NG . . .

AFTER

with an

I F

test, instead of a

SEARCH

:

MOVE ZERO TO CTR. PERFORM 200- COUNT- THEM

VARYI NG X1 FROM 1 BY 1 UNTI L X1 > 50 AFTER X2 FROM 1 BY 1 UNTI L X2 > 10. DI SPLAY CTR.

200- COUNT- THEM.

I F POPULATI ON ( X1, X2) > 100000 ADD 1 TO CTR

END- I F.

Suppose we wish to find the total number of districts in

STATE 3

with populations

less than 50,000. In this case, we want to keep the

STATE

index,

X1

, fixed at 3. To do

this, we could code the following:

MOVE ZERO TO CTR2. SET X1 TO 3.


(25)

VARYI NG X2 FROM 1 BY 1 UNTI L X2 > 10. DI SPLAY CTR2.

300- SEARCH- RTN.

I F POPULATI ON ( X1, X2) < 50000 ADD 1 TO CTR2

END- I F.

DEBUGGING TIP

When an array or a table is to be searched for one specific entry or match, use

the

SEARCH

verb. This is because the

SEARCH

instruction stops as soon as the

con-dition tested in the

WHEN

clause is met. You could, however, use a

PERFORM

with

an

I F

instead of a

SEARCH

. When a table or an array is being searched where there

may be more than one ‘‘hit’’ or match to be tabulated or counted, it is better to

use

PERFORM

s and an

I F

instead of the

SEARCH

. With multiple-level arrays or tables,

use a

PERFORM . . .

VARYI NG . . .

AFTER

with an

I F

test to check for multiple

matches.

T

RIPLE

- L

EVEL

OCCURS C

LAUSE AND

M

ORE

We have seen that

OCCURS

clauses may be written on one or two levels. We may also

use triple-level

OCCURS

clauses. A

maximum

of seven levels of

OCCURS

clauses may be

used with COBOL 85, but COBOL 74 permits only up to three levels.

Suppose we have a table consisting of 50 state populations. Each state is further

subdivided into 10 counties. Each county has precisely five district figures. The

follow-ing array may be coded in the

WORKI NG- STORAGE SECTI ON

:

01 POPULATI ON- TABLE.

05 STATE OCCURS 50 TI MES. 10 COUNTY OCCURS 10 TI MES.

15 DI STRI CT- POP OCCURS 5 TI MES PI C 9( 10) .

In this way, we have defined 2500 fields (50

2

10

2

5) in storage, each 10 positions

long. To access any field defined by several

OCCURS

clauses, we use the

lowest

-level

data-name. In this illustration, the data-name

DI STRI CT- POP

must be used to access any of

the 2500 fields of data.

Since

DI STRI CT- POP

is defined by a triple-level

OCCURS

clause,

three

subscripts are

used to access the specific field desired. The

first

subscript refers to the

major

-level item,

STATE

. The

second

subscript refers to the

intermediate

-level item,

COUNTY

. The

third

sub-script refers to the

minor

-level item,

DI STRI CT- POP

. Subscripts are always enclosed

within parentheses. Each subscript is separated from the next by a comma and a space.

If we code

DI STRI CT- POP ( 5, 4, 3)

, the

DI STRI CT- POP

specified refers to the

popu-lation figure for

STATE 5

,

COUNTY 4

,

DI STRI CT 3

. An item defined by a triple-level

OCCURS

clause is accessed with three subscripts.

Example 1

Write a routine to find the smallest figure in the

POPULATI ON- TABLE

array. (We assume that data

has already been placed in the array.) Store this smallest figure in

HELD

.

Using nested

PERFORM . . . VARYI NG

statements to achieve this looping, we have:

MOVE DI STRI CT- POP ( 1, 1, 1) TO HELD. PERFORM 200- RTN- 1

VARYI NG SUB1 FROM 1 BY 1 UNTI L SUB1 > 50. PERFORM 500- NEXT- RTN.

PERFORM 600- EOJ - RTN. 200- RTN- 1.

PERFORM 300- RTN- 2

VARYI NG SUB2 FROM 1 BY 1 UNTI L SUB2 > 10. 300- RTN- 2.


(26)

To display the temperature at 3

A

.

M

. on January 2, 1993, we have:

DI SPLAY HOURLY- TEMP ( 1, 2, 3)

. The number 1 refers to the first year specified, 1993; 2 refers to the second day of that year

and 3 refers to the third hour, or 3

A

.

M

.

To load the array, we could read 1095 (3 years

2

365 days) records each with 24 hourly

temperatures:

PERFORM 400- LOAD- I T VARYI NG SUB1 FROM 1 BY 1 UNTI L SUB1 > 3 AFTER SUB2 FROM 1 BY 1 UNTI L SUB2 > 365.

PERFORM 400- RTN- 3

VARYI NG SUB3 FROM 1 BY 1 UNTI L SUB3 > 5. 400- RTN- 3.

I F DI STRI CT- POP ( SUB1, SUB2, SUB3) < HELD MOVE DI STRI CT- POP ( SUB1, SUB2, SUB3) TO HELD

END- I F.

Using a

PERFORM . . . VARYI NG . . . AFTER

in the first

PERFORM

, we can eliminate

200- RTN- 1

and

300- RTN- 2:

PERFORM 400- RTN- 3

VARYI NG SUB1 FROM 1 BY 1 UNTI L SUB1 > 50 AFTER SUB2 FROM 1 BY 1 UNTI L SUB2 > 10 AFTER SUB3 FROM 1 BY 1 UNTI L SUB3 > 5.

Note that more than one

AFTER

clause can be used in a

PERFORM . . . VARYI NG

, with

the last one being performed first. That is, the minor subscript is varied first.

With COBOL 85, we can use nested in-line

PERFORM

s:

MOVE DI STRI CT- POP ( 1, 1, 1) TO HELD.

PERFORM VARYI NG SUB1 FROM 1 BY 1 UNTI L SUB1 > 50 PERFORM VARYI NG SUB2 FROM 1 BY 1

UNTI L SUB2 > 10 PERFORM VARYI NG SUB3 FROM 1 BY 1

UNTI L SUB3 > 5

I F DI STRI CT- POP ( SUB1, SUB2, SUB3) < HELD MOVE DI STRI CT- POP ( SUB1, SUB2, SUB3)

TO HELD

END- I F END- PERFORM END- PERFORM END- PERFORM.

PERFORM 500- NEXT- RTN. PERFORM 600- EOJ - RTN.

or

MOVE DI STRI CT- POP ( 1, 1, 1) TO HELD. PERFORM VARYI NG SUB1 FROM 1 BY 1

UNTI L SUB1 > 50

AFTER SUB2 FROM 1 BY 1 UNTI L SUB2 > 10 AFTER SUB3 FROM 1 BY 1 UNTI L SUB3 > 5

I F DI STRI CT- POP ( SUB1, SUB2, SUB3) < HELD MOVE DI STRI CT- POP ( SUB1, SUB2, SUB3)

TO HELD

END- I F END- PERFORM.

PERFORM 500- NEXT- RTN. PERFORM 600- EOJ - RTN.

Example 2

Suppose we want to store the hourly temperatures for Los Angeles or any other city for the years

1993 –1995. We could establish a triple-level or

three-dimensional

array as follows:

01 TEMPERATURE- ARRAY.

05 YEAR- X OCCURS 3 TI MES. 10 DAY- X OCCURS 365 TI MES.

15 HOURLY- TEMP OCCURS 24 TI MES PI C S9( 3) .


(27)

. . . 400- LOAD- I T.

READ DAY- TEMP- FI LE

AT END MOVE ’ NO ’ TO MORE- RECS

END- READ.

PERFORM 500- STORE- 24- VALUES

VARYI NG SUB3 FROM 1 BY 1 UNTI L SUB3 > 24. 500- STORE- 24- VALUES.

MOVE I N- TEMP ( SUB3) TO HOURLY- TEMP ( SUB1, SUB2, SUB3) .

To determine the average temperature for 1994 we could code in-line

PERFORM

s with COBOL

85 as follows:

MOVE 0 TO TOTAL. MOVE 2 TO SUB1.

PERFORM VARYI NG SUB2 FROM 1 BY 1 UNTI L SUB2 > 365 PERFORM VARYI NG SUB3 FROM 1 BY 1 UNTI L SUB3 > 24

ADD HOURLY- TEMP ( SUB1, SUB2, SUB3) TO TOTAL END- PERFORM

END- PERFORM.

COMPUTE AVERAGE = TOTAL / 8760.

DI SPLAY ’ THE AVERAGE TEMPERATURE FOR 1994 I S ’ , AVERAGE.

Note that there are

no

periods between the first

PERFORM

and the last

END- PERFORM

. We divide

TOTAL

by 8760, which is 365 days

2

24 hours.

To find the average temperature for January 3 for the three years 1993 –1995 we could code:

MOVE 0 TO TOTAL. MOVE 3 TO SUB2.

PERFORM 200- MAJ OR- RTN VARYI NG SUB1 FROM 1 BY 1 UNTI L SUB1 > 3.

COMPUTE AVERAGE = TOTAL / 72

DI SPLAY ’ THE AVERAGE TEMPERATURE FOR J AN 3 FOR 1993 – 1995 I S ’ , AVERAGE.

200- MAJ OR- RTN.

PERFORM 300- MI NOR- RTN VARYI NG SUB3 FROM 1 BY 1 UNTI L SUB3 > 24.

300- MI NOR- RTN.

ADD HOURLY- TEMP ( SUB1, SUB2, SUB3) TO TOTAL.

A

PERFORM . . . VARYI NG . . . AFTER

could be used instead. With COBOL 85, we could code

an in-line

PERFORM . . . VARYI NG . . . AFTER

as follows:

MOVE 0 TO TOTAL. MOVE 3 TO SUB2.

PERFORM VARYI NG SUB1 FROM 1 BY 1 UNTI L SUB1 > 3 AFTER SUB3 FROM 1 BY 1

UNTI L SUB3 > 24

ADD HOURLY- TEMP ( SUB1, SUB2, SUB3) TO TOTAL END- PERFORM.

COMPUTE AVERAGE = TOTAL / 72.

DI SPLAY ’ THE AVERAGE TEMPERATURE FOR J AN 3 FOR 1993 – 1995 I S ’ , AVERAGE.

Because seven levels of

OCCURS

are permitted with COBOL 85, a maximum of

six

AFTER

clauses are therefore allowed with COBOL 85. The limit for the number of

AFTER

clauses with COBOL 74 is two.

CHAPTER SUMMARY

A. Multiple-level

OCCURS

1. May be used for an array or a table.

2. The lowest-level

OCCURS

data-name or an item subordinate to it is used to access an entry

in the array or the table.

3. If we use a

SEARCH

for accessing a multiple-level table,

I NDEXED BY

must be used on all


(1)

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

* 800- ADD- RTN ADDS THE APPROPRI ATE ARRAY ELEMENT *

* TO THE TOTAL *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 800- ADD- RTN.

ADD AMOUNT- T ( WS- CTR1, WS- CTR2) TO WS- TOT- SALES.

Sample Input

02 022 10000 03 024 25000 03 021 30000 01 005 40000 01 005 10000 01 003 25000 05 004 12000 04 003 13000 05 003 12000 02 007 11000 06 005 60000

Records 1 –11

6

02 005 30000

07 003 04500 06 001 30000 04 002 12000 05 004 14500 02 005 13500 06 003 12500 01 019 80000 05 016 23000 01 018 90000 02 014 55500

Records 12 –22

6

02 023 45000

05 008 22000 01 008 23000 03 017 60000 02 011 22000 03 009 43000 05 015 50000 03 008 34000 02 006 23000 03 002 10000

Records 23 –32

6

DAY- I N

SLS- NUM- I N

AMOUNT- I N DAY- I N

SLS- NUM- I N

AMOUNT- I N DAY- I N

SLS- NUM- I N

AMOUNT- I N

Sample Output

Report of daily sales totals SALESPERSON REPORT PAGE 1 01/ 11/ 94 DAI LY FI GURES

DAY TOTAL SALES

MON $ 2, 680. 00

TUE $ 2, 100. 00

WED $ 2, 020. 00

THU $ 250. 00

FRI $ 1, 335. 00

SAT $ 1, 025. 00

SUN $ 45. 00

Sample Output Report of total sales for

each salesperson SALESPERSON REPORT PAGE 1 01/ 11/ 94

SALESPERSON TOTAL SALES

1 $ 300. 00

2 $ 220. 00

3 $ 670. 00

4 $ 265. 00

5 $ 1, 535. 00

6 $ 230. 00

Figure 13.4 (continued)


(2)

7 $ 110. 00

8 $ 790. 00

9 $ 430. 00

10 $ 0. 00

11 $ 220. 00

12 $ 0. 00

13 $ 0. 00

14 $ 555. 00

15 $ 500. 00

16 $ 230. 00

17 $ 600. 00

18 $ 900. 00

19 $ 800. 00

20 $ 0. 00

21 $ 300. 00

22 $ 100. 00

23 $ 450. 00

24 $ 250. 00

25 $ 0. 00

REVIEW QUESTIONS I. True-False

Questions

1. If an item is defined with a double-levelOCCURSclause, the first subscript refers to the lower-levelOCCURS.

2. Triple-level subscripting is the maximum for COBOL 85. 3. Subscripts and indexes must always be numeric. 4. The following entries define 5000 positions of storage:

01 TABLE- 1.

05 I TEM- 1 OCCURS 50 TI MES.

10 I TEM- 2 OCCURS 10 TI MES PI C S9( 10) .

5. An entry inTABLE- 1in Question 4 can be referenced by using eitherI TEM- 1orI TEM- 2in

thePROCEDURE DI VI SI ON.

Figure 13.4 (continued)


(3)

II. General Questions 1. There are 50 classes in College X. Each class has exactly 40 students. Each student has taken six exams. Write adouble-levelOCCURSclause to define an area of storage that will hold these scores.

2. Write atriple-levelOCCURSclause for Question 1.

3. Write the file and record description entries for a file of input records that will contain students’ test scores as described above. Each student record will contain six scores in the first 18 positions. The first record is for the first student in class 1, . . . the 40th record is for the 40th student in class 1, the 41st record is for the first student in class 2, and so on. 4. Using the solutions to Questions 2 and 3, write thePROCEDURE DI VI SI ONroutines to read

the exam records and to accumulate the data in the array. 5. Write a routine to find the class with the highest class average. 6. Write a routine to find the student with the highest average.

7. Write a routine to find the student with the highest grade for Exam 2. Print the student name and class number and the grade.

8. Print the number of students in class 5 with a grade on Exam 3 that was less than 65. 9. Write a routine using thePERFORM . . . VARYI NG . . . AFTERto give each student three extra

points as a curve.

10. Suppose a company has four health insurance plans with 3 options for each. Option 1

Employee Only

Option 2 Employee and Spouse

Option 3 Family

Health Plan 1

(basic) $510 $ 640 $1125

Health Plan 2

(major medical) 635 825 900

Health Plan 3

(comprehensive) 715 905 1300

Health Plan 4

(including dental) 975 1100 1725

The cost of each plan is apt to vary so we store the costs in an external table. a. Write theWORKI NG- STORAGEentries for the table.

b. Write a routine to find the cheapest plan for each option.

III. Validating Data Modify the Practice Program so that it includes coding to (1) test for all errors and (2) print a control listing of totals (records processed, errors encountered, batch totals).

DEBUGGING EXERCISES

Consider the following:

WORKI NG- STORAGE SECTI ON.

01 TABLE- 1.

05 WAREHOUSE OCCURS 5 TI MES.

10 STOCK- I TEMS OCCURS 150 TI MES.

15 I TEM- NO PI C 9( 3) .

15 PRI CE PI C 9( 4) .

*

PROCEDURE DI VI SI ON. 100- MAI N- MODULE.

OPEN I NPUT TABLE- FI LE TRANS- FI LE OUTPUT PRI NT- FI LE. READ TABLE- FI LE


(4)

PERFORM 200- TABLE- ENTRY

VARYI NG X1 FROM 1 BY 1 UNTI L X1 > 5. READ TRANS- FI LE

AT END MOVE ’ NO ’ TO MORE- TRANS- RECS

END- READ.

PERFORM 400- CALC- RTN UNTI L NO- MORE- TRANS- RECS. CLOSE TABLE- FI LE

TRANS- FI LE PRI NT- FI LE. STOP RUN.

200- TABLE- ENTRY.

PERFORM 300- ENTER- I T

VARYI NG X2 FROM 1 BY 1 UNTI L X2 > 150. 300- ENTER- I T.

MOVE T- I TEM- NO TO I TEM- NO ( X2, X1) . MOVE T- QTY- ON- HAND TO PRI CE ( X2, X1) . 400- CALC- RTN.

MOVE ACCT- NO TO ACCT- OUT. MOVE ACCT- NAME TO NAME- OUT. MOVE 0 TO FOUND- I T.

PERFORM 500- SEARCH- TABLE VARYI NG X1 FROM 1 BY 1

UNTI L X1 > 5 OR FOUND- I T = 1. WRI TE PRI NT- REC FROM DETAI L- REC

AFTER ADVANCI NG 2 LI NES. READ TRANS- FI LE

AT END MOVE ’ NO ’ TO MORE- TRANS- RECS

END- READ.

500- SEARCH- TABLE. SET X2 TO 1. SEARCH STOCK- I TEMS

WHEN I TEM- I N = I TEM- NO ( X1, X2) MULTI PLY QTY- I N BY PRI CE

GI VI NG GROSS- OUT MOVE 1 TO FOUND- I T

END- SEARCH.

1. Two syntax errors occur on the lines associated with theSETand theSEARCH. Both errors are the result of an omission withinTABLE- 1. Find and correct the error(s).

2. A program interrupt occurs during execution of300- ENTER- I T. Determine why and fix the error.

3. Suppose two warehouses have the sameI TEM- NO(e.g., 127). How will this affect processing? Would this processing be correct? If not, explain how you would modify the program. 4. Suppose the company has decided to increase the price of each item by 10% but has not yet

made the appropriate changes to the table entries. Make the necessary changes to400- CALC-RTNso thatGROSS- OUTis correct.

5. There is another way to make the 10% price increases. You can make them to the table entries as the table is entered. Recode the table-entry routine so that prices are increased by 10%. Which method is more efficient?

PROGRAMMING ASSIGNMENTS

1. Write a program to tabulate the number of employees by area within department. The problem definition appears in Figure 13.5.

Notes:

a. There are 10 areas within each department; there are 20 departments. Add 1 to a corres-ponding total for each employee record read.

b. Records are not in sequence.


(5)

CH 13-1 PROGRAM PRINT-FILE Systems Flowchart EMP-FILE 80-position records standard labels

1 2 3 4 5 6 7 8 91O1112134115161718192O21222324522627282930133233343563373839404124434445464748495051525345555657589560616263645666676869707172737475767778798081288384858687888990919293949596979899 1 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 24 25 26 27

PRINT-FILE Printer Spacing Chart

1 2 3 4 5 80

1 0 1 1 0 2 1 0 3 1 0 4 1 0 5 1 0 6 1 0 7 1 0 8 1 0 9 1 1 0 1 1 1 1 1 2 1 1 3 1 1 4 1 1 5 1 1 6 1 1 7 1 1 8 1 1 9 1 2 0 1 2 1 1 2 2 1 2 3 1 2 4 1 2 5 1 2 6 1 2 7 1 2 8 1 2 9 DEPT AREA1 OTHER-EMP-DATA EMP-FILE Record Layout

E R T E P A

D M

O L O T A

T N O F E MPL

9 T - 9 N

B E S

O Y E Y A R EA WITH I N DEPART M EN T

• • • • • A A R E 1

Z Z 9

A A R E 2

Z Z 9

A A R E 3

Z Z 9

A A R E 4

Z Z 9

A A R E 5

Z Z 9

A A R E 6

Z Z 9

A A R E 7

Z Z 9

A A R E 8

Z Z 9

A A R E 9

Z Z 9

A A R E 1

Z Z 9

0

E R T E P A

D M NT - 99 Z Z 9 Z Z 9 Z Z 9 Z Z 9 Z Z 9 Z Z 9 Z Z 9 Z Z 9 Z Z 9 Z Z 9

H

H

T

T

SSNO CLASS SCHOOL GPA

9V99 STUDENT

NAME CREDITSEARNED

1 9 10 30 31 32 33 35 36 38

1 = Freshman 2 = Sophomore 3 = Junior 4 = Senior

1 = Business 2 = Liberal Arts 3 = Engineering

2. Write a program to tabulate the number of employees by office within territory. The problem definition is shown in Figure 13.6. There is one input record for each employee.

Notes:

a. There are two offices within each territory; there are three territories. b. Records are not in sequence.

3. For Pass-Em State College, read in student records with the following format: Figure 13.5

Problem definition for Programming Assignment 1.

Assume the records are not in sequence. Set up a two-dimensional (324) array that will store the total number of students in each class within each school and their accumulatedGPAs. After all records have been read and processed, print the averageGPAper class in each school. The array should be established as follows:

01 ARRAY- 1.

05 SCHOOL OCCURS 3 TI MES.

10 CLASSES OCCURS 4 TI MES.

15 TOT- STUDENTS PI C 9( 3) .


(6)

CH 13-2 PROGRAM

EMPLOYEE-REPORT Systems Flowchart

PAYROLL-MASTER 80-position records standard labels 20 records/block

1 5 6 25 26

EMPLOYEE

NO. EMPLOYEENAME TERRITORYNO. PAYROLL-MASTER Record Layout

OFFICE NO.

JOB

CLASSIFI-CATION CODE 28

27 29 30 46 47 48 49 80

1 2 3 4 5 6 7 8 91O1112134115161718192O21222324522627282930133233343563373839404124434445464748495051525345555657589560616263645666676869707172737475767778798081288384858687888990919293949596979899 1 0 0 1

2 3 4 5 6 7 8 9 10 11 12 13 14 15

EMPLOYEE-REPORT Printer Spacing Chart

1 0 1 1 0 2 1 0 3 1 0 4

U L O T A T N MB E

H

H

H

T

P E O F

R M LO YEES BY O FF ICE W ITH I N TE RRITO RY 9 9 /9 9/99 P A GE 99

E R

T RITO RY - 99

N C E F F I

O O. T OTAL NO. OF EMPL OYE E S

9 9

• •

ZZ, Z Z9

• • •

For each class within each school divideACCUM- GPAby total number of students to get an averageGPA:

SCHOOL

CLASS TOTAL NO OF STUDENTS AVERAGE GPA

FRESHMAN 999 9. 99

SOPHOMORE 999 9. 99

J UNI OR 999 9. 99

SENI OR 999 9. 99

4. Redo the Practice Program in this chapter assuming the 25 salespeople have unique salesper-son numbers that can be anything from 001 to 999.

5. Interactive Processing. A store has five distribution centers that are numbered 1–5. Each distribution center sets its own prices for each of the 500 parts it stores, numbered 1–500. Write a program to load in as an external table unit prices for each of the 500 parts stored by each of the five distribution centers. Then, write an interactive module that enables a user to key in a requested distribution center and part number, and have the computer display the unit price for the requested part at the requested distribution center. Use appropriate prompts and error control procedures.

Figure 13.6 Problem definition for Programming Assignment 2.