user3556888
user3556888

Reputation: 11

Bad syntax with my loop, but not throwing an error in COBOL

I guess i messed the switch up when i was messing with it trying to figure out why it woulden't work. It only reads the first line of my data, then ends. ( it prints headers, first line of data, all the calculations that are in 300-process-records, and does the final heading for ending the report.

       FILE-CONTROL.
       SELECT F01-INPUT-FILE ASSIGN TO 'I:\COBOL\EmployeePay.dat'
                               ORGANIZATION IS LINE SEQUENTIAL.

       SELECT F02-PRINT-FILE ASSIGN TO 'I:\COBOL\EmployeePay.out'
                               ORGANIZATION IS LINE SEQUENTIAL.

   DATA DIVISION.
   FILE SECTION.

   FD  F01-INPUT-FILE
       RECORD CONTAINS 30 CHARACTERS
       DATA RECORD IS F01-INPUT-RECORD.

   01  F01-INPUT-RECORD.
       05 F01-EMPLOYEE-NAME        PIC X(18).
       05 F01-EMPLOYEE-SSN         PIC 9(9).
       05 F01-GROSS-PAY            PIC 9(3).

   FD  F02-PRINT-FILE
       RECORD CONTAINS 86 CHARACTERS
       DATA RECORD IS F02-PRINT-LINE-RECORD.
   01  F02-PRINT-LINE-RECORD       PIC X(86).

   WORKING-STORAGE SECTION.

   01  W01-DATA-REMAINS-SWITCH     PIC X VALUE 'Y'.

   01  W02-DETAIL-LINE.
       05                          PIC X(2) VALUE SPACES.
       05 W02-EMPLOYEE-NAME        PIC X(18).
       05                          PIC X(2) VALUE SPACES.
       05 W02-EMPLOYEE-SSN         PIC 9(9).
       05                          PIC X(7) VALUE SPACES.
       05 W02-PAY-100S             PIC 9.
       05                          PIC X(5) VALUE SPACES.
       05 W02-PAY-50S              PIC 9.
       05                          PIC X(4) VALUE SPACES.
       05 W02-PAY-20S              PIC 9.
       05                          PIC X(4) VALUE SPACES.
       05 W02-PAY-10S              PIC 9.
       05                          PIC X(4) VALUE SPACES.
       05 W02-PAY-5S               PIC 9.
       05                          PIC X(4) VALUE SPACES.
       05 W02-PAY-1S               PIC 9.
       05                          PIC X(3) VALUE SPACES.
       05 W02-GROSS-PAY            PIC 9(3).
       05                          PIC X(15).

   01 W02-HEADER-LINE1.
       05                          PIC X(22) VALUE SPACES.
       05                 PIC X(24) VALUE SPACES.
       05                          PIC X(40) VALUE SPACES.

   01 W02-HEADER-LINE2.
       05                          PIC X(2) VALUE SPACES.
       05                          PIC X(13) VALUE 'EMPLOYEE NAME'.
       05                          PIC X(20) VALUE SPACES.
       05                          PIC X(4) VALUE '$100'.
       05                          PIC X(3) VALUE SPACES.
       05                          PIC X(3) VALUE '$50'.
       05                          PIC X(2) VALUE SPACES.
       05                          PIC X(3) VALUE '$20'.
       05                          PIC X(2) VALUE SPACES.
       05                          PIC X(3) VALUE '$10'.
       05                          PIC X(3) VALUE SPACES.
       05                          PIC X(2) VALUE '$5'.
       05                          PIC X(3) VALUE SPACES.
       05                          PIC X(2) VALUE '$1'.
       05                          PIC X(3) VALUE SPACES.
       05                          PIC X(3) VALUE 'PAY'.
       05                          PIC X(15) VALUE SPACES.

   01 W02-CLOSING-LINE.
       05                          PIC X(13) VALUE 'End Of Report'.
       05                          PIC X(73) VALUE SPACES.

   01 PAY                          PIC 999V99.

   PROCEDURE DIVISION.

   PERFORM 100-OPEN-FILES.
   PERFORM 200-WRITE-HEADING-LINES.
   PERFORM 300-PROCESS-RECORDS
       UNTIL W01-DATA-REMAINS-SWITCH = 'N'.
   PERFORM 400-WRITE-FOOTER.
   PERFORM 500-CLOSE-FILES.

   100-OPEN-FILES.
       OPEN INPUT F01-INPUT-FILE
       OUTPUT F02-PRINT-FILE
   READ F01-INPUT-FILE
       AT END MOVE "N" TO W01-DATA-REMAINS-SWITCH
       .

   200-WRITE-HEADING-LINES.
       MOVE W02-HEADER-LINE1 TO F02-PRINT-LINE-RECORD.
       WRITE F02-PRINT-LINE-RECORD.
       MOVE W02-HEADER-LINE2 TO F02-PRINT-LINE-RECORD.
       WRITE F02-PRINT-LINE-RECORD.


   300-PROCESS-RECORDS.           

       MOVE F01-EMPLOYEE-NAME TO W02-EMPLOYEE-NAME.
       MOVE F01-EMPLOYEE-SSN TO W02-EMPLOYEE-SSN.
       MOVE F01-GROSS-PAY TO W02-GROSS-PAY.

       PERFORM 310-DO-CALCULATIONS.

       MOVE W02-DETAIL-LINE TO F02-PRINT-LINE-RECORD.
       WRITE F02-PRINT-LINE-RECORD.
   READ F01-INPUT-FILE
       AT END MOVE 'N' TO W01-DATA-REMAINS-SWITCH
       END-READ.

   310-DO-CALCULATIONS.
       COMPUTE W02-PAY-100S = W02-GROSS-PAY / 100
       COMPUTE PAY = W02-GROSS-PAY - (W02-PAY-100S * 100)                                                        
       COMPUTE W02-PAY-50S = PAY / 50
       COMPUTE PAY = PAY - ( W02-PAY-50S * 50)
       COMPUTE W02-PAY-20S = PAY / 20
       COMPUTE PAY = PAY - ( W02-PAY-20S * 20)
       COMPUTE W02-PAY-10S = PAY / 10
       COMPUTE PAY = PAY - ( W02-PAY-50S * 10)
       COMPUTE W02-PAY-5S = PAY / 5
       COMPUTE PAY = PAY - ( W02-PAY-5S * 5)
       COMPUTE W02-PAY-1S = PAY / 1
       .

   400-WRITE-FOOTER.

       MOVE W02-CLOSING-LINE TO F02-PRINT-LINE-RECORD.
       WRITE F02-PRINT-LINE-RECORD.


   500-CLOSE-FILES.   
       CLOSE F01-INPUT-FILE
             F02-PRINT-FILE.

The computes had to be there, i understood the usage it was just a math thing that i was stuck on, theyre working now. =)

So maybe i misunderstood your answer, but fixing it didnt change anything. It still only returns with one line of data from the file and ends.

Upvotes: 1

Views: 395

Answers (2)

Bill Woodger
Bill Woodger

Reputation: 13076

You're suffering from "drop-through" or "fall-through".

I'll go into that shortly, but first a few other things.

Your title: Bad syntax with my loop, but not throwing an error in COBOL. My advice for questions is two write the title last, then you are more likely to avoid this problem. There is no "syntax" issue and nothing for the compiler to assist you with.

Secondly, your problem description: "Having some trouble with my read loop, it will not continue through the loop."

The meaning of that is unclear. We read one meaning into it (the loop does not get entered at all) and you meant another (one record only, the first on the file, appears in the output).

The importance of this is as follows: if the explanation of the existing code does not exactly obtain the output achieved, then that is certainly not a full explanation of the problem: don't change a line of code until you know the full explanation.

Well, OK, but often you want to make some change to aid problem determination, or just to poke about in the hope that some magic will happen and the problem will be fixed. Well, don't do it to the original program. Copy the program. We don't want to be pointing out the side-effects of the bodges and hacks you've attempted, if you want to do that.

On our reading, the Y/Y and N/N problem explained what (we thought) you were getting. However, it does not explain the actual output. How would we know that? You haven't included any output.

Sometimes the problem is an "empty" file, or a file with only one record, or indeed a "corrupt" file (tip it a fiver and it'll take a dive in the third). How, other than their being unlikely, do we exclude those if you don't include sample data?

Then we need to see the code that isn't working. However, if you knew what it was that wasn't working, most likely you'd get to the answer. So, you have to do your best to pare down the code to the smallest amount which still exhibits the problem.

So, a good title, finalised once the question is complete; accurate problem statement; sample input data, actual output, expected output; error messages (in full, with error-codes) if any; minimal sample code which produces the problem.

Often, in the good preparation of a good question you'll get to the answer yourself anyway, before you even need to ask.

A good way is to explain your problem to someone else. Reading and speaking you will read more than simply reading (to yourself) and assuming. Even if you have no colleague/friend available, just pretend you have a Cardboad-Cutout Programmer (can be an inflatable one, like the autopilot always is in comedy films), or an egg-cup, or a rubber-duck (apparently this one works as well).

Oh, and I'll update my answer on your other question.

So, the "fall-through" or "drop-through".

    MOVE X                      TO Y
    .
some-paragraph-name.
    MOVE A                      TO B
    ...

There you see a paragraph name. How does control pass to the line immediately after the paragraph name? There are three valid, legal and usable ways for ordinary code (non-Declaratives, non-SORT-procedure): after MOVE X is executed, if the code is not within a PERFORM whose range finishes at "some-paragraph-name" then the MOVE A will be next; a GO TO some-paragraph-name; a PERFORM (in some variation) of some-paragraph-name.

(Note, what applies to paragraphs above applies equally to SECTIONs in the PROCEDURE DIVISION).

This is not like many other languages where a "function" or a "sub-routine" would be "protected" from the main flow of code, they could not be "fallen into" or GO TO'd.

In COBOL, all three methods of getting there are entirely valid, and entirely valid even for the same paragraph-name in the same program (valid doesn't, of course, mean good practice: good practice would preclude such use).

Since all methods are entirely valid, the compiler has nothing to say when you use one of the methods, even when its use was unintended (how would the compiler know that?).

Here's your problem:

PERFORM 500-CLOSE-FILES.

100-OPEN-FILES.

I've highlighted the line, unfortunately since there is nothing on the line it doesn't show up.

    PERFORM 500-CLOSE-FILES
    GOBACK (or STOP RUN, or EXIT PROGRAM, but GOBACK is better)
    .
100-OPEN-FILES.

So, your program was running, processing the entire input file a record at a time, writing the data to the output file, a record at a time. All approximately OK.

Then you closed the files.

Then you dropped through to 100-OPEN-FILES, and BANG! your output is wiped. Then it does the first read. Then does 300-, just the once, so processing one record before reading the next, then drops into 310-, then 400-, then 500- which closes the files and falls off the end of the program, bringing execution to a halt.

Depending on compiler, actually, there should have been at least one termination statement in the program and a failure on falling off the program. However, the compiler you are using doesn't do that (or you've told it not to do it with options/switches).

Add the GOBACK/STOP RUN/EXIT PROGRAM and your program will work. Generally.

How could you have spotted this yourself? Counting the input and output records and DISPLAYing the totals at the end of the program often helps. If you use the FILE STATUS you get less suspicious of it being a dodgy file. Good formatting, use of 88s, as Bruce already suggested.

Upvotes: 3

Bruce Martin
Bruce Martin

Reputation: 10553

Two obvious problems:

  1. The read statements2. look to be in the wrong columns
  2. The no loop statement
  3. You need to set W01-DATA-REMAINS-SWITCH to Y before you start

Try

100-OPEN-FILES.
   OPEN INPUT F01-INPUT-FILE
   OUTPUT F02-PRINT-FILE
   READ F01-INPUT-FILE
      AT END MOVE "N" TO W01-DATA-REMAINS-SWITCH
   end-Read

   PERFORM UNTIL W01-DATA-REMAINS-SWITCH = "N"

       ....

       READ F01-INPUT-FILE
          AT END MOVE "N" TO W01-DATA-REMAINS-SWITCH
       end-read
  end-perform

Also

  1. Look up 88 levels and the set verb e.g.

    SET EOF            to true
    
  2. Find more out how cobol should be formatted

Upvotes: 0

Related Questions