COBOL adding an array

泄露秘密 提交于 2019-12-25 14:14:20

问题


I want my program to output the inputted array then display the total amount I input. The total value is wrong and the value changes in the array in my program. I think my problem is the adding part. How should I fix it?

 IDENTIFICATION DIVISION.
 PROGRAM-ID. FOREXCHANGE.
 DATA DIVISION.
 WORKING-STORAGE SECTION.
   01 CURR-VAL.
      02 USD  PIC 999V99 VALUE 46.59.
      02 AUS  PIC 999V99 VALUE 32.87.
      02 CND  PIC 999V99 VALUE 36.37.
      02 EUR  PIC 999V99 VALUE 52.32.
      02 YEN  PIC 999V99 VALUE 0.40.
      02 NZD  PIC 999V99 VALUE 30.04.
      02 OMN  PIC 999V99 VALUE 120.99.
      02 SGD  PIC 999V99 VALUE 32.52.
   77 AMOUNT      PIC 9(6)V99.
   77 NEWVAL      PIC 9(4)V99.
   77 ROUNDOFF    PIC ZZZ,ZZ9.99.
   77 VALCUR      PIC 9(6)V99.
   77 FORCUR      PIC X(3).
   77 TRANSAC     PIC 9(4) OCCURS 9999 TIMES.
   77 CURRENCIES  PIC X(3) OCCURS 9999 TIMES.
   77 AMOUNTARR   PIC 9(6)V99 OCCURS 9999 TIMES.
   77 AMOUNTTOT   PIC 9(6)V99 OCCURS 9999 TIMES.
   77 TRANSACNUM  PIC 9(4) VALUE 0001.
   77 CTR         PIC 9(4) VALUE ZERO.
   77 CTR1        PIC 9(4) VALUE ZERO.
   77 CURINDEX    PIC 9 VALUE 0.
   77 CHOICE      PIC X. 
 PROCEDURE DIVISION.
  MAIN-MENU.
     DISPLAY ERASE.
     DISPLAY "MAIN MENU".
     DISPLAY "1. TRANSACTION".
     DISPLAY "2. UPDATE".
     DISPLAY "3. SUMMARY".
     DISPLAY "4. EXIT".
     DISPLAY "ENTER CHOICE: " WITH NO ADVANCING.
     ACCEPT CHOICE.
     IF CHOICE = "1"
        PERFORM ADDTRANS
     ELSE IF CHOICE = "2"
        PERFORM UPDATES
     ELSE IF CHOICE = "3"
        PERFORM SUMMARIES 
     ELSE IF CHOICE = "4"
        STOP RUN
     ELSE 
        DISPLAY "INVALID CHOICE! PLEASE TRY AGAIN!"
        PERFORM MAIN-MENU.

  SUMMARIES.
     DISPLAY ERASE.
     DISPLAY "SUMMARY".
     DISPLAY "TRANSACTION NUMBER   CURRENCY   AMOUNT".
     PERFORM WITH TEST AFTER VARYING CTR FROM 1 BY 1 
           UNTIL CTR = CURINDEX

             DISPLAY "          " TRANSAC(CTR) WITH NO ADVANCING
             DISPLAY "         " WITH NO ADVANCING
             DISPLAY CURRENCIES(CTR)WITH NO ADVANCING
             MOVE AMOUNTARR(CTR) TO ROUNDOFF
             DISPLAY "      " ROUNDOFF
     END-PERFORM.
     PERFORM WITH TEST AFTER VARYING CTR FROM 1 BY 1 
           UNTIL CTR = CURINDEX
                 ADD AMOUNTARR(CTR) TO AMOUNTARR(CTR)
     END-PERFORM.

     MOVE AMOUNTARR(CURINDEX) TO ROUNDOFF.
     DISPLAY "TOTAL PHP" ROUNDOFF.
     DISPLAY "GO BACK TO MAIN MENU?:[Y/N] " 
             WITH NO ADVANCING.
     ACCEPT CHOICE.
     IF CHOICE = "Y"
         PERFORM MAIN-MENU
     ELSE IF CHOICE = "N"
         PERFORM SUMMARIES
     ELSE
         DISPLAY "INVALID CHOICE! GOING BACK TO MAIN MENU"
         PERFORM MAIN-MENU. 

  ADDTRANS. 
     DISPLAY ERASE.
     ADD 1 TO CURINDEX.
     DISPLAY "TRANSACTION NUMBER: " TRANSACNUM.
     MOVE TRANSACNUM TO TRANSAC(CURINDEX).
     ADD 1 TO TRANSACNUM. 
     DISPLAY "ENTER FOREIGN CURRENCY: " WITH NO ADVANCING.
     ACCEPT FORCUR.
     IF FORCUR = "USD"
        MOVE USD TO VALCUR
        DISPLAY "ENTER AMOUNT: $" WITH NO ADVANCING
        ACCEPT AMOUNT
     ELSE IF FORCUR = "AUS"
        MOVE AUS TO VALCUR
        DISPLAY "ENTER AMOUNT: $" WITH NO ADVANCING
        ACCEPT AMOUNT
     ELSE IF FORCUR = "CND"
        MOVE CND TO VALCUR
        DISPLAY "ENTER AMOUNT: $" WITH NO ADVANCING
        ACCEPT AMOUNT
     ELSE IF FORCUR = "EUR"
        MOVE EUR TO VALCUR
        DISPLAY "ENTER AMOUNT: E" WITH NO ADVANCING
        ACCEPT AMOUNT
     ELSE IF FORCUR = "YEN"
        MOVE YEN TO VALCUR
        DISPLAY "ENTER AMOUNT: Y" WITH NO ADVANCING
        ACCEPT AMOUNT
     ELSE IF FORCUR = "NZD"
        MOVE NZD TO VALCUR
        DISPLAY "ENTER AMOUNT: $" WITH NO ADVANCING
        ACCEPT AMOUNT
     ELSE IF FORCUR = "OMN"
        MOVE OMN TO VALCUR
        DISPLAY "ENTER AMOUNT: R" WITH NO ADVANCING
        ACCEPT AMOUNT
     ELSE IF FORCUR = "SGD"
        MOVE SGD TO VALCUR
        DISPLAY "ENTER AMOUNT: $" WITH NO ADVANCING
        ACCEPT AMOUNT
     ELSE
        DISPLAY "INVALID FOREIGN CURRENCY! PLEASE TRY AGAIN!" 
        SUBTRACT 1 FROM CURINDEX
        SUBTRACT 1 FROM TRANSACNUM
        PERFORM MAIN-MENU.
     MOVE FORCUR TO CURRENCIES(CURINDEX).
     MULTIPLY AMOUNT BY VALCUR GIVING AMOUNTARR(CURINDEX).
     MOVE AMOUNTARR(CURINDEX) TO ROUNDOFF.
     DISPLAY "PHP " ROUNDOFF.
     DISPLAY "ENTER ANOTHER TRANSACTION?:[Y/N] " 
             WITH NO ADVANCING.
     ACCEPT CHOICE.
     IF CHOICE = "Y"
         PERFORM ADDTRANS
     ELSE IF CHOICE = "N"
         PERFORM MAIN-MENU
     ELSE
         DISPLAY "INVALID CHOICE! GOING BACK TO MAIN MENU"
         PERFORM MAIN-MENU.

  UPDATES.
     DISPLAY ERASE.
     DISPLAY "ENTER FOREIGN CURRENCY: " WITH NO ADVANCING.
     ACCEPT FORCUR.
     IF FORCUR = "USD"
        MOVE USD TO ROUNDOFF
        DISPLAY "RECENT VALUE: " ROUNDOFF
        DISPLAY "RATE: $" WITH NO ADVANCING
        ACCEPT NEWVAL
        MOVE NEWVAL TO USD
     ELSE IF FORCUR = "AUS"
        MOVE AUS TO ROUNDOFF
        DISPLAY "RECENT VALUE: " ROUNDOFF
        DISPLAY "RATE: $" WITH NO ADVANCING
        ACCEPT NEWVAL
        MOVE NEWVAL TO AUS
     ELSE IF FORCUR = "CND"
        MOVE CND TO ROUNDOFF
        DISPLAY "RECENT VALUE: " ROUNDOFF
        DISPLAY "RATE: $" WITH NO ADVANCING
        ACCEPT NEWVAL
        MOVE NEWVAL TO CND
     ELSE IF FORCUR = "EUR"
        MOVE EUR TO ROUNDOFF
        DISPLAY "RECENT VALUE: " ROUNDOFF
        DISPLAY "RATE: E" WITH NO ADVANCING
        ACCEPT NEWVAL
        MOVE NEWVAL TO EUR
     ELSE IF FORCUR = "YEN"
        MOVE YEN TO ROUNDOFF
        DISPLAY "RECENT VALUE: " ROUNDOFF
        DISPLAY "RATE: Y" WITH NO ADVANCING
        ACCEPT NEWVAL
        MOVE NEWVAL TO YEN
     ELSE IF FORCUR = "NZD"
        MOVE NZD TO ROUNDOFF
        DISPLAY "RECENT VALUE: " ROUNDOFF
        DISPLAY "RATE: $" WITH NO ADVANCING
        ACCEPT NEWVAL
        MOVE NEWVAL TO NZD
     ELSE IF FORCUR = "OMN"
        MOVE OMN TO ROUNDOFF
        DISPLAY "RECENT VALUE: " ROUNDOFF
        DISPLAY "RATE: R" WITH NO ADVANCING
        ACCEPT NEWVAL
        MOVE NEWVAL TO OMN
     ELSE IF FORCUR = "SGD"
        MOVE SGD TO ROUNDOFF
        DISPLAY "RECENT VALUE: " ROUNDOFF
        DISPLAY "RATE: $" WITH NO ADVANCING
        ACCEPT NEWVAL
        MOVE NEWVAL TO SGD
     ELSE
        DISPLAY "INVALID FOREIGN CURRENCY! PLEASE TRY AGAIN!" 
        PERFORM MAIN-MENU.
     DISPLAY "--GO BACK TO MAIN MENU".
     PERFORM MAIN-MENU.

UPDATE: I managed to fix the changing of the value in an array but the addition is still wrong. I found out the problem. The last value in an array adds to itself.

SUMMARIES.
 DISPLAY ERASE.
 DISPLAY "SUMMARY".
 DISPLAY "TRANSACTION NUMBER   CURRENCY   AMOUNT".
 PERFORM WITH TEST AFTER VARYING CTR FROM 1 BY 1 
       UNTIL CTR = CURINDEX

         DISPLAY "          " TRANSAC(CTR) WITH NO ADVANCING
         DISPLAY "         " WITH NO ADVANCING
         DISPLAY CURRENCIES(CTR)WITH NO ADVANCING
         MOVE AMOUNTARR(CTR) TO ROUNDOFF
         DISPLAY "      " ROUNDOFF
 END-PERFORM.

 PERFORM WITH TEST AFTER VARYING CTR1 FROM 1 BY 1 
       UNTIL CTR1 = CURINDEX
             MOVE AMOUNTARR(CTR1) TO AMOUNTTOT(CTR1)
             ADD AMOUNTTOT(CTR1) TO AMOUNTTOT(CTR1)
 END-PERFORM.

回答1:


You can't use PERFORM how you are using it. A PERFORM cannot be in any way recursive.

Even if it could, this would be "spaghetti" code: you can't tell where you are in the program, unless you know where you came from at the time. You go from one tortuous wriggly route to another.

Another problem is that you are "falling through" all over the place. If you arrive at a paragraph from the line immediately preceding it, the paragraph will execute. This explains your apparently random additions.

The code in your program is probably about there, but you need to restructure it entirely. If you look through some of the answers to COBOL questions here, you'll see some sample code to you the general idea.

This should be something like your controlling structure:

 ACCEPT CHOICE
 PERFORM UNTIL CHOICE EQUAL TO "4"
     IF CHOICE = "1"
        PERFORM ADDTRANS
     ELSE IF CHOICE = "2"
        PERFORM UPDATES
     ELSE IF CHOICE = "3"
        PERFORM SUMMARIES 
     ELSE 
        DISPLAY "INVALID CHOICE! PLEASE TRY AGAIN!"
     END-IF
     END-IF
     END-IF
     ACCEPT CHOICE
 END-PERFORM

You should change the nested-IFs to EVALUATE and you should change the tests for literal values to 88s on the field, COBOL's condition-names.

You must restructure your program. At the moment, it is unworkable, unreliable, non-portable and not of any use. However, it is only the structure (probably) that is wrong. If you get a hold on how to structure a program, and how paragraphs can be fallen-through/GO TO'd (don't do it unless you don't see a way not to, with experience there is always a way not to)/PERFORMed.

There was a recent question for which the answer was "fall-through". Have a read of that: https://stackoverflow.com/a/32885852/1927206

Remember, although the structure is wrong, the code is salvageable. It is a common mistake that COBOL beginners make, so not a big problem. Good for learning. Try to look at examples here.



来源:https://stackoverflow.com/questions/32992863/cobol-adding-an-array

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!