This is probably a rookie question, but I still have a hard time working out how to use tables in COBOL.
Currently I'm writing a simple module that can be called by other programs. My program has to search an internal table for data and if not found, add to it.
I have this table:
01 TB-1 OCCURS 10 INDEXED X1.
03 CLIENT-NAME PIC N(30).
03 ORDER-NUMBER PIC 9(06).
Of course I can increase the amount of OCCURS so the likelihood of table overflow decreases. However, when testing the module, I have to deal with the scenario that there's one more record to add that doesn't fit in the table.
What is the best way of dealing with this? I was thinking of preventing an ABEND by giving back an error message.
To do this, I thought I'd define a new field and using it as a counter. So basically, every time my module adds a record, it adds +1 to the counter as well. Kind of like this:
IF COUNTER < 10
PERFORM ADD-RECORD
ELSE DISPLAY 'INPUT HAS EXCEEDED MAX OF 10 OCCURRENCES'
GOBACK
END-IF
.
ADD-RECORD.
MOVE INPUT-CLIENT-NAME TO CLIENT-NAME(X1) IN TB-1.
MOVE INPUT-ORDER-NUMBER TO ORDER-NUMBER(X1) IN TB-1.
ADD +1 TO COUNTER
.
Is this a good way to do this? Do you have any other ideas? Thanks in advance for your help.
The question misses the information what compiler you actually use, therefore you have to check which part of the answer works for you.
The best option is: no maximum (COBOL 2014 feature, not very likely that your compiler supports this)
01 TB-1 OCCURS DYNAMIC DEPENDING ON COUNTER
INDEXED X1.
03 CLIENT-NAME PIC N(30).
03 ORDER-NUMBER PIC 9(06).
As you already use a counter check if you use the INDEXED
clause (for example for SEARCH
), otherwise drop it and only use the counter.
In any case I personally prefer to use the counter for the bounds checking, even in your range (slightly less performant but safer as your program will abend if something is wrong):
01 BOUND-ERR.
03 FILLER PIC X(26) VALUE
'INPUT HAS EXCEEDED MAX OF '.
03 BOUND-MAX PIC 9(03).
03 FILLER PIC X(11) VALUE
'OCCURENCES.'.
01 TB-1-COUNT PIC 9(03) VALUE 0.
*> may not work on your compiler...
01 TB-1-MAX AS CONSTANT 10.
*> ... then try the level 78 extension:
78 TB-1-MAX VALUE 10.
*> if this doesn't work, too, then use REPLACE for the actual bound:
REPLACE TB-1-MAX BY 10.
01 TB-1 OCCURS 1 TO TB-1-MAX DEPENDING ON TB-1-COUNT
INDEXED BY X1.
03 CLIENT-NAME PIC N(30).
03 ORDER-NUMBER PIC 9(06).
IF TB-1-COUNT = TB-1-MAX
MOVE TB-1-MAX TO BOUND-MAX
DISPLAY BOUND-ERR
MOVE 1 TO RETURN-CODE
GOBACK
END-IF
ADD +1 TO TB-1-COUNT
SET X1 UP BY 1
MOVE INPUT-CLIENT-NAME TO CLIENT-NAME (X1) IN TB-1.
MOVE INPUT-ORDER-NUMBER TO ORDER-NUMBER (X1) IN TB-1.
The best way to deal with this is subject to interpretation. Eventually you will hit a limit and be unable to add a new entry in the table.
My experience has been that most programmers pick an upper bound for the table size that is both reasonable and bigger than they expect to need. E.g. when they are told there will never be more than 100 entries they make the table 200 entries in size.
If you are using IBM Enterprise COBOL v5.2 or later, you can specify...
01 TB-1 OCCURS 1 TO UNBOUNDED
DEPENDING NB-ITEMS INDEXED X1.
03 CLIENT-NAME PIC N(30).
03 ORDER-NUMBER PIC 9(06).
77 NB-ITEMS PIC 9(009) COMP VALUE 10.
...and you are fine until you hit 15,151,516 entries. This presumes the size of one occurrence is 66 bytes. The limit for an UNBOUNDED
table is 999,999,998 bytes; 999999998 / 66 = 15151515 (and change).
If you are using an earlier version of IBM Enterprise COBOL you can either pick a reasonable upper limit for your table size or you can venture into the land of dynamically allocating storage (via LE Callable Services), which is useful under certain circumstances but often is overkill.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With