Как мне исправить эту логическую ошибку при печати выходных данных в катушке системного вывода из программы COBOL?

#cobol #mainframe #jcl #gnucobol #cobol85

#cobol #мэйнфрейм #jcl #gnucobol #cobol85

Вопрос:

Это код cobol

      *-----------------------
       IDENTIFICATION DIVISION.
      *-----------------------
       PROGRAM-ID.    TOPACCTS
       AUTHOR.        Otto B. Boolean.
      *--------------------
       ENVIRONMENT DIVISION.
      *--------------------
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT PRINT-LINE ASSIGN TO PRTLINE.
           SELECT CUST-RECS   ASSIGN TO CUSTRECS.
      *-------------
       DATA DIVISION.
      *-------------
       FILE SECTION.
       FD  PRINT-LINE RECORDING MODE F.
       01  PRINT-REC.
           05  FILLER         PIC X(02) VALUE SPACES.
           05  LAST-NAME-O    PIC X(25).
           05  FILLER         PIC X(02) VALUE SPACES.
           05  ACCT-BALANCE-O PIC X(18).
           05  FILLER         PIC X(33) VALUE SPACES.
      *
       FD  CUST-RECS RECORDING MODE F.
       01  CUSTOMER-REC.
           05  LAST-NAME          PIC X(25).
           05  FILLER             PIC X(10) VALUE SPACES.
           05  FIRST-NAME         PIC X(15).
           05  FILLER             PIC X(10) VALUE SPACES.
           05  ACCT-BALANCE       PIC X(18).
           05  FILLER             PIC X(02) VALUE SPACES.


      *
       WORKING-STORAGE SECTION.
       01  Filler.
           05 LASTREC          PIC X VALUE SPACE.
           05 TOTL             PIC 9(2) VALUE ZEROS.
           05 SUB1             PIC 9(2) VALUE 01.
           05 S                PIC X(12) VALUE "8,500,000.00".

      *
         01 OVERLIMIT.
           03 FILLER OCCURS 20 TIMES.
               05  OL-ACCT-NO            PIC X(8).
               05  OL-ACCT-LIMIT         PIC S9(7)V99 COMP-3.
               05  OL-ACCT-BALANCE       PIC S9(7)V99 COMP-3.
               05  OL-LASTNAME           PIC X(20).
               05  OL-FIRSTNAME          PIC X(15).
      *
       01  HEADER-1.
           05  FILLER         PIC X(20) 
                     VALUE 'Financial Report for'.
           05  FILLER         PIC X(01) VALUE SPACES.
           05  FILLER         PIC X(14) 
                     VALUE "Account holder".
           05  FILLER         PIC X(45) VALUE SPACES.
      *
       01  HEADER-2.
           05  FILLER         PIC X(05) VALUE 'Year '.
           05  HDR-YR         PIC 9(04).
           05  FILLER         PIC X(02) VALUE SPACES.
           05  FILLER         PIC X(06) VALUE 'Month '.
           05  HDR-MO         PIC X(02).
           05  FILLER         PIC X(02) VALUE SPACES.
           05  FILLER         PIC X(04) VALUE 'Day '.
           05  HDR-DAY        PIC X(02).
           05  FILLER         PIC X(56) VALUE SPACES.
      *
       01  HEADER-3.
           05  FILLER         PIC X(08) VALUE 'No.'. 
           05  FILLER         PIC X(02) VALUE SPACES.
           05  FILLER         PIC X(10) VALUE 'Cust Name '.
           05  FILLER         PIC X(15) VALUE SPACES.
           05  FILLER         PIC X(08) VALUE 'Balance '.
           05  FILLER         PIC X(40) VALUE SPACES.
      *
       01  HEADER-4.
           05  FILLER         PIC X(08) VALUE '--------'.
           05  FILLER         PIC X(02) VALUE SPACES.
           05  FILLER         PIC X(10) VALUE '----------'.
           05  FILLER         PIC X(15) VALUE SPACES.
           05  FILLER         PIC X(10) VALUE '----------'.
           05  FILLER         PIC X(02) VALUE SPACES.
           05  FILLER         PIC X(13) VALUE '-------------'.
           05  FILLER         PIC X(40) VALUE SPACES.
      *
       01 WS-CURRENT-DATE-DATA.
           05  WS-CURRENT-DATE.
               10  WS-CURRENT-YEAR         PIC 9(04).
               10  WS-CURRENT-MONTH        PIC 9(02).
               10  WS-CURRENT-DAY          PIC 9(02).
           05  WS-CURRENT-TIME.
               10  WS-CURRENT-HOURS        PIC 9(02).
               10  WS-CURRENT-MINUTE       PIC 9(02).
               10  WS-CURRENT-SECOND       PIC 9(02).
               10  WS-CURRENT-MILLISECONDS PIC 9(02).
      *
      *------------------
       PROCEDURE DIVISION.
      *------------------
       OPEN-FILES.
           OPEN INPUT  CUST-RECS.
           OPEN OUTPUT PRINT-LINE.
           DISPLAY HEADER-1.
           PERFORM WRITE-HEADERS.
           DISPLAY 'PREPARED ON ' HDR-DAY '.' HDR-MO '.' HDR-YR.
           DISPLAY '# OF RECORDS: ' TOTL.
           DISPLAY '==========================================='.
           PERFORM READ-NEXT-RECORD.
           
           
      *
       WRITE-HEADERS.
           MOVE FUNCTION CURRENT-DATE TO WS-CURRENT-DATE-DATA.
           MOVE WS-CURRENT-YEAR  TO HDR-YR.
           MOVE WS-CURRENT-MONTH TO HDR-MO.
           MOVE WS-CURRENT-DAY   TO HDR-DAY.
           MOVE SPACES TO PRINT-REC.
           WRITE PRINT-REC AFTER ADVANCING 1 LINES.
           MOVE SPACES TO PRINT-REC.
      *
      *
       READ-NEXT-RECORD.
           PERFORM READ-RECORD
            PERFORM UNTIL LASTREC = 'Y'
            PERFORM THE-RICH
            PERFORM WRITE-RECORD
            PERFORM READ-RECORD
            END-PERFORM.
           EXIT.
      *

      *
       READ-RECORD.
           READ CUST-RECS          
           AT END MOVE 'Y' TO LASTREC
           END-READ.
           EXIT.
      *
       THE-RICH.
           IF FUNCTION NUMVAL-C(S) < FUNCTION NUMVAL-C(ACCT-BALANCE)
            THEN
               DISPLAY LAST-NAME  ACCT-BALANCE
               MOVE ACCT-BALANCE TO ACCT-BALANCE-O
               MOVE LAST-NAME TO LAST-NAME-O
               ADD 1 TO SUB1
               MOVE SUB1 TO TOTL
            END-IF.
           EXIT.
 
      *
       WRITE-RECORD.
           MOVE ACCT-BALANCE TO  ACCT-BALANCE-O.
           MOVE LAST-NAME    TO  LAST-NAME-O.
      *    MOVE FIRST-NAME   TO  FIRST-NAME-O.
           WRITE PRINT-REC.
           EXIT.
      *
  

это вывод SYSOUT

  Financial Report for Account holder
 PREPARED ON 24.09.2020
 no OF RECORDS: 00
 ===========================================
 Maggie     Bignell        8,670,838.00
 Saw        Eckart         8,668,500.00
 Dede       Quickenden     8,667,260.00
 Allison    Oxshott        8,593,183.00
 Ambrose    Inch           8,557,403.00
 Leann      Lob            8,656,689.00
 Nevile     Roswarn        8,579,721.00
 Hedda      Littrell       8,598,965.00
 KonstantineMerner         8,557,306.00
 Heddie     Atwel          8,674,813.00
 Torie      Gimenez        8,662,345.00
 Lorraine   Van Hault      8,500,390.00
 Javier     Coltan         8,534,879.00
 Kissee     Kidston        8,650,707.00
 Benedikta  Spitell        8,589,633.00
 Niles      Garnson        8,649,886.00
 Alair      Sturrock       8,576,908.00
 Tandy      Pilgram        8,626,022.00
 Elfrida    Bamlet         8,540,474.00

 IGZ0020S A logic error occurred.  Neither FILE STATUS nor a declarative was specified for file CUSTRECS in program
          TOPACCTS at relative location X'414'.  The status code was 46.
          From compile unit TOPACCTS at entry point TOPACCTS at compile unit offset  00000414 at entry offset  00000414
          at address 1B800414.
  

Ответ №1:

Если вы используете мэйнфреймовый компилятор COBOL, вы переходите к документации и выбираете свою версию. Затем вы выполняете поиск по «ключу состояния файла» и просматриваете, что означает состояние файла 46.

Для файла, открытого в режиме ввода или ввода-вывода, была предпринята попытка последовательного чтения, и не было установлено ни одной допустимой следующей записи, поскольку:

  • Предыдущая инструкция READ была неудачной, но не вызвала условие завершения.
  • Предыдущий оператор чтения вызвал условие завершения.

Обратите внимание, что в вашем OPEN-FILES абзаце вы PERFORM READ-NEXT-RECORD , а затем переходите к остальной части вашего кода после того, как уже достигли конца файла.

Вероятно, вам нужен STOP RUN или GOBACK в конце вашего первого абзаца.

Редактировать относительно количества записей печати: на самом деле нет хорошего способа отобразить количество записей в верхней части отчета, потому что вы не знаете количество записей, пока не прочитаете весь входной файл, но вы печатаете строки отчета по ходу. Большая часть контрольных значений времени, таких как количество записей, редактируется DISPLAY (что по умолчанию передается в DD SYSOUT), а отчеты отправляются в другой DD, определенный в FILE-CONTROL (через a WRITE , точно так же, как то, что вы делаете).

Второе редактирование, касающееся количества записей печати: как указывает @GilbertLeBlanc, вы можете сохранять свои выходные строки в таблице до тех пор, пока не прочитаете все записи во входном файле. В таблице должно быть достаточно места для обработки всех выходных записей, и для этого существует несколько различных способов.

  • Ваша таблица может быть статически определена с достаточно большим OCCURS предложением для обработки того, что, как вам сказали, является разумным количеством записей. Раньше это было очень распространенным явлением, и был бы код для проверки, было ли превышено разумное число, и отменить, если это так.
  • В вашей таблице может по-разному встречаться UNBOUNDED фраза с учетом ее ограничений, а хранилище управляется с ALLOCATE помощью оператора и FREE инструкции.
  • Вы могли бы выполнить собственное распределение и перераспределение с помощью вызываемых файлов CEEGTST, CEEFRST и CEECZST.

Гилберт также указывает, что вы можете прочитать файл дважды, один раз, чтобы получить количество записей, затем закрыть и снова открыть для выполнения обычной обработки. Это будет работать до тех пор, пока вы не делаете что-то сложное с вашим JCL, например…

 //TOPACCTS EXEC PGM=TOPACCTS
//SYSOUT   DD  SYSOUT=*
//CUSTRECS DD  DISP=SHR,DSN=MY.INPUT.FILE01
//CUSTRECS DD  DISP=SHR,DSN=MY.INPUT.FILE02
//CUSTRECS DD  DISP=SHR,DSN=MY.INPUT.FILE03
//PRTLINE  DD  SYSOUT=*
//PRTLINE  DD  SYSOUT=*
//PRTLINE  DD  SYSOUT=*
  

… где каждый раз, когда вы закрываете и открываете CUST-RECS и PRINT-LINE, вы получаете следующий DD. Но это более сложная тема JCL, с которой вы, возможно, не очень часто сталкиваетесь на практике.

Комментарии:

1. STOP RUN работал с C0000. Я не подумал об этом, спасибо.

2. Теперь я хочу напечатать количество записей в SYSOUT поверх выходных данных, но, похоже, я могу распечатать его только после READ-NEXT-RECORD запуска. Есть какой-нибудь умный способ сделать это?

3. @Fnechz: вы можете либо сохранить все выходные данные в алфавитно-цифровой форме, пока все входные записи не будут прочитаны, затем записать выходные строки, либо вы можете прочитать входной файл дважды, то есть открыть файл, прочитать файл, закрыть файл, снова открыть файл, прочитать файлснова и снова закрываем файл.