Почему я получаю ошибку SB37 в коде?

Я меняю три значения внутри файла, который определяет 7500 байт. Раньше я помещал все определения файлов после своего файла, чтобы лучше их видеть. Но так как я поднялся на уровень в COBOL, я просто хочу сделать все заполнителем, а затем сделать видимыми четыре поля, к которым мне нужно получить доступ.

Я продолжаю получать ошибку sB37, когда запускаю свой JCL. Мой выходной файл также определяется как 7500 байт. Я просмотрел список компиляции, и он показывает все мои поля в правильных местах.

Я посмотрел на свой выходной файл, и, кажется, было записано только 28 000 записей, и первые десять выглядят как мусорная информация.

Я не могу перечислить всю программу для правил компании, но как мне решить ошибку sB37.

Вопрос: как исправить ошибку sB37?

Код:

FD OUTPUT-FILE                                   
     RECORD VARYING FROM 2900 TO 7500          
     RECORDING MODE IS V                       
     BLOCK CONTAINS 0.                         
 01 O-PROVIDER-RECORD.                            
     05 FILLER              PIC X(149).           
     05 END-DTE             PIC X(8).             
     05 CANCEL              PIC X(2).             
     05 FILLER              PIC X(1133).          
     05 LAST-ACTIVITY-DTE   PIC X(8).             
     05 FILLER              PIC X(1598).          
     05 GROUP-CTR           PIC S999 COMP-3.      
     05 FILLER              PIC X(4600).  

JCL:

//STEP2      EXEC PGM=programnamehere             
//STEPLIB     DD DSN=SW89.DEBUG.programnamehere,DISP=SHR                 
//SYSOUT      DD SYSOUT=1                                         
//SYSDBOUT    DD SYSOUT=1                                         
//SYSOUC      DD SYSOUT=2                                         
//SYSPRINT    DD SYSOUT=1                                         
//SYSUDUMP    DD SYSOUT=1                                         
//INPUT1      DD DSN=MainFile.B01(+0),DISP=SHR,BUFNO=30               
//INPUT2      DD DSN=CDP.PARMLIB(SW00T111),DISP=SHR               
//OUTPUT1     DD DSN=SW89.DEBUG.OUTPUTFILE,DISP=(NEW,CATLG),             
//            DCB=TS20.VB7504.MODEL,MGMTCLAS=TMM,                 
//            SPACE=(CYL,(100,10),RLSE)                           
//PRTOUTA     DD SYSOUT=3,DCB=(BLKSIZE=0,LRECL=133,RECFM=FBM)     
//*         

Последняя часть файла:

 05  AREA.                                                    
     10  IND                     PIC X.                 
     10  CTR                     PIC S999  COMP-3.      
    10 P-GROUP-INFO OCCURS 200 TIMES DEPENDING ON CTR.
         15  P-NO                PIC 9(7).              
         15  P-START-DTE.                                
             20  PSTART-CC       PIC 99.                 
             20  P-START-DATE.                           
                 25  P-START-YY  PIC 99.                 
                 25  P-START-MM  PIC 99.                 
                 25  P-START-DD  PIC 99.                 
         15  P-STOP-DTE.                                 
             20  P-STOP-CC       PIC 99.                 
             20  P-STOP-DATE.                            
                 25  YY          PIC 99.                 
                 25  MM          PIC 99.                 
                 25  DD          PIC 99.                 

Когда я иду проверять свои совпадения, я обнаруживаю, что мой оператор записи вставляет пустую строку между всеми моими обычными строками файла. Единственное, что здесь должно произойти, это то, что три значения изменяются в o-provider-record, а затем записываются обратно в файл. В каждой второй строке не должно быть пустых строк с этой новой информацией.

Код:

CHECK-MATCH.                                                     
    PERFORM VARYING SUB FROM 1 BY 1 UNTIL SUB > TABLECOUNTER     
      IF P-PROVIDER >= TRIG-PROV-FROM(SUB) AND                   
         P-PROVIDER <= TRIG-PROV-THRU(SUB) THEN                  
         IF WS-CURRENT-DATE < P-END-DTE THEN                     
            IF P-YTD-TOTAL-PD  = 0 AND                           
               P-PYR-TOTAL-PD  = 0 AND                           
               P-PYR2-TOTAL-PD = 0 AND                           
               P-PYR3-TOTAL-PD = 0 AND                           
               P-PYR4-TOTAL-PD = 0 THEN                          
               IF P-NON-BILL-IND NOT EQUAL 'Y'                   
                PERFORM VARYING TAB FROM 1 BY 1 UNTIL TAB > 5    
                 IF P-TAXONOMY-CD(TAB) = TRIG-TAXONOMY(SUB) THEN 

                    ADD 1 TO T-REC-FOUND                       
                    ADD 1 TO T-REC-UPDATED                     

                    MOVE 'ZZ' TO O-CANCEL                      
                    MOVE '93939393' TO O-END-DTE               
                    MOVE '93939393' TO O-LAST-ACTIVITY-DTE    

                    PERFORM LOAD-PRINT-REPORT THRU X-LPR       
                    PERFORM PRINT-REPORT      THRU X-PR        
                    PERFORM ERASE-REPORT      THRU X-ER        
                 END-IF                                        
                END-PERFORM                                    
               END-IF                                          
            END-IF                                             
         END-IF                                                
      END-IF                                                   
     ADD 1 TO T-REC-WRITTEN              
     WRITE O-PROVIDER-RECORD END-WRITE   
    END-PERFORM.                         
X-CHECK-MATCH. EXIT.   

person Community    schedule 17.03.2014    source источник


Ответы (1)


Вы пишете выходную запись для каждой итерации вашего самого внешнего PERFORM. Если есть две итерации (подозреваемые из ваших предыдущих вопросов), то для каждой входной записи вы получите две выходные записи.

Мы знаем, что ваш файл содержит записи переменной длины. Судя по описанному вами поведению, вы не используете APPLY WRITE ONLY для этого файла, поэтому поведение соответствует ожидаемому. COBOL указывает FD/01 на следующее доступное место в выходном буфере, сначала после OPEN, а затем после каждой успешной записи. Ваша первая запись в цикле PERFORM приведет к перемещению указателя на следующую доступную позицию, которая содержит в качестве отправной точки любой старый материал, который случайно завалялся (для ранних операций записи это, вероятно, будут двоичные нули, поскольку буферы используются повторно, это будут ваши старые данные).

Вам нужна реструктуризация, как предложил NealB в предыдущем вопросе. У вас есть много тестов, которые «инвариантны» внутри цикла. Они должны быть снаружи, и цикл должен вводиться только в том случае, если эти инвариантные тесты показывают возможность того, что цикл необходим в этом случае.

Вернемся к более ранним ответам. Это будет очень запутанно...

Теперь мы можем видеть вашу исходную запись, у вас есть OCCURS... DEPENDING ON... что заставляет исходный файл содержать записи переменной длины при написании из программы COBOL.

Если вы включаете в свое определение тот же размер счетчика и позицию и имеете OCCURS с записью длиной 23 байта, вы сделаете эту часть записи переменной длиной от нуля до 4600 байт (ваша замена для CTR со значением 0 до 200).

Я бы не сделал CTR упакованным десятичным полем, я бы сделал его бинарным (BINARY/COMP/COMP-4), но это не то, что вы можете изменить, и не определяйте его иначе для вашей версии макет, иначе будут происходить очень странные вещи.

Догадка:

У вас есть RECORD [IS] VARYING ... но у вас нет ничего, что могло бы изменить длину этой конкретной записи.

Обычно есть три способа справиться с этим: иметь OCCURS DEPENDING ON внутри записи со значением в начале записи, которое указывает, сколько раз что-то происходит; используйте ИЗМЕНЕНИЕ В ЗАВИСИМОСТИ ОТ на FD; используйте разные макеты записей, несколько уровней 01 в FD.

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

По мере того, как мы становимся более опытными, мы используем КОПИИ и тетради. Это не проблема, если определены сотни полей, но используются лишь некоторые из них. Используя тетрадь, нам не нужно проверять позиции, потому что мы знаем, что у нас есть то же самое, что и любая программа, обрабатывающая эти данные. Кодирование собственных макетов — неправильное направление.

person Bill Woodger    schedule 17.03.2014
comment
Иногда он запускается, но по большей части дает мне все неверные данные. Другой человек, с которым я работаю, сказал мне использовать в моем JCL SYSIN dd dsn=sw.t10.prime.filename,disp=(,CATLG),DCB=(LRECL=1500,RECFM=FB,BUFNO=25),RETPD= 40,МГМТКЛАСС=ТММ - person ; 17.03.2014
comment
По-прежнему получают неверные данные, даже если они настроены только на чтение записи, а затем на запись этой же записи в файл. Выбрасывает мусор на поля. - person ; 18.03.2014
comment
Вы используете WRITE или WRITE... FROM...? Если просто WRITE, вы перемещаете свои данные в выходную запись перед WRITE? - person Bill Woodger; 18.03.2014
comment
WRITE O-PROVIDER-RECORD END-WRITE. ‹-- Это запись, которую я использую. - person ; 18.03.2014
comment
А как вы получаете данные в O-PROVIDER-RECORD? - person Bill Woodger; 18.03.2014
comment
ПЕРЕМЕСТИТЕ P-PROVIDER-RECORD в O-PROVIDER-RECORD. - person ; 19.03.2014