Search code examples
cobolgnucobol

Table indexing in cobol


I have a 2-D array in cobol and I want to write each row to the output file. I write the following code to do this.

FILE-SECTION.
01 FILE-TABLE.
   05 FILE-TABLE-ROW OCCURS 10 TIMES INDEXED BY I.
      10 FILE-TABLE-COL PIC X(1) OCCURS 10 TIMES INDEXED BY J.

SET I TO 1.
PAR-A.
IF I <= 10 THEN
   WRITE FILE-TABLE-ROW(I)
   SET I UP BY 1
   GO TO PAR-A
END-IF.

Surprisingly, the compiler report the error "FILE-TABLE-ROW needs one subscript" at the WRITE FILE-TABLE-ROW(I) LINE. I don't understand why this is an error.


Solution

  • First off all I see you've now gone for the contracted table with OCCURS after your last question. I think this is the wrong thing to do. This is better.

       01  FILE-TABLE.
          05  FILE-TABLE-ROW 
              OCCURS 10 TIMES 
              INDEXED BY I.
              10  FILE-TABLE-COL 
                  OCCURS 10 TIMES 
                  INDEXED BY J.
                  15  FILE-TABLE-COL           PIC X(1).
    

    Just a point I've not mentioned before, since you may be naming to aid you as a beginner, you don't need to name fields if you are not going to use them.

       01  FILE-TABLE.
          05  FILE-TABLE-ROW 
              OCCURS 10 TIMES 
              INDEXED BY I.
              10  FILLER 
                  OCCURS 10 TIMES 
                  INDEXED BY J.
                  15  FILE-TABLE-COL           PIC X(1).
    

    Note that since the 1985 Standard, the word FILLER can be written in invisible ink:

        05  FILLER                             PIC X(20).
        05                                     PIC X(20).
    

    The blank in the name is an implicit FILLER. Note also that 05 can be written as 5, as can every level-number which starts with zero.

    READ FILE, WRITE RECORD as the old saying goes. A "Record" in this context is an 01-level beneath an DF. You are attempting to write something which is a subordinate part of a record, which won't work. Seems to have confused the compiler.

    I see no FD but presume it is there. Put your table into WORKING-STORAGE (or LOCAL-STORAGE). Define a 10-byte record under your FD, MOVE FILE-TABLE-ROW to that newly-defined record, or use WRITE FROM FILE-TABLE-ROW.

    You can't write part of a record (an 01-level) in the FILE SECTION. You can use MOVE, or WRITE ... FROM..., to access data at a non-01-level, and get that data into your 01-level to allow a WRITE.

    WORKING-STORAGE SECTION,
    01  some-thing PIC X.
    

    Then

    MOVE some-thing TO output-record
    WRITE output-record
    

    Or

    WRITE output-record FROM some-thing
    

    There are two different ways to write WRITE that interest you here:

    WRITE record-name
    WRITE record-name FROM somewhere-else
    

    For the first, you fully-define your output under your FD, put values in the fields you need, and then WRITE the record.

    For the second, you only need a minimal definition under the FD (enough to define a length for the record, which can be variable, you'll probably come to that later) and you put values in all the fields you need, subordinate to another group item if necessary. The definition under the FD can be complete, it is just that it doesn't have to be.

    That data can be from anywhere in the DATA DIVISION. It could even be from somewhere else in the FILE SECTION (WRITE output-record FROM input-record is something you will see).

    The FROM on WRITE, like the INTO on READ, is an implicit MOVE. MOVE formatted-data TO output-record and WRITE output-record, is what the WRITE ... FROM ... says.