第一次执行GO TO语句的问题

时间:2013-11-18 03:15:51

标签: cobol goto

使用GO-TO语句时遇到问题。这应该运行直到用户键入' END'。如果我输入' END'当我第一次打开程序时,它会关闭,但是如果我在输入第一次通过的有效数据后输入它,它就会继续返回用户输入数据屏幕。

   ENVIRONMENT DIVISION.
   INPUT-OUTPUT SECTION.
   FILE-CONTROL.

       SELECT USED-CAR-FILE-OUT
           ASSIGN TO 'USED-CAR.RPT'
           ORGANIZATION IS LINE SEQUENTIAL.

   DATA DIVISION.
   FILE SECTION.

   FD USED-CAR-FILE-OUT.
   01 USED-CAR-RECORD-OUT              PIC X(80).

   WORKING-STORAGE SECTION.
   01  FIRST-RECORD                    PIC X(3)     VALUE 'YES'.
   01  ID-CODE                         PIC X(3).
   01  TOTAL-CASH-PAYMENT              PIC 9(5).
   01  MONTHLY-PAYMENT                 PIC 9(4).
   01  NUMBER-OF-MONTHS                PIC 9(3).
   01  TOTAL-BALANCE                   PIC S9(6)V99 VALUE ZEROS.
   01  INTEREST-COLLECTED              PIC 99V99    VALUE ZEROS.
   01  MONTH-DIFF                      PIC 99       VALUE ZEROS.
   01  MONTH-NUM                       PIC 99       VALUE ZEROS.
   01  YEAR-NUM                        PIC 99       VALUE ZEROS.
   01  ID-HOLD                         PIC X(3)     VALUE SPACES.
   01  PAYMENT-HOLD                    PIC X(3)     VALUE SPACES.






   01  DETAIL-LINE.
       05  ID-CODE-DL                  PIC X(3).
       05                              PIC X(3)    VALUE SPACES.
       05                              PIC X(4)    VALUE 'Yr='.
       05  YEAR-NUMBER-DL              PIC Z9.
       05                              PIC X(4)    VALUE SPACES.
       05                              PIC X(4)    VALUE 'MO='.
       05  MONTH-NUMBER-DL             PIC Z9.
       05                              PIC X(4)    VALUE SPACES.
       05                              PIC X(5)    VALUE 'Pmt='.
       05  PAYMENT-DL                  PIC $$$,$$$.
       05                              PIC X(4)    VALUE SPACES.
       05                              PIC X(5)    VALUE 'Int='.
       05  INTEREST-EARNED-DL          PIC $$$$.99.
       05                              PIC X(3)    VALUE SPACES.
       05                              PIC X(5)    VALUE 'Bal='.
       05  BALANCE-DL                  PIC $$$,$$$.99.


   PROCEDURE DIVISION.
   100-MAIN.

       OPEN OUTPUT USED-CAR-FILE-OUT
           PERFORM 200-USER-INPUT THRU 299-EXIT
       CLOSE USED-CAR-FILE-OUT
       STOP RUN.

   200-USER-INPUT.
       DISPLAY 'Used Car Sales Report'
       DISPLAY 'Enter the ID code (or END) - maxium three char.'
       ACCEPT ID-CODE
       IF ID-CODE = 'END'
           GO TO 299-EXIT
       END-IF
       DISPLAY 'Enter the Total Cash Payment - maximum five digits'
       ACCEPT TOTAL-CASH-PAYMENT
       DISPLAY 'Enter the Monthly Payment - maximum four digits'
       ACCEPT MONTHLY-PAYMENT

       DISPLAY 'Enter the Number of Months - maximum three digits'
       ACCEPT NUMBER-OF-MONTHS
       PERFORM 300-RECORD-PROCESS.

   299-EXIT.
       EXIT.

   300-RECORD-PROCESS.
       IF TOTAL-CASH-PAYMENT > 0
           IF FIRST-RECORD = 'YES'
               MOVE ID-CODE TO ID-CODE-DL
               MOVE 1 TO YEAR-NUMBER-DL
               MOVE 1 TO YEAR-NUM
               move 1 to MONTH-NUMBER-DL
               MOVE TOTAL-CASH-PAYMENT TO PAYMENT-DL
               MOVE PAYMENT-DL TO MONTHLY-PAYMENT
               ADD MONTHLY-PAYMENT TO TOTAL-BALANCE
               MOVE 'NO' TO FIRST-RECORD
            END-IF
           COMPUTE INTEREST-COLLECTED ROUNDED = TOTAL-BALANCE
            * .0175 / 12
           MOVE INTEREST-COLLECTED TO INTEREST-EARNED-DL
           ADD INTEREST-COLLECTED TO TOTAL-BALANCE
           MOVE TOTAL-BALANCE TO BALANCE-DL
           ADD 1 TO MONTH-DIFF
           MOVE MONTH-DIFF TO MONTH-NUMBER-DL
           IF MONTH-NUMBER-DL > 13
               ADD 1 TO MONTH-NUM
               MOVE MONTH-NUM TO MONTH-NUMBER-DL
           END-IF
           IF MONTH-NUMBER-DL = 13
               MOVE 1 TO MONTH-NUM
               MOVE MONTH-NUM TO MONTH-NUMBER-DL
           END-IF
           IF MONTH-NUM = 1
               ADD 1 TO YEAR-NUM
               MOVE YEAR-NUM TO YEAR-NUMBER-DL
           END-IF
           MOVE DETAIL-LINE TO USED-CAR-RECORD-OUT
           WRITE USED-CAR-RECORD-OUT
           AFTER ADVANCING 1 LINE
           MOVE ID-HOLD TO ID-CODE-DL

           IF MONTH-DIFF < NUMBER-OF-MONTHS
               PERFORM 300-RECORD-PROCESS
           END-IF
           PERORM 200-USER-INPUT
       END-IF

       IF MONTHLY-PAYMENT > 0
           IF FIRST-RECORD = 'YES'
               MOVE ID-CODE TO ID-CODE-DL
               MOVE 1 TO YEAR-NUMBER-DL
               MOVE 1 TO YEAR-NUM
               move 1 to MONTH-NUMBER-DL
               MOVE 'NO' TO FIRST-RECORD
           END-IF

           MOVE MONTHLY-PAYMENT TO PAYMENT-DL
           MOVE PAYMENT-DL TO MONTHLY-PAYMENT
           ADD MONTHLY-PAYMENT TO TOTAL-BALANCE
           COMPUTE INTEREST-COLLECTED ROUNDED = TOTAL-BALANCE
            * .0175 / 12
           MOVE INTEREST-COLLECTED TO INTEREST-EARNED-DL
           ADD INTEREST-COLLECTED TO TOTAL-BALANCE
           MOVE TOTAL-BALANCE TO BALANCE-DL
           ADD 1 TO MONTH-DIFF
           MOVE MONTH-DIFF TO MONTH-NUMBER-DL
           IF MONTH-NUMBER-DL > 13
               ADD 1 TO MONTH-NUM
               MOVE MONTH-NUM TO MONTH-NUMBER-DL
           END-IF
           IF MONTH-NUMBER-DL = 13
               MOVE 1 TO MONTH-NUM
               MOVE MONTH-NUM TO MONTH-NUMBER-DL
           END-IF
           IF MONTH-NUM = 1
               ADD 1 TO YEAR-NUM
               MOVE YEAR-NUM TO YEAR-NUMBER-DL
           END-IF
           MOVE DETAIL-LINE TO USED-CAR-RECORD-OUT
           WRITE USED-CAR-RECORD-OUT
           AFTER ADVANCING 1 LINE
           MOVE ID-HOLD TO ID-CODE-DL
           IF TOTAL-CASH-PAYMENT > 0
               MOVE 0 TO TOTAL-CASH-PaYMENT
               MOVE 0 TO PAYMENT-DL
           END-IF
           IF MONTH-DIFF < NUMBER-OF-MONTHS
           PERFORM 300-RECORD-PROCESS
           END-IF
       PERFORM 200-USER-INPUT
       END-IF.

EDIT解决了以下问题 如果几个月,我也会遇到问题。 24.我逐步完成程序,它显示我的最后一个细节线作为正确的结果,但我的输出在24个月停止。提前致谢。

3 个答案:

答案 0 :(得分:4)

AAAAAAAk!

执行严重殴打 - 通过提示 - 通过执行 使用重型物体
直到承诺 - 从未提取过 - 再次 - 请

执行即 EVIL 。它会导致与布局相关的代码。

在顶级控制级别,使用

PERFORM 200-USER-INPUT
  UNTIL ID-CODE = 'END'.

(或者可能在ID-CODE上使用88 USER-INPUT-ENDED - 样式问题)

如何确定是否继续输入200 -...是您的选择,

IF NOT USER-INPUT-ENDED
   DISPLAY 'Enter the Total Cash Payment - maximum five digits'
   ACCEPT TOTAL-CASH-PAYMENT
   ...
   ACCEPT NUMBER-OF-MONTHS
   PERFORM 300-RECORD-PROCESS.

OR

  IF NOT USER-INPUT-ENDED
     PERFORM 210-ACCEPT-DETAILS.

210-ACCEPT-DETAILS.

   DISPLAY 'Enter the Total Cash Payment - maximum five digits'.
   ACCEPT TOTAL-CASH-PAYMENT.
   ...
   ACCEPT NUMBER-OF-MONTHS.
   PERFORM 300-RECORD-PROCESS.

因为你PERFORMED 200 -...然后只会执行200 -... 210 -...是一个新段落,只能从200 -... IF END进入。

下一步是稍微修改300 -...
  在200 -...中的PERFORM 300 -...之前移动初始化(FIRST-RECORD ='YES'代码),然后将PERFORM 300-RECORD-PROCESS.修改为

  PERFORM 300-RECORD-PROCESS
    UNTIL TOTAL-BALANCE = 0.

(我在这里假设这是报告终止条件;如果不是,则替换报告终止条件)

您现在可以重组300 -...来计算应付利息,修改年份和月份数字并显示结果。 所有在300 -...中的PERFORM将消失。

所以,实质上你有

MAIN:perform user-input until end-detected.  
user-input: get user data; perform calculations until balance is zero.
calculations: one month's calculations at a time. 

这也有一个好处,如果你选择,你可以插入

IF MONTHLY-PAYMENT IS LESS THAN INTEREST-COLLECTED
   MOVE 'ERR' TO ID-CODE.

在ID-CODE中使用'ERR'在300 -...而不是渐进式报告行AND中产生适当的错误消息,同时将0分配给TOTAL-BALANCE,终止{ {1}}。

答案 1 :(得分:1)

你的问题是你为自己创造了一个无限循环。你200段执行300段,你的300段执行你的200段。

您需要重新构建您的计划。

一个名为200-USER-INPUT的段落应该关注它。

repeat until end of input
     get some input
     if there is input to process 
         process the input

Yoiks!我刚刚注意到你在300以内的PERFORM 300 - !

答案 2 :(得分:1)

使用GO TO和PERFORM THROUGH段落范围已经破坏了COBOL的过程返回机制 用于维护适当的程序控制流程。实质上,你有一个无效的程序 - 它可能会编译 没有错误但根据COBOL的规则仍然是无效的程序。

以下是从控制流的角度来看程序正在做什么的概述。该 主线计划基本上是:

100-MAIN.
   PERFORM 200-USER-INPUT THRU 299-EXIT

这要求COBOL执行从头开始找到的所有代码 200-USER-INPUT直到299-EXIT结束。这些大纲 程序是:

200-USER-INPUT.
    IF some condition GO TO 299-EXIT
    ...
    PERFORM 300-RECORD-PROCESS
    .

299-EXIT.

请注意,如果some condition为真,则程序流将跳过结束 200-USER-INPUT并跳转到299-EXIT。 299-EXIT什么都不做 非常有趣,它只是一个空段落作为一个结束 执行段落范围。

在段落300-RECORD-PROCESS中,您有相当多的代码。有趣的 位是:

 300-RECORD-PROCESS.
    ...
    PERFORM 200-USER-INPUT

请注意,PERFORM 200-USER-INPUT这不是PERFORM THRU,因为您已在100-MAIN中编码。 问题是,当你回到200-USER-INPUT并且some codition变成时 true(当你输入'EXIT'时),控制流程 跳到段落结尾的299-EXIT 你现在正在表演。从这一点来说 转发COBOL使用的控制机制流程来管理来自PERFORM动词的返回 已经腐败了。不再有正常的控制机制流程返回到200-USER-INPUT的位置 是在300-RECORD-PROCESS中进行的。

接下来发生的事情并不是大多数程序员所期望的。大多数程序员似乎都在期待 当达到299-EXIT结束时,程序流程应该返回到最后一个PERFORM的位置 已经完成。在这种情况下,就在PERFORM 200-USER-INPUT之后。不,COBOL不会那样工作,控制流程 将继续299-EXIT之后的下一个可执行语句。这会让你 回到300-RECORD-PROCESS中的第一个可执行语句!这就是你的原因 没有得到这个计划的预期行为。

COBOL程序中的逻辑流程必须确保执行过程的结束 总是以与它们相反的顺序到达。这对应于呼叫/返回 堆栈语义 大多数程序员都熟悉。

我的建议是避免使用PERFORM THRUGO TO。这是两个最大的 今天用COBOL编程语言留下的邪恶。这些结构是一个悬念 过去的编程时代,今天没有建设性的好处。