2016-08-24 1 views
1

В настоящее время я изучаю на неделю старый язык программирования COBOL, но столкнулся с проблемой. это образец программы Cobol.Как отобразить десятичный формат вывода в коболе?

IDENTIFICATION DIVISION. 
    PROGRAM-ID. MONTHLY. 
    ENVIRONMENT DIVISION. 
    INPUT-OUTPUT SECTION. 
    FILE-CONTROL. 
     SELECT IN-FILE ASSIGN TO "USERINPUT.DAT". 
     SELECT OUT-FILE ASSIGN TO "USEROUTPUT.DAT". 
    DATA DIVISION. 
    FILE SECTION. 
    FD IN-FILE 
     LABEL RECORDS ARE STANDARD 
     DATA RECORD IS IN-REC. 
    01 IN-REC. 
     02 C-NAME PIC X(25). 
     02 STREET PIC X(20). 
     02 ZIP-CODE PIC X(15). 
     02 CREDIT PIC 9(6)V99. 
     02 MONTH PIC 99. 
     02 FILLER PIC XX VALUE "\n". 
    FD OUT-FILE 
     LABEL RECORDS ARE STANDARD 
     DATA RECORD IS OUT-REC. 
    01 OUT-REC PIC X(80). 
    *----------------------- 
    WORKING-STORAGE SECTION. 
    *----------------------- 
    01 HDG-01. 
     02 FILLER PIC X(27) VALUE SPACES. 
     02 FILLER PIC X(27) VALUE "ABC Loans & Savings Company". 
    01 HDG-02. 
     02 FILLER PIC X(28) VALUE SPACES. 
     02 FILLER PIC X(25) VALUE "Ayala Avenue, Makati City". 
    01 HDG-03. 
     02 FILLER PIC X(30) VALUE SPACES. 
     02 FILLER PIC X(20) VALUE "SCHEDULE OF PAYMENTS". 
    01 HDG-04. 
     02 FILLER PIC X(28) VALUE SPACES. 
     02 FILLER PIC X(15) VALUE "ORIGINAL AMOUNT". 
     02 REC-CREDIT PIC Z(5)9.99. 
    01 HDG-05. 
     02 FILLER PIC X(14) VALUE SPACES. 
     02 FILLER PIC X(9) VALUE "MONTH". 
     02 FILLER PIC X(11) VALUE "INTEREST". 
     02 FILLER PIC X(17) VALUE "TOTAL-PAYMENT". 
     02 FILLER PIC X(14) VALUE "UNPAID-BALANCE". 
    01 TRANSFER-LINE. 
     02 FILLER PIC X(16) VALUE SPACES. 
     02 REC-MONTH PIC 99. 
     02 FILLER PIC X(6) VALUE SPACES. 
     02 INTEREST PIC 9(3)V99. 
     02 FILLER PIC X(7) VALUE SPACES. 
     02 TOTAL-PAY PIC 9(6)v99. 
     02 FILLER PIC X(10) VALUE SPACES. 
     02 UNPAID-BAL PIC 9(6)v99. 
    01 PRINT-LINE. 
     02 FILLER PIC X(16) VALUE SPACES. 
     02 FILLER PIC 99. 
     02 FILLER PIC X(6) VALUE SPACES. 
     02 FILLER PIC ZZ9.99. 
     02 FILLER PIC X(7) VALUE SPACES. 
     02 FILLER PIC Z(5)9.99. 
     02 FILLER PIC X(10) VALUE SPACES. 
     02 FILLER PIC Z(5)9.99. 
    01 PRINT-NULL. 
     02 FILLER PIC X(16) VALUE SPACES. 
     02 FILLER PIC XX VALUE "--". 
     02 FILLER PIC X(6) VALUE SPACES. 
     02 FILLER PIC XXXXX VALUE "-----". 
     02 FILLER PIC X(7) VALUE SPACES. 
     02 FILLER PIC X(9) VALUE "---------". 
     02 FILLER PIC X(9) VALUE SPACES. 
     02 FILLER PIC X(9) VALUE "---------". 
    01 X PIC 99. 
    01 REM PIC 999. 
    01 CHECK-MONTH PIC 99. 
    01 CLIENT-NO PIC 9. 
    01 PRINT-ASTERISK. 
     02 FILLER PIC X(30) VALUES ALL "*" . 
     02 FILLER PIC X(18) VALUES "-END OF CLIENT NO ". 
     02 CLIENT PIC 9. 
     02 FILLER PIC X VALUE "-". 
     02 FILLER PIC X(30) VALUES ALL "*" . 
    PROCEDURE DIVISION. 

    OPEN INPUT IN-FILE 
     OUTPUT OUT-FILE. 

    REPEAT-RTN. 
     ADD 1 TO CLIENT-NO. 
     MOVE CLIENT-NO TO CLIENT. 
     READ IN-FILE AT END PERFORM CLOSE-RTN. 
     MOVE CREDIT TO UNPAID-BAL. 
     MOVE MONTH TO CHECK-MONTH. 
     PERFORM WITH TEST BEFORE UNTIL CHECK-MONTH < 13 
      COMPUTE CHECK-MONTH = CHECK-MONTH - 12 
     END-PERFORM. 
     COMPUTE CHECK-MONTH = MONTH + (12 - CHECK-MONTH). 
     MOVE ZEROES TO X. 
     PERFORM PROCESS-RTN CHECK-MONTH TIMES. 
     WRITE OUT-REC FROM PRINT-ASTERISK AFTER 1 LINE. 
     PERFORM REPEAT-RTN. 

    PROCESS-RTN. 
     ADD 1 TO X. 
     MOVE X TO REM. 

     PERFORM WITH TEST BEFORE UNTIL REM <= 13 
      COMPUTE REM = REM - 12 
     END-PERFORM. 

     IF REM=13 OR REM = 1 THEN 
      PERFORM HDG-RTN 
     END-IF. 
     IF REM=13 THEN 
      MOVE SPACES TO OUT-REC 
      WRITE OUT-REC. 
     MOVE X TO REC-MONTH. 
     COMPUTE INTEREST = UNPAID-BAL * 0.015. 
     COMPUTE TOTAL-PAY ROUNDED= CREDIT/MONTH + INTEREST. 
     COMPUTE UNPAID-BAL = UNPAID-BAL - TOTAL-PAY + INTEREST. 

     IF UNPAID-BAL < 1 THEN 
      MOVE ZEROES TO UNPAID-BAL 
     END-IF. 

     IF X > MONTH THEN 
      WRITE OUT-REC FROM PRINT-NULL AFTER 1 LINE 
     ELSE 
      MOVE TRANSFER-LINE TO PRINT-LINE 
      WRITE OUT-REC FROM PRINT-LINE AFTER 1 LINE 
     END-IF. 

    HDG-RTN. 
     IF X > 1 THEN 
      WRITE OUT-REC FROM HDG-01 AFTER 2 LINE 
      WRITE OUT-REC FROM HDG-02 AFTER 1 LINE 
      WRITE OUT-REC FROM C-NAME AFTER 2 LINE 
     ELSE IF CLIENT-NO > 1 THEN 
      WRITE OUT-REC FROM HDG-01 AFTER 1 LINE 
      WRITE OUT-REC FROM HDG-02 AFTER 1 LINE 
      WRITE OUT-REC FROM C-NAME AFTER 2 LINE 
     ELSE 
      WRITE OUT-REC FROM HDG-01 BEFORE 1 LINE 
      WRITE OUT-REC FROM HDG-02 BEFORE 1 LINE 
      WRITE OUT-REC FROM C-NAME AFTER 1 LINE 
     END-IF. 
     WRITE OUT-REC FROM STREET AFTER 1 LINE. 
     WRITE OUT-REC FROM ZIP-CODE AFTER 1 LINES. 
     WRITE OUT-REC FROM HDG-03 AFTER 2 LINE. 
     MOVE CREDIT TO REC-CREDIT. 
     WRITE OUT-REC FROM HDG-04 AFTER 1 LINE. 
     WRITE OUT-REC FROM HDG-05 AFTER 2 LINE. 

    CLOSE-RTN. 
     CLOSE IN-FILE , OUT-FILE. 
     STOP RUN. 

    END PROGRAM MONTHLY. 

Программа предполагает, чтобы производить вывод, как эти:

     ABC Loans & Savings Company       
         Ayala Avenue, Makati City       

The Client Name is Here:               
The Client Address:                
The ZiP/CITY:                 

          SCHEDULE OF PAYMENTS        
         ORIGINAL AMOUNT 4291.50        

      MONTH INTEREST TOTAL-PAYMENT UNPAID-BALANCE    
      01  64.37  422.00   3933.87     
      02  05900  416.63   3576.24     
      03  05364  411.27   3218.61     
      04  04827  405.90   2860.98     
      05  04291  400.54   2503.35     
      06  03755  395.18   2145.72     
      07  03218  389.81   1788.09     
      08  02682  384.45   1430.46     
      09  02145  379.08   1072.83     
      10  01609  373.72   715.20     
      11  01072  368.35   357.57     
      12  00536  362.99    0.00     
******************************-END OF CLIENT NO 1-****************************** 

Но выход программы при запуске программа отличается. Это выглядит так:

     ABC Loans & Savings Company       
         Ayala Avenue, Makati City       

The Client Name is Here:               
The Client Address:                
The ZiP/CITY:                 

          SCHEDULE OF PAYMENTS        
         ORIGINAL AMOUNT 4291.50        

      MONTH INTEREST TOTAL-PAYMENT UNPAID-BALANCE    
      01  06437  00042200   00393387     
      02  05900  00041663   00357624     
      03  05364  00041127   00321861     
      04  04827  00040590   00286098     
      05  04291  00040054   00250335     
      06  03755  00039518   00214572     
      07  03218  00038981   00178809     
      08  02682  00038445   00143046     
      09  02145  00037908   00107283     
      10  01609  00037372   00071520     
      11  01072  00036835   00035757     
      12  00536  00036299   00000000     
******************************-END OF CLIENT NO 1-****************************** 

У меня проблема с десятичным форматированием и нулевым подавлением. кстати, я просто использовал DAT-файл для ввода, поэтому я не использую никаких функций ACCEPT или ввода, и он содержит точный символ, необходимый для записи, такой как текст ниже:

Имя клиента здесь: Клиент Адрес: ZiP/CITY: 0042915012

Я считаю, что проблема кроется в рабочей линии печати и линии передачи.

+0

Похоже, что ваш образец также выключен, если у вас нет объяснений для столбца интересов. –

ответ

3

На первый взгляд я заметил две проблемы с кодом:

  1. длина вашего PRINT-LINE и TRANSFER-LINE отличаются из-за разницы в PICTURE -clauses числовых элементов. Например, PRINT-LINE использует PIC ZZ9.99, а TRANSFER-LINE использует PIC 9(3)V99. Обратите внимание, что десятичная точка . в PICTURE -clause требует одного байта хранения, а V вообще не занимает никакого хранения, поэтому поле в PRINT-LINE является одним байтом, большим, чем в TRANSFER-LINE.
  2. Когда вы делаете MOVE TRANSFER-LINE TO PRINT-LINE, вы не выполняете передачу поля за полем, а вместо этого перемещаете весь блок данных как один, поэтому PICTURE -классы в PRINT-LINE полностью игнорируются. Вы не сталкиваетесь с большими проблемами, поскольку PRINT-LINE занимает больше места хранения, чем TRANSFER-LINE (см. 1.). Если бы это было наоборот, у вас могли бы даже возникнуть проблемы с перезаписыванием (но, по крайней мере, получить предупреждение о компиляторе).

Чтобы получить это право можно

  • Назовите уровень-02-пункты PRINT-LINE, как у TRANSFER-LINE и сделать MOVE CORRESPONDING TRANSFER-LINE TO PRINT-LINE - но тогда вам придется обратиться в ваше поле с квалифицированным именем (INTEREST OF TRANSFER-LINE)

или

  • Get избавьтесь от TRANSFER-LINE и поместите ваши данные непосредственно в PRINT-LINE
2

@ piet.t указал на проблему при создании вашего вывода. Только когда отдельное поле является «целевым» полем для чего-либо, произойдет любое преобразование данных любого типа. Для ПЕРЕМЕЩЕНИЯ группы в группу все подчиненные определения игнорируются.

Далее:

У вас есть "рекурсивный" использование ВЫПОЛНИТЬ. То, что это делает, не определено и может отличаться от компилятора к компилятору. Никогда не используйте это.

У вас есть предложение VALUE на позиции, отличной от 88-го уровня, в разделе FILE. Это ничего не делает - и если да, то что вы пытаетесь?

Ваше имя плохое. Программы COBOL часто существуют для многих, многих, лет. Есть определенные программы, написанные в 1970-х годах, которые по-прежнему работают со 100 точностью. Программа будет написана один раз, но ее нужно будет понимать много раз - так напишите, чтобы люди поняли. Не используйте имена с одним словом, используйте описательные имена (всегда есть шанс, что новый стандарт COBOL «зарезервирует» ваше однословное имя, и это вызовет путаницу в следующий раз, когда программа изменится). X, REM и CHECK-MONTH означают, что? Что означает МЕСЯЦ (не то, что люди ожидали бы)?

Что это, и это кузен, должен делать?

PERFORM WITH TEST BEFORE UNTIL CHECK-MONTH < 13 
     COMPUTE CHECK-MONTH = CHECK-MONTH - 12 
    END-PERFORM. 

Для кого-то, кто обеспокоен «древними» языками, почему вы печатаете все эти полные остановки/периоды? Они не нуждались в таком широком (и подверженном ошибкам) ​​использовании с 1985 года.

Используйте END-IF. Всегда, а не только тогда, когда вам хочется, чтобы закончить каждый IF.

Использовать ОЦЕНКУ. Доступен с 1985 года и заменяет ваш END-IF-дефицитный вложенный-IF.

С ИСПЫТАНИЕМ ПРЕЖДЕ ЧЕМ находится по умолчанию. Не нужно указывать его.

Учитывайте, что поля, которые могут стать отрицательными, не будут делать этого, если они не подписаны.

Создайте свою программу, прежде чем писать. Если выяснится, что дизайн не работает, перепроектируйте, а не просто «исправляйте» существующую программу, чтобы она выглядела так, как будто «работает».

Например, вы знаете, что вам нужен заголовок для каждой записи, не так ли? Зачем тестировать это внутри цикла?

+0

Я думаю, что VALUE здесь для информационных целей (кажется, карету returne, кстати). Но я согласен с вами: хотя рекурсия на некоторых языках сексуальна, в COBOL это не очень хорошая идея. Вообще. И это делается с выходом, который нарушает поток исполнения, поэтому это даже не правильная рекурсия. Даже правильная рекурсия, однако, не будет использоваться, как вы сказали. И эта переменная называется «X». Aaaaargh. – gazzz0x2z

+1

@ gazzz0x2z Я знаю, что должен быть/n, но COBOL - это скомпилированный язык, «текст»/n во время выполнения - это просто. Текст :-) –

Смежные вопросы