Search code examples
iocobol

COBOL record not writing to text file


I'm trying to make a simple COBOL program that takes user inputs and writes them to a .txt file. My program successfully creates a .txt file, however, it fails to record any of the input, and for the life of me I can't figure out why. I want it to repeatedly take user input until specified not to and write that input to a text file.

This is what I have:

   ENVIRONMENT DIVISION.
   INPUT-OUTPUT SECTION.
   FILE-CONTROL.
       SELECT TEST-FILE
           ASSIGN TO "C:\Users\Patrick\Desktop\TESTFILE.TXT"
           ORGANIZATION IS LINE SEQUENTIAL.

   DATA DIVISION.
   FILE SECTION.
   FD  TEST-FILE.
   01  TEST-RECORD         PIC X(25).


   WORKING-STORAGE SECTION.
   01 CONT                 PIC A(1).
   01  TEST-DETAIL.
       05  ITEM-NUMBER      PIC 9(7).
       05  FILLER           PIC X(5) VALUE SPACES.
       05  ITEM-PRICE       PIC 9(4).

   PROCEDURE DIVISION.
   PROGRAM-CONTROL.
       PERFORM OPEN-FILE.
       PERFORM GET-RECORD UNTIL CONT = 'N'.
       PERFORM CLOSE-OUT-FILE.
       STOP RUN.

   OPEN-FILE.
       OPEN OUTPUT TEST-FILE.

   GET-RECORD.
       PERFORM PROMPT-USER.
       PERFORM WRITE-RECORD.
       PERFORM CHECK-NEXT-RECORD.

   PROMPT-USER.
       DISPLAY 'ENTER PART-NUMBER'.
           ACCEPT ITEM-NUMBER.
       DISPLAY 'ENTER ITEM-PRICE'.
           ACCEPT ITEM-PRICE.

   WRITE-RECORD.
       MOVE TEST-DETAIL TO TEST-RECORD.
       WRITE TEST-RECORD.

   CHECK-NEXT-RECORD.
       DISPLAY 'ENTER ANOTHER RECORD? Y/n'.
           ACCEPT CONT.
       IF CONT = 'n' THEN MOVE 'N' TO CONT.

   CLOSE-OUT-FILE.
       CLOSE TEST-FILE.

   PERFORM PROGRAM-CONTROL.

Another thing I notice, is that if I move WRITE-RECORD out of GET-RECORD and into PROGRAM-CONTROL, like so

   PROGRAM-CONTROL.
       PERFORM OPEN-FILE.
       PERFORM GET-RECORD UNTIL CONT = 'N'.
       PERFORM WRITE-RECORD.
       PERFORM CLOSE-OUT-FILE.
       STOP RUN.

Then it will write to the .txt file, however, it will only write the last entry inputted (as would be expected). I'm guessing this is an issue with scope, but I don't understand it. Where am I going wrong, and can it work how I have it set up, or does the WRITE call need to be part of the PROGRAM-CONTROL? If so, how do I recursively call only the PROMPT-USER, WRITE-RECORD and CHECK-NEXT-RECORD portions so it works?


Solution

  • Delete PERFORM PROGRAM-CONTROL. at the end of the program and it should do what you intended.

    As currently presented, the PERFORM PROGRAM-CONTROL statement is the last statement of CLOSE-OUT-FILE., not a separate procedure. This establishes an infinite recursive loop.

    After answering 'n', the file is closed, control is transferred to PROGRAM-CONTROL, the file is opened, then because CONT has a value of 'N', the file is closed, control is transferred to PROGRAM-CONTROL, the file is opened, then because CONT has a value of 'N', control is transferred to PROGRAM-CONTROL, and so on.

    Where am I going wrong, and can it work how I have it set up, or does the WRITE call need to be part of the PROGRAM-CONTROL?

    You used an unnecessary statement and, no, WRITE does not need to be part of the PROGRAM-CONTROL.

    If so, how do I recursively call only the PROMPT-USER, WRITE-RECORD and CHECK-NEXT-RECORD portions so it works?

    Standard COBOL warns against recursive procedures; such as, paragraph recursion. In this case, you only need remove that one statement.

    Recursion was added in COBOL 2002; however, the recursion was added to PROGRAMs marked as RECURSIVE and included for FUNCTIONs and METHODs, but no change was made for procedures, where its use is undefined.


    ISO/IEC 1989:2002, PERFORM statement, 14.8.27.3 General rules:

    11) The results of executing the following sequence of PERFORM statements are undefined and no exception condition is set to exist when the sequence is executed:
    a) a PERFORM statement is executed and has not yet terminated, then
    b) within the range of that PERFORM statement another PERFORM statement is executed, then
    c) the execution of the second PERFORM statement passes through the exit of the first PERFORM statement.
    NOTE Because this is undefined, the user should avoid such an execution sequence. On some implementations it causes stack overflows, on some it causes returns to unlikely places, and on others other actions can occur. Therefore, the results are unpredictable and are unlikely to be portable.