Chapter 16. MULTIPLE-LEVEL ARRAYS AND TABLES

CHAPTER OBJECTIVES

Upon completion of this chapter, you should be able to

  • Establish a series of items using a double-level OCCURS clause.

  • Demonstrate how to establish a series of items within a multiple-level array.

  • Demonstrate how to look up data stored in a multiple-level array.

  • Access and manipulate data defined with a triple-level (or more) OCCURS clause.

DOUBLE-LEVEL OCCURS CLAUSE

When describing an area of storage, as many as seven levels of OCCURS are permitted.

Like a single-level OCCURS, multiple levels of OCCURS may be used for (1) accumulating 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.

DEFINING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, 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, it is used to perform various calculations. The array consists of 7 × 24 temperature readings; that is, there are 24 hourly temperature readings for each of 7 days. The array is represented as

DEFINING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY

To define this array in WORKING-STORAGE with a single-level OCCURS would require the following coding.

DEFINING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY

The ellipses, or dots (. . .), indicate that 24 elementary items must be written, which would be rather cumbersome. Instead, use a double-level OCCURS clause to define the array as follows

DEFINING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY

The following illustration shows how this array is visualized in storage.

DEFINING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY

For each DAY-IN-WEEK, there are 24 HOUR figures, each of which consists of a TEMPERATURE (average or mean temperature for that hour) that is three integers long. Thus, this array defines a storage area of 504 positions (7 × 24 × 3). This two-dimensional array is established as follows.

  1. The array has 7 rows as indicated by the first OCCURS clause:

    05 DAY-IN-WEEK OCCURS 7 TIMES.
  2. Within this array, each row has 24 columns, as indicated by the second OCCURS clause:

    10 HOUR OCCURS 24 TIMES.
  3. Each of the elements in this 7 × 24 array is large enough to hold three integers, as indicated by the subordinate entry:

    15 TEMPERATURE PIC S9 (3).

To access any of the temperature figures, use the data-name on the lowest OCCURS level or any data-name subordinate to it. Either TEMPERATURE or HOUR could be used to access the temperatures. Because HOUR contains only one elementary item, TEMPERATURE and HOUR refer to the same area of storage. Thus, the array could also have been defined as

Alternative Coding

DEFINING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY

The PIC clause is added to the second OCCURS level data-name, thereby eliminating the reference to the data-name TEMPERATURE.

We use the entry TEMPERATURE throughout, however, since it is clearer. Note that DAY-IN-WEEK could not be used for accessing a single field in the array, since each DAY-IN-WEEK actually refers to 24 temperatures.

USING SUBSCRIPTS WITH DOUBLE-LEVEL OCCURS ENTRIES

Since TEMPERATURE is defined with two OCCURS clauses, two subscripts must be used to access any hourly temperature. The first subscript refers to the first or major-level OCCURS clause, which, in this example, specifies the DAY-IN-WEEK. The second subscript refers to the second, or minor, OCCURS level, which, in this example, specifies the HOUR. Thus, TEMPERATURE (1,6) refers to the temperature for Monday (the first row) at 6 A.M. (the sixth column in the array). Assuming there is data in the array, the temperature for Wednesday at noon can be displayed with the following instruction.

DISPLAY 'Temperature for Wednesday at noon is', TEMPERATURE (3, 12).

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.

A pictorial representation of the table with its subscripts is shown here:

USING SUBSCRIPTS WITH DOUBLE-LEVEL OCCURS ENTRIES

Following are rules for using a double-level OCCURS clause.

ACCESSING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY

Example 1

Suppose we wish to print an average temperature for the entire week. We need to add all the array elements into a total field and divide by 168 (7 × 24). Nested PERFORMs are used for this purpose. The first PERFORM varies the major subscript, DAY-SUB, and the second PERFORM varies the minor subscript, HOUR-SUB:

ACCESSING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY

Using in-line PERFORMs, the above can be written as

ACCESSING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY

When using nested in-line PERFORMs, there should be no periods until after the last END-PERFORM. A period is optional after the last END-PERFORM unless it is the last word in the paragraph.

THE PERFORM ... VARYING WITH THE AFTER OPTION

The following expanded format for the PERFORM . . . VARYING results in nested PERFORMs without the need for two separate PERFORM . . . VARYING statements:

Expanded Format

THE PERFORM ... VARYING WITH THE AFTER OPTION

This format is particularly useful for processing multiple-level arrays and tables. The PERFORM . . . VARYING varies the major subscript, and the AFTER clause varies the minor subscript. Thus, the preceding nested PERFORM is simplified as

Alternative Coding

THE PERFORM ... VARYING WITH THE AFTER OPTION

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 . . . VARYING . . . AFTER, DAY-SUB is initialized at 1 and HOUR-SUB is varied from 1 to 24. Then DAY-SUB is incremented 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

Suppose users want to make inquiries from the TEMPERATURE-ARRAY. The following could be used.

THE PERFORM ... VARYING WITH THE AFTER OPTION

Example 3

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

THE PERFORM ... VARYING WITH THE AFTER OPTION

This array defines 500 fields of data or 5000 characters. Each of the 50 states is divided into 10 counties, each with 10 digits. We have arbitrarily selected 10 counties per state, each with a POPULATION 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.

THE PERFORM ... VARYING WITH THE AFTER OPTION

Note: The number is parentheses represent the subscripts for each entry.

Suppose we wish to accumulate a total United States population. The population of all 10 counties for each of 50 states are added. The lowest level item, POPULATION, is used to access the elements in the array. POPULATION must be accessed using two subscripts. The first defines the major level, STATE, and the second defines the minor level, COUNTY. POPULATION (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, the COUNTY figures for STATE 1 are accumulated. Thus, the second or minor subscript varies from 1 to 10. After 10 additions for STATE 1 are performed, the 10 COUNTY figures for STATE 2 are accumulated. That is, the major subscript is incremented to 2 and then COUNTY (2, 1), COUNTY (2, 2), . . . COUNTY (2, 10) are accumulated before the figures for STATE 3 are added.

The required operations may be performed in two ways:

  1. Using Nested PERFORMs

  2. Using PERFORM . . . VARYING . . . AFTER

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:

USING NESTED PERFORMS

With in-line nested PERFORMs, this would be specified as

USING NESTED PERFORMS

USING PERFORM ... VARYING ... AFTER

Using the AFTER option of the PERFORM . . . VARYING, we simplify as follows.

USING PERFORM ... VARYING ... AFTER

The following illustrates how this procedure could be written using an in-line PERFORM.

USING PERFORM ... VARYING ... AFTER

The program varies 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, STATE-SUB is set equal to 1 and COUNTY-SUB is varied from 1 to 10. STATE-SUB is then set to 2, and COUNTY-SUB is varied from 1 to 10, and so on.

The sequence of additions may also be performed as follows: POPULATION (1, 1), POPULATION (2, 1), . . . POPULATION (50, 1); POPULATION (1, 2), POPULATION (2, 2), . . . POPULATION (50, 2), . . . POPULATION (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 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

USING PERFORM ... VARYING ... AFTER

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

Example 4

Suppose an array is established that contains 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 numbered from 1 to 25, consecutively. The WORKING-STORAGE SECTION entry for this array is

USING PERFORM ... VARYING ... AFTER

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 consecutively: the MONTH-AMOUNT from 1 to 12, and the SALESPERSON 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 salespersons 1 through 25. Line 2 contains 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 WORKING-STORAGE as follows.

USING PERFORM ... VARYING ... AFTER

A single-level OCCURS clause is used to describe the 25 sales totals within SALES-LINE. Since each line contains 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 SALES-TOTAL, which OCCURS 25 TIMES, consists of two fields, MONTHLY-SALESPERSON-TOTAL and a one-position blank area. This one-position blank 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

USING PERFORM ... VARYING ... AFTER

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:

USING PERFORM ... VARYING ... AFTER

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 consider how to ADD to fields in the array. We end that section with the program that produces the output specified above.

USING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY FOR ACCUMULATING TOTALS

Suppose a company has 10 departments and five salespeople (numbered 1–5) within each department. To accumulate the total amount of sales for each salesperson within each department, a two-dimensional array is established:

USING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY FOR ACCUMULATING TOTALS

The total area must be initialized to zero before adding any data to the total area. To initialize an entire array at zero, the following two statement could be used: INITIALIZE DEPARTMENT-TOTALS or MOVE ZEROS TO DEPARTMENT-TOTALS. Alternatively, we can write

USING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY FOR ACCUMULATING TOTALS

Initializing or moving zeros to DEPARTMENT-TOTALS replaces all fields with 0; note, however, that MOVE 0 TO DEPARTMENT-TOTALS only moves a 0 to the leftmost position in the array. This is because DEPARTMENT-TOTALS, as a group item, is treated as an alphanumeric field; if a single 0 is moved to an alphanumeric field, the 0 is placed in the leftmost position; all other positions are replaced with blanks.

Assume an input record has been created each time a salesperson makes a sale. Each input record contains a department number called DEPARTMENT-IN, a salesperson number called SALESPERSON-NUMBER-IN, and an amount of sales called AMOUNT-IN. There might be numerous 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.

USING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY FOR ACCUMULATING TOTALS

As indicated previously, input fields may be used as subscripts. For correct processing, a validation procedure should be used to ensure that (1) DEPARTMENT-IN is an integer between 1 and 10, and (2) SALESPERSON-NUMBER-IN is an integer between 1 and 5. AMOUNT-IN should also be checked to ensure that it is numeric.

USING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY FOR ACCUMULATING TOTALS

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 DIVISION is as follows.

USING A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY FOR ACCUMULATING TOTALS

In this illustration, we assume that the values for DEPARTMENT-IN vary from 1–10 and the values for SALESPERSON-NUMBER-IN 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. The input consists of transaction records, each with the following format.

Field Description

Type

Size

COBOL Field-names

Salesperson Number

S

2,0

SALESPERSON-NUMBER-IN

Sales Amount

P

3,0

SALES-AMOUNT-IN

Month

S

2,0

MONTH-IN

Day

S

2,0

DAY-IN

Year

S

4,0

YEAR-IN

The full program for printing monthly sales totals that uses procedures discussed in this section appears in Figure 16.1.

Program for printing monthly sales totals.

Figure 16.1. Program for printing monthly sales totals.

LOADING INPUT DATA INTO A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, 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 READ . . . INTO.

Consider again our TEMPERATURE-ARRAY from the beginning of this chapter.

LOADING INPUT DATA INTO A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY

Suppose we have seven input records, each with 24 three-position hourly temperatures. 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.

LOADING INPUT DATA INTO A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY

The ARRAY-LOAD routine could be executed as follows. We use subscript names here that are more meaningful than SUB and SUB1.

LOADING INPUT DATA INTO A DOUBLE-LEVEL, OR TWO-DIMENSIONAL, ARRAY

If there are not exactly seven records in TEMPERATURE-FILE, 240-ERROR-RTN will be executed, which terminates the job.

PERFORMING A LOOK-UP USING A DOUBLE-LEVEL 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.

Assume that the following table has been loaded into storage.

PERFORMING A FULL TABLE LOOK-UP

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-NUMBER 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 records have the following format.

Field Description

Type

Size

COBOL Field-names

Part Number

S

4,0

PART-NUMBER-IN

Quantity Ordered

P

3,0

QUANTITY-ORDERED-IN

For each PART-NUMBER-IN, the program needs to look up the corresponding PART-NUMBER in the table and find its UNIT-PRICE. The unit price for each part is stored in the table and not in the transaction record for these reasons:

  1. If each input 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 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 INVENTORY-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 report. Each time a PART-NUMBER is ordered, the program prints the PART-NUMBER and the TOTAL-AMOUNT of the transaction, where TOTAL-AMOUNT = QUANTITY-ORDERED (from the input record) * UNIT-PRICE (from the table). Since we will use a SEARCH, the table we have described must include the appropriate INDEXED BY clauses with each OCCURS level item:

PERFORMING A FULL TABLE LOOK-UP

THE IDENTIFIER USED WITH THE SEARCH REFERS TO THE LOWEST-LEVEL OCCURS ENTRY

To SEARCH the table, we write SEARCH ITEM . . . because ITEM is the lowest-level OCCURS entry. Note that SEARCH ITEM increments the lowest-level index only. Hence, if SUB 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 executed from a PERFORM . . . VARYING that increments the major index, SUB.

The routine would then appear as

THE IDENTIFIER USED WITH THE SEARCH REFERS TO THE LOWEST-LEVEL OCCURS ENTRY

MATCH-FOUND is a field that is initialized at 'NO' and changed to 'YES' only when the corresponding PART-NUMBER in the table is found. We terminate 500-SEARCH-IT when a match is found (MATCH-FOUND = 'YES') or the entire table has been searched (SUB > 50). 600-NO-MATCH-ERROR would be executed only if no match existed between the PART-NUMBER-IN and a table entry.

The full program for this example appears in Figure 16.2.

Program for performing a look-up using a double-level OCCURS.

Figure 16.2. Program for performing a look-up using a double-level OCCURS.

Alternatively, we could use a PERFORM . . . VARYING . . . AFTER for searching the table:

Program for performing a look-up using a double-level OCCURS.

Using the PERFORM . . . VARYING . . . AFTER, there is no need for the SEARCH in 500-SEARCH-IT.

SEARCHING ONLY PART OF A TABLE

Suppose we wish to find the UNIT-PRICE for PART-NUMBER-IN stored at WAREHOUSE 5. There is no need to search the entire table, just those entries within WAREHOUSE 5. Using the preceding INVENTORY-TABLE, we could write the SEARCH as

SEARCHING ONLY PART OF A TABLE

We use ITEM in the SEARCH statement. The major index in the WHEN clause is replaced with 5 because we do not want it to vary. We SEARCH ITEM, not WAREHOUSE, because we are looking for an item within a specific warehouse, warehouse 5 in this instance.

VARYING ONLY ONE INDEX

If we write

VARYING ONLY ONE INDEX

the PART-NUMBERs that will be searched are (1, 1), (1, 2) . . . (1, 100). The major-level index, SUB, will not be varied. If we want to SEARCH the entire table (all warehouses and all items), we need to write

VARYING ONLY ONE INDEX

If we write

VARYING ONLY ONE INDEX

the PART-NUMBERs searched will be (1, 1), (2, 1) . . . (50, 1). That is, only the major-level index, SUB, will be varied, not the minor index, SUB1.

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.

SEARCHING ELEMENTS IN AN ARRAY

To search an entire array, we use a PERFORM . . . VARYING, which varies the major index and in which the module being performed includes a SEARCH:

SEARCHING ELEMENTS IN AN ARRAY

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 district-wide 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 SUB contains the state number and SUB1 the district number.

A PERFORM . . . VARYING is written to increment the major index. The paragraph that is performed will have a SEARCH that varies the minor index. That is, the statement SEARCH DISTRICT . . . varies SUB1, the minor index, from 1 by 1 until a match is found or SUB1 exceeds 10. SUB, the major index, remains constant in the SEARCH, at whatever value to which it was initially set. The PERFORM . . . VARYING will increment this major subscript. Thus, to SEARCH the array until a "hit" or match is found, we would have:

SEARCHING AN ARRAY UNTIL A MATCH IS FOUND

Each time through 500-SEARCH-RTN, SUB is set by the PERFORM: first to 1, then to 2, and so on. Then, in 500-SEARCH-RTN itself, SUB1 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 = 123000), or the array has been completely searched. If a match is found, we want to print the values of the indexes, since SUB will contain the state number and SUB1, the district number.

SUB and SUB1, as indexes, cannot be used in a DISPLAY statement, so we must copy their contents to other fields using a SET instruction. To move the contents of an index to other fields, such as SUB-OUT and SUB1-OUT, we use the SET statement, not the MOVE statement.

Alternatively, we could use a PERFORM . . . VARYING . . . AFTER:

SEARCHING AN ARRAY UNTIL A MATCH IS FOUND

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 populations 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 . . . VARYING . . . AFTER with an IF test, instead of a SEARCH:

SEARCHING AN ENTIRE ARRAY FOR MULTIPLE MATCHES

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, SUB, fixed at 3. To do this, we could write the following.

SEARCHING AN ENTIRE ARRAY FOR MULTIPLE MATCHES

Tip

Debugging Tip

When an array or 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 condition tested in the WHEN clause is met. When a table or array is being searched, where there may be more than one hit or match to be tabulated or counted, it is better to use PERFORMs and an IF instead of the SEARCH. With multiple-level arrays or tables, use a PERFORM . . . VARYING . . . AFTER with an IF test to check for multiple matches.

TRIPLE-LEVEL OCCURS CLAUSES AND MORE

We have seen that OCCURS clauses may be written on one or two levels. We may also use triple-level OCCURS clauses.

Suppose we have a table consisting of 50 state populations. Each state is further subdivided into 10 counties. Each county has precisely five districts. The following array may be specified in the WORKING-STORAGE SECTION.

TRIPLE-LEVEL OCCURS CLAUSES AND MORE

In this way, we have defined 2500 fields (50 × 10 × 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 DISTRICT-POPULATION must be used to access any of the 2500 fields of data.

Since DISTRICT-POPULATION 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 subscript refers to the minor-level item, DISTRICT-POPULATION. Subscripts are always enclosed within parentheses. Each subscript is separated from the next by a comma and a space. If we write DISTRICT-POPULATION (5, 4, 3), the DISTRICT-POPULATION specified refers to the population figure for STATE 5, COUNTY 4, DISTRICT 3.

Example 1

Write a routine to find the smallest figure in the POPULATION-TABLE array. (We assume that data has already been placed in the array.) Store this smallest figure in SMALLEST.

Using nested PERFORM . . . VARYING . . . AFTER statements to achieve this looping, we have:

TRIPLE-LEVEL OCCURS CLAUSES AND MORE

Note that more than one AFTER clause can be used in a PERFORM . . . VARYING, with the last one being performed first. That is, the minor subscript is varied first.

We can also use nested in-line PERFORMs:

TRIPLE-LEVEL OCCURS CLAUSES AND MORE

Example 2

Suppose we want to store the hourly temperatures for Los Angeles, or any other city, for the years 2000–2002. We could establish a triple-level, or three-dimensional, array as follows.

TRIPLE-LEVEL OCCURS CLAUSES AND MORE

Note that a PIC of S9 (3) allows for temperatures from −999 to 999.

To display the temperature at 3 A.M. on January 2, 2000, we have: DISPLAY HOURLY-TEMPERATURE (1, 2, 3). The number 1 refers to the first year specified, 2000; 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 × 365 days) records each with 24 hourly temperatures:

TRIPLE-LEVEL OCCURS CLAUSES AND MORE

To determine the average temperature for 2001, we could write in-line PERFORMs as follows.

TRIPLE-LEVEL OCCURS CLAUSES AND MORE

Note that there are no periods between the PERFORM and the END-PERFORM. We divide TOTAL by 8760, which is 365 days × 24 hours.

To find the average temperature for January 3 for the three years 2000–2002, we write:

TRIPLE-LEVEL OCCURS CLAUSES AND MORE

END-OF-CHAPTER AIDS

CHAPTER SUMMARY

Multiple-level OCCURS.

  1. Multiple-level OCCURS 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, INDEXED BY must be used on all OCCURS levels.

  4. The identifier used with the SEARCH statement should typically be the one on the lowest OCCURS level. Only the index on the same level as the OCCURS level will be incremented by the SEARCH. That is, SEARCH XXX, for example, will vary only the index specified with XXX. Consider the following.

    05 MONTHLY-AMOUNT OCCURS 10 TIMES INDEXED BY SUB1

    SUB1 is the only index incremented in the search regardless of whether MONTHLY-AMOUNT is subordinate to an OCCURS or contains another level of OCCURS.

KEY TERMS

None

CHAPTER SELF-TEST

TRUE-OR-FALSE QUESTIONS

  • 1. If an item is defined with a double-level OCCURS clause, the first subscript refers to the lower-level OCCURS.

  • 2. Triple-level subscripting is the maximum for COBOL/400.

  • 3. Subscripts and indexes must always be numeric.

  • 4. The following entries define 5000 positions of storage.

    TRUE-OR-FALSE QUESTIONS
  • 5. An entry in TABLE-1 in Question 4 can be referenced by using either ITEM-1 or ITEM-2 in the PROCEDURE DIVISION.

FILL-IN-THE BLANKS

  1. With MOVE ITEM-IN (SUB1, SUB2) TO WS-HOLD-ITEM, SUB1 refers to the ___ -level OCCURS clause and SUB2 refers to the ___ -level OCCURS clause.

  2. Consider the following DATA DIVISION entry.

    FILL-IN-THE BLANKS
    1. The number of storage positions reserved for this area is ___.

    2. The data-name that may be used to access a field in the PROCEDURE DIVISION is ___.

    3. If ITEM-IN (COUNTERA, COUNTERB) is used in the PROCEDURE DIVISION, then COUNTERA may vary from ___ to ___ and COUNTERB may vary from ___.

  3. If three subscripts are used to access an item, the first refers to the ___ level, the second to the ___ level, and the third to the ___ level.

  4. Each subscript within the parentheses is separated from the next by a ___ followed by ___.

  5. If a SEARCH is used for accessing a double-level table, a(n) ___ clause must be used on both OCCURS levels.

GENERAL QUESTIONS

  1. There are 50 classes in College X. Each class has exactly 40 students. Each student has taken six exams. Write a double-level OCCURS clause to define an area of storage that will hold these scores. Write a triple-level OCCURS clause for the same scores.

  2. 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.

  3. Using the solutions to Questions 1 and 2, write the PROCEDURE DIVISION routines to read the exam records and to accumulate the data in the array.

  4. Write a routine to find the class with the highest class average.

  5. Write a routine to find the student with the highest average.

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

  7. Print the number of students in class 5 with a grade on Exam 3 that was less than 65.

  8. Write a routine using the PERFORM . . . VARYING . . . AFTER to give each student three extra points as a curve.

  9. Using the following TEMPERATURE-ARRAY:

    GENERAL QUESTIONS
    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 was the highest temperature.

    4. Find the number of days when the temperature fell below 32° at any hour. Could PERFORM . . . VARYING . . . AFTER be used?

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

  10. Assume the following triple-level array has been loaded.

    GENERAL QUESTIONS
    1. How many warehouses are there?

    2. How many products are stored in each warehouse?

    3. How many suppliers are there for each product?

    4. Write a program excerpt using an in-line PERFORM to print the names of the product suppliers for product number 10 in warehouse 5.

    5. Print the number of products in warehouse 4 that have ACME as a product supplier.

  11. Consider our population array:

    GENERAL QUESTIONS

    Assume there are 500 input records with the following format.

    Field Description

    Type

    Size

    COBOL Field-name

    State Number

    S

    2,0

    STATE-NUMBER-IN

    County Number

    S

    2,0

    COUNTY-NUMBER-IN

    Population

    P

    11,0

    POPULATION-IN

    Write a routine to load each record into the POPULATION-ARRAY.

  12. Assume the input records have the following format:

     

    Field Description

    Type

    Size

    County 1

    Population

    S

    11,0

    County 2

    Population

    S

    11,0

    County 3

    Population

    S

    11,0

    County 4

    Population

    S

    11,0

    County 5

    Population

    S

    11,0

    County 6

    Population

    S

    11,0

    County 7

    Population

    S

    11,0

    County 8

    Population

    S

    11,0

    County 9

    Population

    S

    11,0

    County 10

    Population

    S

    11,0

    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 POPULATION-ARRAY.

  13. Assume the input records have the following format.

     

    Field Description

    Type

    Size

    State 1

    Population

    S

    11,0

    State 2

    Population

    S

    11,0

    .

       

    .

       

    .

       

    State 50

    Population

    S

    11,0

    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 POPULATION-ARRAY.

  14. Suppose records were read with the format as follows.

     

    Field Description

    Type

    Size

    County 1

    Population

    S

    11,0

    County 2

    Population

    S

    11,0

    County 3

    Population

    S

    11,0

    County 4

    Population

    S

    11,0

    County 5

    Population

    S

    11,0

    County 6

    Population

    S

    11,0

    County 7

    Population

    S

    11,0

    County 8

    Population

    S

    11,0

    County 9

    Population

    S

    11,0

    County 10

    Population

    S

    11,0

    There are 50 such records, where the first record is for STATE 1, the second is for STATE 2, and so on.

    If we want to print a report as follows, what type of array would we need in WORKING-STORAGE to print the 50 state population totals?

    GENERAL QUESTIONS
  15. Suppose records were read with the following format.

 

Field Description

Type

Size

State 1

Population

S

11,0

State 2

Population

S

11,0

.

   

.

   

.

   

State 50

Population

S

11,0

To print the following report, what type of array would we need in WORKING-STORAGE to process the data?

GENERAL QUESTIONS

DEBUGGING EXERCISES

Consider the following.

DEBUGGING EXERCISES
  1. Two syntax errors occur on the lines associated with the SET and the SEARCH. Both errors are the result of an omission within TABLE-1. Find and correct the error(s).

  2. A program interrupt occurs during execution of 300-ENTER-IT. Determine the reason and fix the error.

  3. Suppose two warehouses have the same ITEM-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 percent but has not yet made the appropriate changes to the table entries. Make the necessary changes to 400-CALCULATION-RTN so that GROSS-OUT is correct.

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

PRACTICE PROGRAM

Write a program to print two sales reports. The first report prints seven daily totals, edited. The second report prints 25 salesperson totals, edited. The Sales file is shown below.

Record description layout for sales file

Field Description

Type

Size

COBOL Field-name

Day Number

S

2,0

DAY-OF-WEEK

Salesperson Number

S

3,0

SALESPERSON-NUMBER

Transaction Amount

P

7,2

TRANSACTION-NUMBER

Notes:

  1. For the first report, each daily total represents the sum of all 25 salesperson sales totals for the corresponding day. For the second report, each salesperson total represents the sum of the seven daily sales totals for the corresponding salesperson.

  2. Records are not in sequence.

Report of daily sales totals

PRACTICE PROGRAM

Report of total sales for each salesperson

PRACTICE PROGRAM

The following is a sample of the structured pseudocode for this problem.

PRACTICE PROGRAM

PROGRAMMING ASSIGNMENTS

  1. Write a program to read the employee file and print a report that will tabulate the number of employees by department within region. The employee file contains the following data.

    Record description layout for employee file

    Field Description

    Type

    Size

    COBOL Field-name

    Employee Number

    S

    5,0

    EMPLOYEE-NUMBER

    Region

    S

    3,0

    REGION

    Department

    S

    2,0

    DEPARTMENT

    Notes:

    1. There are 10 departments within each region with a maximum of 20 regions.

    2. The departments are numbered 1 through 10. The region numbers are not numbered in any particular sequence.

    3. Add 1 to a corresponding total for each employee record-read.

    4. Records are not in sequence.

    5. All totals should be edited to suppress high-order zeros.

    Report of total number of employees by department within region

    PROGRAMMING ASSIGNMENTS
  2. Write a program to tabulate the number of employees by office within territory. There is one payroll master record for each employee.

    Record description layout for payroll master file

    Field Description

    Type

    Size

    COBOL Field-name

    Employee Number

    S

    5,0

    EMPLOYEE-NUMBER

    Employee Name

    A

    20

    EMPLOYEE-NAME

    Territory Number

    S

    2,0

    TERRITORY-NUMBER

    Office Number

    S

    2,0

    OFFICE-NUMBER

    Job Class Code

    S

    2,0

    JOB-CLASS-CODE

    Report of total number of employees by office within territory

    PROGRAMMING ASSIGNMENTS

    Notes:

    1. There are two offices within each territory; there are three territories.

    2. Print each territory on a new page.

    3. Records are not in sequence.

  3. For Pass-Em State College, print the average GPA report by reading in student records with the following student record file:

    Record description layout for student record file

    Field Description

    Type

    Size

    COBOL Field-name

    Student Number

    S

    9,0

    STUDENT-NUMBER

    Student Name

    A

    20

    STUDENT-NAME

    Class

    S

    1,0

    CLASS

    School

    S

    1,0

    SCHOOL

    GPA

    S

    3,2

    GPA

    Credits Earned

    P

    3,0

    CREDITS-EARNED

    Class Codes

    1 = Freshman

    2 = Sophomore

    3 = Junior

    4 = Senior

    School Codes

    1 = Business

    2 = Liberal Arts

    3 = Engineering

    Notes:

    1. Assume the records are not in sequence.

    2. Set up a two-dimensional (3 × 4) array that will store the total number of students in each class within each school and their accumulated GPAs.

    3. Print each school on a different page.

    4. After all records have been read and processed, print the average GPA per class in each school.

    5. For each class within each school divide the accumulated GPA by the total number of students in the class to get an average GPA:

    Average GPA report

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

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset