Loading a table from input
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:
WS-COUNTis 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.- The guard comes before the store. With six branches the sixth is reported and skipped rather than written past the end of the table.
- 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:
- The number of days, which must be from 1 to 10
- 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.