开发者

Is there a way to parameterize functions in COBOL?

开发者 https://www.devze.com 2023-02-07 15:57 出处:网络
I\'m coding routines like: READ-A. READ FILE-A AT END MOVE 1 TO EOF-A NOT AT END ADD 1 TO CN-READ-A END-READ.

I'm coding routines like:

READ-A.
       READ FILE-A
           AT END
             MOVE 1 TO EOF-A
           NOT AT END 
             ADD 1 TO CN-READ-A
       END-READ.
F-READ-A. EXIT.

to read several files and I was wondering if there's a way to code a routine that is able to read the filename from a variable so I don't have 开发者_JAVA技巧to code the same thing for each file. Thanks!


One solution as said above is to use multiple programs or nested program, for which I have included an example below, which is solution 1.

Another solution is to COBOL classes, which might not be to your liking but I like them, so I've included an example, which is solution 2.

Solution 1:

   program-id. TestProgram.
   working-storage section.
   01 file-name        pic x(128).
   01 file-lines       pic 9(9).
   procedure division.
       move 0 to file-lines
       move "d:\rts_win32.txt" to file-name
       call "program1" using file-name file-lines
       display file-lines
       stop run
   end program TestProgram.
   program-id. Program1.

   file-control.
       select file-a assign to myfile
           organization is line sequential.

   data division.
   fd file-a.
   01 file-a-line      pic x(80).

   working-storage section.
   01 EOF-A            pic 9 value 0.
   linkage section.
   01 lk-filename      pic x(128).
   01 CN-READ-A        pic 9(9).
   procedure division using lk-filename
                            CN-READ-A.

       move lk-filename to myfile
       open input file-a

       perform READ-A until EOF-A equals 1
       close file-a
       goback.

       READ-A.
       READ FILE-A
           AT END
             MOVE 1 TO EOF-A
           NOT AT END 
             ADD 1 TO CN-READ-A
       END-READ.
       F-READ-A. 
       EXIT.


   end program Program1.

Solution 2

  program-id. TestProgram.:
   working-storage section.
   01 file-counter type FileLineCounter.
   procedure division.
       set file-counter to new type FileLineCounter("d:\rts_win32.txt")
       display file-counter::LineCount
       stop run
   end program TestProgram.
   class-id FileLineCounter.
   file-control.
       select file-a assign to myfile
           organization is line sequential.

   data division.
   fd file-a.
   01 file-a-line      pic x(80).

   working-storage section.

   01 cn-read-a binary-long property as "LineCount".

   method-id New.
   01 EOF-A            pic 9 value 0.
   procedure division using by value filename as string.

       set myfile to filename
       open input file-a

       perform READ-A until EOF-A equals 1
       close file-a
       goback.

       READ-A.
       READ FILE-A
           AT END
             MOVE 1 TO EOF-A
           NOT AT END 
             ADD 1 TO CN-READ-A
       END-READ.
       F-READ-A. 
       EXIT.

   end method.

   end class.


May not be "in the wild" yet with compiler support, but the current ISO Draft 20xx standard includes FUNCTION-ID in place of PROGRAM-ID. It adds a parameter friendly function call computing paradigm to COBOL.

Might not help today, but maybe in the near future. If I'm not mistaken, User Defined Functions are actually from the COBOL 2002 spec, but it seems compiler vendors are hit or miss on support for the feature.

FUNCTION-ID support is in closed trials for OpenCOBOL 2.0, but the timeline for the 2.0 release is undetermined and could be another year or more before it's made public.


The proper Cobol way to parameterize routines is via the nested subprogram.

You can do what you want, but it is dependant upon your compiler and environment, you can pass a file, or a file name, or a DDname.

What platform are you on?

Edit: On z/OS, you can change what FILE-A points to at runtime using putenv() to adjust the dataset name associated with the DDNAME that FILE-A uses.

See: http://ibmmainframes.com/post-57281.html http://cicswiki.org/cicswiki1/index.php?title=How_do_I_allocate_a_file_dynamically_using_COBOL%3F

You will need a OPEN-A and CLOSE-A paragraph as well between switching files.

It isn't exactly passing parameters to your read statement, but it lets you reuse your OPEN/READ/WRITE/CLOSE statements for different files. But only serially.

There was a way, under VS COBOL II, where you could pass an FD to a subprogram, that would look something like:

CALL MYREADPGM USING FILE-A CALL MYREADPGM USING FILE-B

This possible with Enterprise Cobol but IIRC VisualAge does not support that.


I realize this is an old thread, but hopefully someone might find this useful in the future: IBM's Enterprise COBOL on z/OS 6.4 compiler supports user-defined functions (released May 2022). User-defined functions could be a useful alternative to the other suggestion for internal programs. In contrast to program calls, there are compile time checks for parameters to user-defined function invocations. Also, you can invoke the function in a lot of places where you couldn't call a program, like within a n expression.

Here's an example based on passing a file name to a function. It might be possible to combine this with the PUTENV() suggestion above.

   IDENTIFICATION DIVISION.
     FUNCTION-ID. READ-FILE.
   DATA DIVISION.
    LINKAGE SECTION.
     1 FILE-NAME PIC X(50).
     1 RET PIC 9(9).
   PROCEDURE DIVISION USING FILE-NAME RETURNING RET.
  * DO STUFF WITH FILE-NAME
  * ...
       GOBACK
       .
   END FUNCTION READ-FILE.
   IDENTIFICATION DIVISION.
     PROGRAM-ID. MAINPROG.
   DATA DIVISION.
    WORKING-STORAGE SECTION.
     1 READ-RESULT PIC 9(9).
   PROCEDURE DIVISION.
       COMPUTE READ-RESULT = FUNCTION READ-FILE('MYINPUTFILE')
       GOBACK
       .
   END PROGRAM MAINPROG.

More examples can be found in the Programming Guide Chapter 32 Using user-defined functions. https://www.ibm.com/support/pages/enterprise-cobol-zos-documentation-library#Table642


You could create a data file of filenames, treat each one as an individual record, and then read each file. In the "SELECT ...ASSIGN" you would need to use a working-storage variable for the filename and move the value from the 'file of filenames' into it.

As you are using VisualAge, I assume in UNIX, you might also be able to run the program from the shell (sh,ksh), with the filename as a parameter, and repeatedly run the program from the shell for each file name.

0

精彩评论

暂无评论...
验证码 换一张
取 消