Page 2 of 2

Re: COBOL File Processing Position wise

PostPosted: Sat Jan 05, 2013 10:31 pm
by Akatsukami
IBM MINAKSHI wrote:For Do while logic.. do we need to put array replacement in COBOL?



By no means.

As the input data are very simple, the correspondence between the PL/I structure and the COBOL record is also very simple. I wrote:

Code: Select all
      dcl 1 input_record                 unal,                           
           2 source                     char (3),                       
           2 account_number             char (15),                       
           2 id                         char (8),                       
           2 ccode                      char (3),                       
           2 message (10)               char (30); 



In COBOL, this becomes:

            01  INPUT_RECORD.
                02  SOURCE                    PIC X(3).
                02  ACCOUNT_NUMBER            PIC X(15).
                02  ID                        PIC X(8).
                02  CCODE                     PIC X(3).
                02  MESSAGE OCCURS 10 TIMES   PIC X(30).


Note that the unaligned (unal) keyword is applied to the PL/I structure, eliminating the insertion of “slack” bytes by the compiler to force subordinate variables to start on “natural” boundaries. There is no direct COBOL equivalent, although the PL/I keyword aligned does have the COBOL equivalent of SYNCHRONIZED. Note also that, as the individual fields are all character/PIC X, they will all start on byte boundaries; however, I declare all my structures unaligned from habit.

Now, PL/I is a block-structured language, unlike COBOL (although programmers usually find that many of the block-structure features of PL/I are more trouble than they are worth). The PL/I program is simply

      read file (tulin) into (input_record);                         
                                                                   
     do while (¬eof_tulin);             
     [everything else]
     end;



However, COBOL’s own structure makes this fairly easy to emulate; the corresponding code is:


            PROCEDURE DIVISION.
            0000-MAIN.
                READ INPUT-FILE INTO INPUT-RECORD
                     AT END MOVE 'Y' TO EOF-INPUT-FILE.
                PERFORM 1000-PROCESS UNTIL EOF-INPUT-FILE.
                GOBACK.
            1000-PROCESS.
                [everything else]


Note that COBOL PERFORM…UNTIL is not the equivalent of do until in PL/I and other languages. The default is for the condition to be tested before the PERFORM, thus making it the equivalent of do while (you can force the test to be done after the PERFORM, thus making it the equivalent of do until.

Ah, but what, you ask, about the array handling? (In COBOL, the proper terminology is “internal table”). In PL/I, I use an iterated do while;

     do i = 2 to 5 while (input_record.message(i)¬=' ');         
         output_detail.message      = input_record.message (i);     
         call do_output;                                           
       end;           


In COBOL, you would use a PERFORM VARYING:

            1000-PROCESS.
                [other stuff]
                PERFORM 1100-MESSAGE-LOOP
                    VARYING I FROM 2 BY 1
                    UNTIL I = 5 OR MESSAGE (I) OF INPUT-RECORD IS EQUAL TO SPACES.
                READ INPUT-FILE INTO INPUT-RECORD
                     AT END MOVE 'Y' TO EOF-INPUT-FILE.
            1100-MESSAGE-LOOP.
                MOVE MESSAGE (I) OF INPUT-RECORD TO MESSAGE OF OUTPUT-DETAIL.
                PERFORM 2000-OUTPUT.

Re: COBOL File Processing Position wise

PostPosted: Sun Jan 06, 2013 5:00 am
by BillyBoyo
Well, I baked the dog along the way, but not to a fatal extent :-)

I have, eventually, updated the posts to replace the "READ FILE" references...

Re: COBOL File Processing Position wise

PostPosted: Sun Jan 06, 2013 9:49 am
by IBM MINAKSHI
Thanks .. i will try this now..

Re: COBOL File Processing Position wise

PostPosted: Sun Jan 06, 2013 10:14 am
by IBM MINAKSHI
Thanks a lot Akatsukami .

After your initial guidence i tried converting code to COBOL. i converted but used 4 IF blocks to check if message2,3,4,5, is not equal to spaces.. them populated related output fields and write records.
PERFORM 100-MOVE-WRITE-PARA UNTIL EOF-INPUT-FILE
100-MOVE-WRITE-PARA
     MOVE INPUT-SOURCE           TO OUTPUT-SOURCE
     MOVE INPUT-ACCOUNT-NUM      TO OUTPUT-ACCOUNT-NUM
     MOVE INPUT-ID               TO OUTPUT-ID
     MOVE INPUT-CCODE            TO OUTPUT-CCODE
     MOVE INPUT-MESSAGE1         TO OUTPUT-MESSAGE
     WRITE OUTPUT-FILE           FROM OUTPUT-RECORD

     IF INPUT-MESSAGE2 NOT = SPACES
        MOVE SPACES              TO     OUTPUT-SOURCE
                                        OUTPUT-ACCOUNT-NUM
                                        OUTPUT-ID
                                        OUTPUT-CCODE
        MOVE INPUT-MESSAGE2      TO     OUTPUT-MESSAGE
        WRITE OUTPUT-FILE        FROM   OUTPUT-RECORD

        IF INPUT-MESSAGE3 NOT = SPACES
           MOVE SPACES           TO     OUTPUT-SOURCE
                                     OUTPUT-ACCOUNT-NUM
                                        OUTPUT-ID
                                        OUTPUT-CCODE
           MOVE INPUT-MESSAGE3   TO     OUTPUT-MESSAGE
           WRITE OUTPUT-FILE     FROM   OUTPUT-RECORD
and so on...


Now i got that i should put 10 error message in an internal table (array) then process input records.
One question as population of data in case of 1st error message and other (2,3,4,5) are different.. like for first message i have to move value of source,a/c no,id,ccode and error-message while in case of other messages i have to move spaces to source,a/c no,id,ccode and actual message to output message then how should i handle this... shall i move first message, write record then apply PERFORM loop logic?

PERFORM 100-MOVE-WRITE-PARA UNTIL EOF-INPUT-FILE
100-MOVE-WRITE-PARA
     MOVE INPUT-SOURCE           TO OUTPUT-SOURCE
     MOVE INPUT-ACCOUNT-NUM      TO OUTPUT-ACCOUNT-NUM
     MOVE INPUT-ID               TO OUTPUT-ID
     MOVE INPUT-CCODE            TO OUTPUT-CCODE
     MOVE INPUT-MESSAGE(1)        TO OUTPUT-MESSAGE
     WRITE OUTPUT-FILE           FROM OUTPUT-RECORD
     
then perform look as you told varying I = 2 by 1.. but in this case how will i handle table index...

Re: COBOL File Processing Position wise

PostPosted: Sun Jan 06, 2013 8:20 pm
by Akatsukami
IBM MINAKSHI wrote:One question as population of data in case of 1st error message and other (2,3,4,5) are different.. like for first message i have to move value of source,a/c no,id,ccode and error-message while in case of other messages i have to move spaces to source,a/c no,id,ccode and actual message to output message then how should i handle this... shall i move first message, write record then apply PERFORM loop logic?

PERFORM 100-MOVE-WRITE-PARA UNTIL EOF-INPUT-FILE
100-MOVE-WRITE-PARA
     MOVE INPUT-SOURCE           TO OUTPUT-SOURCE
     MOVE INPUT-ACCOUNT-NUM      TO OUTPUT-ACCOUNT-NUM
     MOVE INPUT-ID               TO OUTPUT-ID
     MOVE INPUT-CCODE            TO OUTPUT-CCODE
     MOVE INPUT-MESSAGE(1)        TO OUTPUT-MESSAGE
     WRITE OUTPUT-FILE           FROM OUTPUT-RECORD
     

Yes; note that if you move spaces to the output fields before executing the PERFORM VARYING, you need only code it once. Recall that I wrote:
 do while (¬eof_tulin);                                         
   output_detail.source         = input_record.source;         
   output_detail.account_number = input_record.account_number;
   output_detail.id             = input_record.id;             
   output_detail.ccode          = input_record.ccode;           
   output_detail.message        = input_record.message (1);     
   call do_output;                                             
   output_detail.source         = ' ';                         
   output_detail.account_number = ' ';                         
   output_detail.id             = ' ';                         
   output_detail.ccode          = ' ';                         
                                                               
   do i = 2 to 5 while (input_record.message(i)¬=' ');         
     output_detail.message      = input_record.message (i);     
     call do_output;                                           
   end;                                                         
                                                               
   read file (tulin) into (input_record);     
 end;                                     

The COBOL equivalent would be:
            MOVE SOURCE OF INPUT-RECORD         TO
                SOURCE OF OUTPUT-DETAIL.
            MOVE ACCOUNT_NUMBER OF INPUT-RECORD TO
                ACCOUNT_NUMBER OF OUTPUT-DETAIL.
            MOVE ID OF INPUT-RECORD TO
                ID OF OUTPUT-DETAIL.
            MOVE CCODE OF INPUT-RECORD TO
                CCODE OF OUTPUT-DETAIL.
            MOVE MESSAGE (1) OF INPUT-RECORD TO
                MESSAGE OF OUTPUT-DETAIL.
            PERFORM 2000-OUTPUT.
            MOVE SPACES TO SOURCE OF OUTPUT-DETAIL.
            MOVE SPACES TO ACCOUNT_NUMBER OF OUTPUT-DETAIL.
            MOVE SPACES TO ID OF OUTPUT-DETAIL.
            MOVE SPACES TO CCODE OF OUTPUT-DETAIL.
            PERFORM 1100-MESSAGE-LOOP
                VARYING I FROM 2 BY 1
                UNTIL I = 5 OR MESSAGE (I) OF INPUT_RECORD = SPACES.
            READ INPUT-FILE INTO INPUT-BUFFER
                AT END MOVE TO EOF-INPUT-FILE.
        1100-MESSAGE-LOOP.
            MOVE MESSAGE (I) OF INPUT-RECORD TO
                MESSAGE OF OUTPUT-DETAIL.
            PERFORM 2000-OUTPUT.

Thus all fields in OUTPUT-DETAIL except MESSAGE are set to spaces before the loop; as they are not targets within the loop, they need never be reset.

Note also that I do not bother moving spaces to MESSAGE OF OUTPUT-DETAIL, since I know that OUTPUT-DETAIL will never be written unless MESSAGE has first been overlaid with an instance of MESSAGE OF INPUT-RECORD.
then perform look as you told varying I = 2 by 1.. but in this case how will i handle table index...

Well, you may not have to.

COBOL has the concept of an index; it is not defined as a separate variable but in the INDEXED BY clause on the table. However, a COBOL table need not have an index defined; any variable that resolves to an integer (or a literal integer) can be used as a subscript. I believe indexing is more efficient (although on a Series z box that is probably not noticeable save for a loop from 1 to 1,000,000,000) and permits the use of certain table operations that subscripting does not. However, I note again that I haven't written COBOL since 1995; someone like Mr. Boyo would be a better adviser in this case.

Other languages do not explicitly have this difference (although in, say, PL/I, a loop will be measurably more efficient if the control variable is FIXED BIN (31) rather than FIXED BIN (15), FIXED DEC, or, Kamisama forbid, PICTURE), so I have tended to scant indexes. You may define I as either an index or a subscript; for the purposes of this program, they are handled the same way.

Re: COBOL File Processing Position wise

PostPosted: Sun Jan 06, 2013 10:59 pm
by IBM MINAKSHI
Thanks Akatsukami Sir .

I learned a lot from you. Now i will try executing this program and create a report as per my expectations..
Thanks again..

Re: COBOL File Processing Position wise

PostPosted: Mon Jan 07, 2013 3:16 pm
by BillyBoyo
Well, at the moment I'm just watching, as this is much clearer with one set of ideas consistently and serially applied, rather than more of a mish-mash which becomes difficult to follow.

The main comments I'd make later are mostly to do with the "more modern" Cobol we have these days compared to when you last used it. Programming logic itself ages well.