Searching a table:
There are several variations that could be used instead of the sample code that I handed
out in the program called TABLSOUP.CBL.
Here is the relevant code from TABLSOUP.CBL:
Definition of the input field:
FD INPUT-FILE
DATA RECORD IS INPUT-REC.
01 INPUT-REC.
05 ORDER-NO PIC 9999.
05 ITEM-NUMBER-IN PIC 99.
WORKING-STORAGE entries:
01 INDICATORS.
05 MORE-RECS PIC XXX VALUE "YES".
05 MATCH-IND PIC XXX VALUE "NO".
01 SUBSCRIPTS.
05 ITEM-SUB PIC 99 VALUE 0.
01 TABLE-COMBINED.
05 FILLER PIC X(17) VALUE "03SEAFOOD CHOWDER".
05 FILLER PIC X(17) VALUE "12CORN CHOWDER ".
05 FILLER PIC X(17) VALUE "15CLAM CHOWDER ".
05 FILLER PIC X(17) VALUE "17TOMATO SOUP ".
05 FILLER PIC X(17) VALUE "24CHICKEN SOUP ".
05 FILLER PIC X(17) VALUE "25VEGETABLE SOUP ".
05 FILLER PIC X(17) VALUE "27ONION SOUP ".
05 FILLER PIC X(17) VALUE "28GREEN PEA SOUP ".
05 FILLER PIC X(17) VALUE "45WONTON SOUP ".
01 RDF-TABLE-COMBINED REDEFINES TABLE-COMBINED.
05 ENTRIES OCCURS 9 TIMES.
10 ITEM-NUMBER-TBL PIC 99.
10 ITEM-NAME-TBL PIC X(15).
PROCEDURE DIVISION entries:
B-200-LOOP.
IF LINE-CT > 55 OR PAGE-NO = 1
PERFORM B-310-HDR-ROUT.
MOVE SPACES TO PRINTZ.
MOVE ORDER-NO TO ORDER-NO-PR.
MOVE ITEM-NUMBER-IN TO ITEM-NUMBER-IN-PR.
MOVE 1 TO ITEM-SUB.
MOVE "NO " TO MATCH-IND.
PERFORM B-300-SEARCH
UNTIL ITEM-SUB > 9 OR MATCH-IND = "YES".
IF MATCH-IND = "YES"
MOVE ITEM-NAME-TBL (ITEM-SUB) TO ITEM-NAME-PR
ELSE
MOVE "*** INVALID ***" TO ITEM-NAME-PR.
WRITE PRINTZ
AFTER ADVANCING 1 LINES.
ADD 1 TO LINE-CT.
READ INPUT-FILE
AT END
MOVE "NO " TO MORE-RECS.
B-300-SEARCH.
IF ITEM-NUMBER-IN = ITEM-NUMBER-TBL (ITEM-SUB)
MOVE "YES" TO MATCH-IND
ELSE
ADD 1 TO ITEM-SUB.
The output that this program generates is shown below.
09/09/99 SOUP REPORT PAGE 1
ORDER ITEM # ITEM NAME
1111 12 CORN CHOWDER
1212 27 ONION SOUP
1224 45 WONTON SOUP
1225 28 GREEN PEA SOUP
2003 17 TOMATO SOUP
2027 28 GREEN PEA SOUP
3003 03 SEAFOOD CHOWDER
3010 34 *** INVALID ***
4012 15 CLAM CHOWDER
4078 50 *** INVALID ***
5000 19 *** INVALID ***
5012 24 CHICKEN SOUP
For the changes below assume that all of the DATA DIVISION entries remain the same
(although MATCH-IND is not used in all of them) and that only the procedure division is
changing.
The first and second examples illustrate two ways to code an early exit. Remember that the
early exit can only be used if the numbers in the table that are being searched are in
sequence. If the numbers are in random order, the whole table must be searched.
In the first early exit example, the early exit is including as one of the conditions in
the search statement. I add the OR the item number in the table that the subscript is
pointing to is greater than the item number from the input indicating that we have passed
the point where the match would be found.
B-200-LOOP.
...
MOVE 1 TO ITEM-SUB.
MOVE "NO " TO MATCH-IND.
PERFORM B-300-SEARCH
UNTIL ITEM-SUB > 9 OR MATCH-IND = "YES" OR
ITEM-NUMBER-TBL (ITEM-SUB) > ITEM-NUMBER-IN.
IF MATCH-IND = "YES"
MOVE ITEM-NAME-TBL (ITEM-SUB) TO ITEM-NAME-PR
ELSE
MOVE "*** INVALID ***" TO ITEM-NAME-PR.
WRITE PRINTZ
AFTER ADVANCING 1 LINES.
ADD 1 TO LINE-CT.
READ INPUT-FILE
AT END
MOVE "NO " TO MORE-RECS.
B-300-SEARCH.
IF ITEM-NUMBER-IN = ITEM-NUMBER-TBL (ITEM-SUB)
MOVE "YES" TO MATCH-IND
ELSE
ADD 1 TO ITEM-SUB.
In the second early exit example, I will test for the exit within the search loop and set
the indicator to NO meaning there can be no match. Because the indicator can be set to
either YES or NO, I am changing the initialization to moving three spaces to the match
indicator. If I do not find a match in the search paragraph, I then test to see if I have
passed the spot where a match would be. If that is true, I set the match indicator to NO.
Otherwise I add 1 to the subscript.
B-200-LOOP.
...
MOVE 1 TO ITEM-SUB.
MOVE " " TO MATCH-IND.
PERFORM B-300-SEARCH
UNTIL ITEM-SUB > 9 OR MATCH-IND NOT = " ".
IF MATCH-IND = "YES"
MOVE ITEM-NAME-TBL (ITEM-SUB) TO ITEM-NAME-PR
ELSE
MOVE "*** INVALID ***" TO ITEM-NAME-PR.
WRITE PRINTZ
AFTER ADVANCING 1 LINES.
ADD 1 TO LINE-CT.
READ INPUT-FILE
AT END
MOVE "NO " TO MORE-RECS.
B-300-SEARCH.
IF ITEM-NUMBER-IN = ITEM-NUMBER-TBL (ITEM-SUB)
MOVE "YES" TO MATCH-IND
ELSE
IF ITEM-NUMBER-TBL (ITEM-SUB) > ITEM-NUMBER-IN
MOVE "NO " TO MATCH-IND
ELSE
ADD 1 TO ITEM-SUB.
The next example deals a different way to code the original program. It does not
incorporate early exits. In this example instead of performing a paragraph, I have
embedded the perform code in the perform statement itself.
B-200-LOOP.
...
MOVE 1 TO ITEM-SUB.
MOVE "NO " TO MATCH-IND.
PERFORM
UNTIL ITEM-SUB > 9 OR MATCH-IND = "YES"
IF ITEM-NUMBER-IN = ITEM-NUMBER-TBL(ITEM-SUB)
MOVE "YES" TO MATCH-IND
ELSE
ADD 1 TO ITEM-SUB
END-IF
END-PERFORM
IF MATCH-IND= "YES"
MOVE ITEM-NAME-TBL (ITEM-SUB) TO ITEM-NAME-PR
ELSE
MOVE "*** INVALID ***" TO ITEM-NAME-PR.
WRITE PRINTZ
AFTER ADVANCING 1 LINES.
ADD 1 TO LINE-CT.
READ INPUT-FILE
AT END
MOVE "NO " TO MORE-RECS.
Finally, the last example shows the code without the match indicator. In this example the
test for a match has been move to a condition in the until to avoid using the indicator.
Since the test is being done, the search paragraph becomes a place where you simply add 1
to the subscript since you only go there when there is not a match. After the perform, the
IF had to be changed because I could not test for the indicator and I could not test for
the item number on the input equal to the item number in the table because the subscript
might have reached 10 and the test would therefore be out of bounds. Instead I tested for
the subscript greater than the size of the table and if it was, I handled the error
processing. My personal preference is to use it because I think the code is more
straightforward and does not involve coding if statements as part of the until clause.
B-200-LOOP.
...
MOVE 1 TO ITEM-SUB.
PERFORM B-300-SEARCH
UNTIL ITEM-SUB > 9 OR
ITEM-NUMBER-IN = ITEM-NUMBER-TBL (ITEM-SUB).
IF ITEM-SUB > 9
MOVE "*** INVALID ***" TO ITEM-NAME-PR
ELSE
MOVE ITEM-NAME-TBL (ITEM-SUB) TO ITEM-NAME-PR
END-IF
WRITE PRINTZ
AFTER ADVANCING 1 LINES.
ADD 1 TO LINE-CT.
READ INPUT-FILE
AT END
MOVE "NO " TO MORE-RECS.
B-300-SEARCH.
ADD 1 TO ITEM-SUB.