How do I get the size of an array in Cobol?

arrays, cobol

Solution

I would use a 78 item for the size and use it in the OCCURS and then if you want to make this size externally controlled you can add some conditional statements around it...

The vanilla portable example would be:

  WORKING-STORAGE SECTION.
  78 THIS-TABLE-SIZE VALUE 15.

   01 THIS-LENGTH    PIC 9(04).
   01 THIS-TABLE     PIC X(20) OCCURS THIS-TABLE-SIZE TIMES.
   PROCEDURE DIVISION.
      DISPLAY THIS-TABLE-SIZE.

However using $if.. the example would be:

  WORKING-STORAGE SECTION.
  $if THIS-TABLE-SIZE defined
  $display THIS-TABLE-SIZE is changed
  $else
   78 THIS-TABLE-SIZE VALUE 15.
  $end

   01 THIS-LENGTH    PIC 9(04).
   01 THIS-TABLE     PIC X(20) OCCURS THIS-TABLE-SIZE TIMES.
   PROCEDURE DIVISION.
      DISPLAY THIS-TABLE-SIZE.

Then the default compiled/run would yield:

Y:\DemoAndTests\size.of>cobol testprog.cbl nologo int();
* Generating testprog
* Data:         800     Code:         464     Literals:         144

Y:\DemoAndTests\size.of>run testprog
15

But if the constant is set...

Y:\DemoAndTests\size.of>cobol testprog.cbl nologo int() constant"THIS-TABLE-SIZE(20)";
THIS-TABLE-SIZE is changed
* Generating testprog
* Data:         896     Code:         464     Literals:         144

Y:\DemoAndTests\size.of>run testprog
20

I would also consider moving the 78 level to a copybook.

Problem

I want to get the length of a table (by which I mean the number of elements in an array) in COBOL. The convention I have seen is typically to hard-code it to match the occurrences in working storage. But I want the code to get the length, so that if the working storage is changed and the program recompiled, then the procedure division statements do no need to be changed. This is both to reduce maintenance effort, and prevent just "missing" a use in the 5000 lines of code, and potentially to allow the code to be in a copycode that could be used in multiple programs that have different table lengths. So here is the only solution I have come up with. ``` IDENTIFICATION DIVISION. PROGRAM-ID. TESTPROG. DATA DIVISION. WORKING-STORAGE SECTION. 01 THIS-LENGTH PIC 9(04). 01 THIS-GROUP. 05 THIS-TABLE PIC X(20) OCCURS 15 TIMES. PROCEDURE DIVISION. COMPUTE THIS-LENGTH = LENGTH OF THIS-GROUP / LENGTH OF THIS-TABLE. DISPLAY LENGTH OF THIS-GROUP ' / ' LENGTH OF THIS-TABLE ' = ' THIS-LENGTH. EXIT-PROG. STOP RUN. ``` And this outputs ``` 000000300 / 000000020 = 0015 ``` So that works, but it's pretty clunky. It requires a dummy group level around the rows, just to get the length of them. Is there a better way to do this?

Original source