如何在cobol中显示十进制格式输出?

时间:2016-08-24 09:28:20

标签: output cobol gnucobol

我目前正在学习一周的旧编程语言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

我认为问题在于工作存储打印线和传输线。

2 个答案:

答案 0 :(得分:4)

乍一看,我发现您的代码有两个问题:

  1. PRINT-LINETRANSFER-LINE的长度不同,因为数字项的PICTURE - 子句不同。例如,PRINT-LINE使用PIC ZZ9.99TRANSFER-LINE使用PIC 9(3)V99。请注意,. - 子句中的小数点PICTURE需要一个字节的存储空间,而V根本不需要任何存储空间,因此PRINT-LINE中的字段是比TRANSFER-LINE中的字节大一个字节。
  2. 执行MOVE TRANSFER-LINE TO PRINT-LINE时,您不会进行逐字段转移,而是将整个数据块移动为一个,因此PICTURE中的PRINT-LINE - 子句是完全被忽略了你不会遇到更大的麻烦,因为PRINT-LINETRANSFER-LINE占用更多的存储空间(参见1.) - 如果是相反的话,你甚至可能会遇到存储覆盖问题(但至少应该存在)得到编译器警告)。
  3. 为了做到这一点你可以

    • PRINT-LINE的02级项目命名为TRANSFER-LINE,并执行MOVE CORRESPONDING TRANSFER-LINE TO PRINT-LINE - 然后您必须使用限定名称({{1} }})

    • 摆脱INTEREST OF TRANSFER-LINE并将您的数据直接放入TRANSFER-LINE

答案 1 :(得分:3)

@ piet.t指出了生成输出的问题。只有当单个字段是某个字段的“目标”字段时,才会发生任何类型的任何数据转换。对于将组移动到组,将忽略所有从属定义。

此外:

您对PERFORM进行“递归”使用。这样做是未定义的,并且可能因编译器而异。永远不要使用它。

您在FILE SECTION中的非88级项目上有一个VALUE子句。这没有任何作用 - 如果确实如此,你在尝试什么?

你的命名很差。 COBOL程序通常存在许多年。对于某些在20世纪70年代编写的程序,今天仍以100精度运行。一个程序将被编写一次,但需要多次理解 - 所以写给人们理解。不要使用单字名称,使用描述性名称(新的COBOL标准总是有可能“保留”您的单字名称,这将在下次程序更改时引起混淆)。 X,REM和CHECK-MONTH意味着什么? 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。

WITH TEST BEFORE是默认值。无需指定它。

如果没有签名,请考虑可能变为负数的字段不会这样做。

在编写程序之前设计程序。如果事实证明设计不起作用,请重新设计,而不是仅仅“修补”现有程序,使其看起来“有效”。

例如,知道您需要为每条记录添加标题,不是吗?为什么要在循环内测试?