Есть ли способ параметризации функций в COBOL?

Я кодирую процедуры, такие как:

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.

чтобы прочитать несколько файлов, и мне было интересно, есть ли способ кодировать подпрограмму, которая может прочитать имя файла из переменной, поэтому мне не нужно кодировать одно и то же для каждого файла. Спасибо!

5 ответов

Решение

Как было сказано выше, одним из решений является использование нескольких программ или вложенных программ, для которых я включил приведенный ниже пример, который является решением 1.

Другое решение - это классы COBOL, которые могут вам не нравиться, но они мне нравятся, поэтому я привел пример, который является решением 2.

Решение 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.

Решение 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.

Я понимаю, что это старая ветка, но, надеюсь, кому-то она может пригодиться в будущем: компилятор IBM Enterprise COBOL для z/OS 6.4 поддерживает определяемые пользователем функции (выпущен в мае 2022 г.). Пользовательские функции могут быть полезной альтернативой другим предложениям для внутренних программ. В отличие от вызовов программ, существуют проверки времени компиляции для параметров вызовов пользовательских функций. Кроме того, вы можете вызывать функцию во многих местах, где вы не можете вызвать программу, например, внутри выражения.

Вот пример, основанный на передаче имени файла в функцию. Возможно, это удастся объединить с приведенным выше предложением PUTENV().

         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.

Дополнительные примеры можно найти в Руководстве по программированию, глава 32 Использование пользовательских функций. https://www.ibm.com/support/pages/enterprise-cobol-zos-documentation-library#Table642

Может пока не быть "в дикой природе" с поддержкой компилятора, но текущий стандарт ISO Draft 20xx включает FUNCTION-ID вместо PROGRAM-ID. Он добавляет парадигму вычисления вызова функции, дружественную к параметру, в COBOL.

Может не помочь сегодня, но, возможно, в ближайшем будущем. Если я не ошибаюсь, пользовательские функции на самом деле взяты из спецификации COBOL 2002, но кажется, что поставщики компиляторов испытывают трудности с поддержкой этой функции.

Поддержка FUNCTION-ID находится в закрытых испытаниях для OpenCOBOL 2.0, но сроки выхода версии 2.0 не определены, и может быть еще год или более до того, как он будет обнародован.

Правильный способ параметризации подпрограмм Cobol - через вложенную подпрограмму.

Вы можете делать то, что вы хотите, но это зависит от вашего компилятора и среды, вы можете передать файл, или имя файла, или DDname.

На какой ты платформе?

Изменить: В z/OS вы можете изменить то, на что указывает FILE-A во время выполнения, используя putenv(), чтобы настроить имя набора данных, связанное с DDNAME, которое использует FILE-A.

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

Вам также понадобится параграф OPEN-A и CLOSE-A между переключениями файлов.

Он не совсем передает параметры в оператор read, но позволяет повторно использовать операторы OPEN/READ/WRITE/CLOSE для разных файлов. Но только поочередно.

В VS COBOL II был способ передать FD подпрограмме, которая выглядела бы примерно так:

CALL MYREADPGM с помощью FILE-A CALL MYREADPGM с помощью FILE-B

Это возможно с Enterprise Cobol, но IIRC VisualAge не поддерживает это.

Вы можете создать файл данных с именами файлов, обработать каждый файл как отдельную запись, а затем прочитать каждый файл. В "SELECT ...ASSIGN" вам нужно будет использовать переменную рабочего хранилища для имени файла и переместить в него значение из "файла имен файлов".

Поскольку вы используете VisualAge, я предполагаю, что в UNIX вы также можете запускать программу из оболочки (sh,ksh) с именем файла в качестве параметра и многократно запускать программу из оболочки для каждого имени файла.

Другие вопросы по тегам