2

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

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

4

2 回答 2

4

乍一看,我注意到您的代码存在两个问题:

  1. 由于数字项的 - 子句不同,您的PRINT-LINE和的长度也不同。例如使用while使用。请注意, - 子句中的小数点需要一个字节的存储空间,而 则根本不占用任何存储空间,因此 in 的字段比 in 的字段大一个字节。TRANSFER-LINEPICTUREPRINT-LINEPIC ZZ9.99TRANSFER-LINEPIC 9(3)V99.PICTUREVPRINT-LINETRANSFER-LINE
  2. 当您这样做时,MOVE TRANSFER-LINE TO PRINT-LINE您不会进行逐个字段的传输,而是将整个数据块作为一个数据块移动,因此完全忽略PICTURE- 子句。PRINT-LINE您不会遇到更大的麻烦,因为PRINT-LINE它占用的存储空间多于TRANSFER-LINE(参见 1.) - 如果反过来,您甚至可能会遇到存储覆盖问题(但至少应该得到编译器警告)。

为了做到这一点,你可以

  • 将 level-02-items 命名为PRINT-LINElike those ofTRANSFER-LINE并执行MOVE CORRESPONDING TRANSFER-LINE TO PRINT-LINE- 但随后您必须使用限定名称 ( INTEREST OF TRANSFER-LINE)来处理您的字段

或者

  • 摆脱TRANSFER-LINE并将您的数据直接放入PRINT-LINE
于 2016-08-24T12:07:47.623 回答
3

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

更远:

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

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

你的命名很糟糕。COBOL 程序通常存在很多很多年。某些 1970 年代编写的程序至今仍以 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 是默认设置。无需指定。

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

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

例如,您知道每条记录都需要一个标题,不是吗?为什么要在循环中进行测试?

于 2016-08-25T07:52:15.670 回答