MODULE 6 · TABLES · 2/8

Loading a table from input

14 min30 XPExercise

Hard-coding values into a program means recompiling whenever they change. In practice most tables are loaded at the start of the run from a file or parameter input: branch lists, product prices, exchange rates. Then the main processing looks values up in memory instead of rereading input.

Loading until a terminator

The shape is the priming-read loop you already know, plus a counter that doubles as the subscript:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. LOADDEMO.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-BRANCH-TABLE.
           05  WS-BRANCH      PIC X(10) OCCURS 5 TIMES.
       01  WS-COUNT           PIC 9(2) VALUE ZERO.
       01  WS-INPUT           PIC X(10).
       01  WS-I               PIC 9(2).
       PROCEDURE DIVISION.
           ACCEPT WS-INPUT
           PERFORM UNTIL WS-INPUT = "END"
               IF WS-COUNT = 5
                   DISPLAY "TABLE FULL - IGNORED: " WS-INPUT
               ELSE
                   ADD 1 TO WS-COUNT
                   MOVE WS-INPUT TO WS-BRANCH(WS-COUNT)
               END-IF
               ACCEPT WS-INPUT
           END-PERFORM
           PERFORM VARYING WS-I FROM WS-COUNT BY -1 UNTIL WS-I = 0
               DISPLAY WS-I ": " WS-BRANCH(WS-I)
           END-PERFORM
           STOP RUN.

With input CORK, DUBLIN, GALWAY, END it prints the branches in reverse:

03: GALWAY
02: DUBLIN
01: CORK

Three things to notice:

  1. WS-COUNT is both the count and the next free slot. Add 1, then store at that subscript. After the loop it holds the number of entries actually loaded.
  2. The guard comes before the store. With six branches the sixth is reported and skipped rather than written past the end of the table.
  3. Later loops use WS-COUNT, not 5. Only the loaded entries contain real data. The rest are whatever the table was initialised to.

Loading a known number of entries

If the input starts with a count, check the count first, then load with PERFORM VARYING:

           ACCEPT WS-DAYS
           IF WS-DAYS < 1 OR WS-DAYS > 10
               DISPLAY "INVALID DAY COUNT"
           ELSE
               PERFORM 1000-LOAD-DAY
                   VARYING WS-DAY FROM 1 BY 1 UNTIL WS-DAY > WS-DAYS
           END-IF

The count comes from outside the program, so treat it as untrusted. A header record claiming 5,000 entries must not be allowed to fill a 10-element table.

Why load at all?

Once the data is in a table you can make more than one pass over it. To list days with above-average sales you need the average first, which means seeing every day, and then you need to go back over the days again. Reading input only goes forward, so you keep the values in a table.

On the job

When a load hits the table limit, production programs usually do not just skip entries. They display a message and set a non-zero RETURN-CODE so the job scheduler stops the downstream steps and an operator gets paged. "Table full" abends after a business grows past a limit set in 1992 are a classic support ticket. The fix is to raise the OCCURS and the guard together.

Your task

A shop manager wants to know which days beat the average. Read:

  1. The number of days, which must be from 1 to 10
  2. That many daily sales amounts, one per line, e.g. 750.00

Load the amounts into the table WS-DAY-SALES (already declared in the starter). Then display the average, rounded to the cent, followed by each day whose sales are strictly greater than the average, and a count:

AVERAGE:   600.00
DAY 02:   750.00
DAY 04:  1250.00
DAYS ABOVE AVERAGE: 02

If the day count is outside 1–10, display only INVALID DAY COUNT.

Use WS-AMOUNT-OUT (PIC Z(4)9.99) to format both the average and the daily amounts.

fixed format
Run your program to see its output here. The first visible test's input and datasets are used.
Submit to grade your program against every test.