Manipulate the COBOL Data Structure

I would like information to manage tables. I ran into a small problem with a piece of cobol code, as shown below:

01 TABLE-1. 05 STRUCT-1 OCCURS 25 TIMES. 10 VALUE-1 PIC AAA. 10 VALUE-2 PIC 9(5)V999. 05 NUMBER-OF-OCCURS PIC 99. 

How do you update the values? (update VALUE-2 when you know VALUE-1)
How to find the value and add a new one? Many thanks!

+4
source share
3 answers

How to find the value / How to update the value

First you need to find the record (row) that you want to update. This is usually done by searching the table for the given key value. COBOL provides several ways to do this. I recommend starting with a review of COBOL SEARCH expression. If STRUCT-1 records STRUCT-1 sorted, you can use SEARCH ALL , otherwise you must use SEARCH or just code your own search loop. To use any of these methods, you will need to declare another variable somewhere in your program for use as an index (offset) in table STRUCT-1 . COBOL provides an INDEXED BY on OCCURS to declare an index specific to a given table. (see OCCURS )

Once you set the index to STRUCT-1 to indicate the row to be updated, you simply MOVE value for the corresponding variables inside that row, for example

MOVING 123.456 TO VALUE-2 (IDX-1)

where IDX-1 is the index mentioned above. Please note that you can use either an integer or an index variable to indicate the line number to update, you are not limited to using a variable of type INDEX. However, it is usually more efficient to use INDEX variables compared to other types of variables, especially when working with multidimensional tables, where the program makes many references to the table.

How to add a new line

First make sure that STRUCT-1 contains exactly 25 rows. COBOL does not have a mechanism to dynamically increase or decrease this number (I heard that it will be possible in the next ISO standard COBOL - but do not hold your breath while waiting for it). Technically, all 25 lines are available at any time. However, the general convention is to β€œgrow” so that the table is empty until the sequence is complete, one row at a time. To use this convention, you need to assign a variable to track the last line number used (remember to initialize this variable to zero when the program starts). In your example, it looks like the NUMBER-OF-OCCURS does the job (I didn’t mention this, but you need this variable to relate the SEARCH discussed above).

To add a row, simply increase NUMBER-OF-OCCURS by 1. Be careful not to exceed the size of the table. example code could be:

 IF NUMBER-OF-OCCURS < (LENGTH OF TABLE-1 / LENGTH OF STRUCT-1 (1)) ADD +1 TO NUMBER-OF-OCCURS ELSE table is full, preform some error/recovery routine END-IF 

The above code avoids explicitly using the number of events in TABLE-1 , which in turn can save a number of maintenance problems when / if the number of OCCURS is ever changed.

See note below: there are very large Woops - you caught him!

Now back to the search problem. The following code example illustrates how you can continue:

STATEMENT OF WORK STORAGE:

  01 FOUND-IND PIC X(1). 88 FOUND-YES VALUE 'Y'. 88 FOUND-NO VALUE 'N'. 77 MAX-IDX USAGE IS INDEX. 01 TABLE-1. 05 STRUCT-1 OCCURS 25 TIMES INDEXED BY IDX-1. 10 VALUE-1 PIC AAA. 10 VALUE-2 PIC 9(5)V999. 05 NUMBER-OF-OCCURS PIC 99. 

What has been added:

  • FOUND-IND used to indicate whether a found string is found. Levels 88 provide specific values ​​for installation / testing.
  • MAX-IDX used to set the upper limit of the search restriction. You can use NUMBER-OF-OCCURS in the top grades test, but this will force a converson data type for each test that is not very efficient.
  • IDX-1 used as the index (offset) in table STRUCT-1 .

Personally, I would declare NUMBER-OF-OCCURS as PIC S9(4) BINARY , but what you have will work.

Assuming STRUCT-1 not sorted and NUMBER-OF-OCCURS represents the current number of active rows in STRUCT-1 this is an example of how you could encode SEARCH when looking for the value "ABC":

 SET FOUND-NO TO TRUE IF NUMBER-OF-OCCURS > ZERO SET IDX-1 TO 1 SET MAX-IDX TO NUMBER-OF-OCCURS SEARCH STRUCT-1 WHEN IDX-1 > MAX-IDX CONTINUE WHEN VALUE-1 (IDX-1) = 'ABC' SET FOUND-YES TO TRUE END-SEARCH END-IF IF FOUND-YES row found, use IDX-1 to reference the row containing 'ABC' ELSE row not found, IDX-1 does not contain a valid index END-IF 

How it works:

  • Start by assuming the row is not in the table by setting the FOUND-NO parameter to true.
  • The first IF guarantees that before starting the search there will be at least 1 active row in STRUCT-1 (this means that the INDEX index is zero, so you need to protect yourself from this).
  • SEARCH ends when the first SEARCH WHEN clause is executed. That's why the verb "do nothing" CONTINUE can be used when the string search ends. Another termination condition (finding the value you are looking for) is the only place you can set FOUND-YES .
  • When SEARCH completes, check for success or failure, proceed accordingly.

Some exercises for you:

  • Why didn't I need to encode the AT END clause in the SEARCH statement?
  • Why didn't I need to encode the VARYING clause in the SEARCH statement?
  • Why did I code the WHERE clauses in the order I did it?

Hope this helps you get started on the right track.

Edit

In response to your question in the comments: Is it possible to use NUMBER-OF-OCCURS as an index for searching. The answer is yes, but you need to implement several different rules. When using NUMBER-OF-OCCURS as an index, you can no longer use it to track how many rows currently contain valid data. This means that you need a different mechanism for identifying unused strings in STRUCT-1 . This can be accomplished by initializing unused rows with a discarded value (such as LOW-VALUE ) that you will never want to insert into the table. SEARCH becomes:

 SET FOUND-NO TO TRUE MOVE 1 TO NUMBER-OF-OCCURS SEARCH STRUCT-1 VARYING NUMBER-OF-OCCURS WHEN VALUE-1 (NUMBER-OF-OCCURS) = 'ABC' SET FOUND-YES TO TRUE END-SEARCH 

The above will search for each row in STRUCT-1 if the value you are looking for (i.e. ABC ) is not in the table. As an optimization, you can add a second WHEN clause to abort the search by detecting a released value:

 WHEN VALUE-1 (NUMBER-OF-OCCURS) = LOW-VALUE CONTINUE 

The above LOW-VALUE assumptions were used to identify unused strings. You can also refuse IDX-1 and MAX-IDX from your working storage, as they do not need this solution.

Using NUMBER-OF-OCCURS as an index also means that you must change the way you search for an empty string to insert a new value. The easiest way to do this is to do a table lookup using the LOW-VALUE code above instead of 'ABC' . If FOUND-YES set at the end of the search, then NUMBER-OF-OCCURS is the index of the first unused row. If FOUND-NO set, then the table is already populated.

The above code is much simpler than I originally suggested. So why did I give you a more complicated solution? A more complex solution is more efficient because it makes much less internal offset calculations and data type conversions as it passes through the table. It also avoids doing extra SEARCH to find the next unused line. These performance indicators may not cause concern in your application, but if the tables are large and often available, you should be aware of the performance aspect of search tables and forced data type conversions (for example, the cost of converting a PIC 99 field to an index link).

Note:

My initial example for calculating whether a table was populated using a special register LENGTH OF will work in this example, but has a really bad built-in guess! LENGTH OF TABLE-1 includes not only the STRUCT-1 table, but also NUMBER-OF-OCCURS . The length of NUMBER-OF-OCCURS less than one> STRUCT-1 , so that everything works fine due to truncation of the result into an integer value. This is a very good example of code working correctly for the wrong reason! To make the correct calculation, you will have to configure the working storage for something like:

 01 TABLE-1. 05 STRUCT-TABLE. 10 STRUCT-1 OCCURS 25 TIMES. 20 VALUE-1 PIC AAA. 20 VALUE-2 PIC 9(5)V999. 05 NUMBER-OF-OCCURS PIC 99. 

and the calculation of the boundaries will be as follows:

 IF NUMBER-OF-OCCURS < (LENGTH OF STRUCT-TABLE / LENGTH OF STRUCT-1 (1)) ADD +1 TO NUMBER-OF-OCCURS ELSE table is full, preform some error/recovery routine END-IF 

Or you can simply move NUMBER-OF-OCCURS from the definition of the TABLE-1 record.

+8
source

To fill in and change the data in the tables in the working storage section, you need to use the index / index, which you can define in the working storage, and then write the code processing in the procedure section. In this case, you can use the execute..unit command.

+1
source

Wow ... that was a long answer. Suppose with number II:

Perform variable II from 1 to 1

before II> NUMBER-OF-OCCURS

If value-1 (II) = known-value-1

  Move New-Value-2 to Value-2 (II) 

End if

End-perform

+1
source

Source: https://habr.com/ru/post/1303458/


All Articles