I have the code,
IDENTIFICATION DIVISION.
PROGRAM-ID. SAMPLE3.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT EMP-SALARY ASSIGN TO 'input.txt'
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD EMP-SALARY.
01 NEWFILE.
05 FS-EMPNO PIC 9(6).
05 FS-NAME PIC 9(4).
05 FILLER PIC X(63).
WORKING-STORAGE SECTION.
01 WS-EOF PIC A(1) VALUE "N".
PROCEDURE DIVISION.
MAIN-PARA.
OPEN I-O EMP-SALARY
PERFORM READ-PARA THRU READ-PARA-EXIT UNTIL WS-EOF="Y"
STOP RUN.
MAIN-PARA-EXIT.
EXIT.
READ-PARA.
READ EMP-SALARY
AT END
MOVE "Y" TO WS-EOF
NOT AT END
IF FS-EMPNO > 10000
MOVE '1000' TO FS-NAME
REWRITE NEWFILE
DISPLAY " RECORD " NEWFILE
END-IF
END-READ.
READ-PARA-EXIT.
EXIT.
I got the error read statement should be executed first Status=43, and implicit close of file.
This program is to rewrite a record in a file. what is the reason for this error.
It is best to include FILE STATUS processing for any files you use in a program, and always test the value after an IO.
If that is the code you are running, you must have an OPEN failing, a READ failing, and the REWRITE deciding that it just can't go on. Check that it is the code that you are running.
Can you show the version of GnuCOBOL you are running, and the OS you are running on, include the FILE STATUS in your program and test the values, and also include an explicit CLOSE of your file, which is always good practice.
See if structuring your program like this simplifies:
PROCEDURE DIVISION.
OPEN I-O EMP-SALARY
* do file status checking here
PERFORM READ-PARA
PERFORM PROCESS-PARA UNTIL END-OF-INPUT-FILE
* END-OF-INPUT-FILE (make the name relevant to your file) is an 88 on the FILE STATUS
* filed for that file
* close the file
* do file status checking here
STOP RUN
.
READ-PARA.
READ EMP-SALARY
* do file status checking here
PROCESS-PARA.
IF FS-EMPNO > 10000
MOVE '1000' TO FS-NAME
PERFORM UPDATE-RECORD
END-IF
PERFORM READ-PARA
.
UPDATE-RECORD.
REWRITE NEWFILE
* do file status checking here
DISPLAY " RECORD " NEWFILE
.
Related
I have the following Gnu Cobol code:
IDENTIFICATION DIVISION.
PROGRAM-ID. INCOME-TAX-CALCULATOR.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT EMPLOYEE-FILE
ASSIGN TO "employees.csv"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD EMPLOYEE-FILE.
01 EMPLOYEE-RECORD.
02 EMP-ID PIC 9(5).
02 EMP-NAME PIC X(30).
02 EMP-SALARY PIC 9(7).
02 EMP-TAX PIC 9(5).
WORKING-STORAGE SECTION.
01 WS-TAX-RATE PIC 9(4)V99 VALUE 20.
PROCEDURE DIVISION.
OPEN INPUT EMPLOYEE-FILE
PERFORM UNTIL EOF
READ EMPLOYEE-FILE
AT END SET EOF TO TRUE
END-READ
COMPUTE EMP-TAX = EMP-SALARY * WS-TAX-RATE
DISPLAY EMP-ID, EMP-NAME, EMP-SALARY, EMP-TAX
END-PERFORM
CLOSE EMPLOYEE-FILE
STOP RUN.
in GnuCobol 3.1.2.0 I get the following error:
programName:25: error: 'EOF' is not defined
I have seen similar questions but END PROGRAM does not help.
I use the compiler with the free format like this: cobc -x -F -o programName programName.cbl
You've missed a definition for that EOF, so it is... undefined.
adding a definition like the following in WORKING-STORAGE-SECTION would solve that:
01 FILLER PIC X VALUE ' '.
88 EOF VALUE 'E'.
but you'd likely define a "NOT-EOF" or similar and set it before that loop, or, even better get rid of it completely:
PERFORM UNTIL EXIT
READ EMPLOYEE-FILE
AT END EXIT PERFORM
END-READ
COMPUTE EMP-TAX = EMP-SALARY * WS-TAX-RATE
DISPLAY EMP-ID, EMP-NAME, EMP-SALARY, EMP-TAX
END-PERFORM
... but you'd likely still want to add checks for "did the OPEN work", but that's a different question, if at all.
There is a better way to do this:
perform until exit
read employee-file
at end
exit perform
not at end
COMPUTE EMP-TAX = EMP-SALARY * WS-TAX-RATE
DISPLAY EMP-ID, EMP-NAME, EMP-SALARY, EMP-TAX
end-read
end-perform
I always do my reads this way, there is no need for an EOF flag. Even better, break out the not at end stuff into a paragraph and perform that:
perform until exit
read employee-file
at end
exit perform
not at end
perform compute-and-display
end-read
end-perform
close employee-file
goback
.
compute-and-display.
COMPUTE EMP-TAX = EMP-SALARY * WS-TAX-RATE
DISPLAY EMP-ID, EMP-NAME, EMP-SALARY, EMP-TAX
exit paragraph
.
The exit paragraph is not needed but I like to use it just to make my intent clear that it is an explicit "return". Also, if you are using GnuCobol, you can just use lower case.
This is CICS COBOL Program :-
IDENTIFICATION DIVISION.
PROGRAM-ID. ELECPRG.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT INFL ASSIGN TO INFLDD
ORGANIZATION IS LINE SEQUENTIAL
ACCESS MODE IS SEQUENTIAL
FILE STATUS IS FS.
DATA DIVISION.
FILE SECTION.
FD INFL.
01 ELEC-REC.
05 P-NUM PIC X(5).
05 FILLER PIC X(1).
05 C-NAME PIC X(10).
05 FILLER PIC X(1).
05 C-UNIT PIC X(4).
WORKING-STORAGE SECTION.
COPY ELECMAP.
01 WS-MSG PIC X(20) VALUE 'BILL PROD DB UPDATE'.
01 FS PIC 9(2).
PROCEDURE DIVISION.
000-MAIN.
MOVE LOW-VALUES TO ELBILLI, ELBILLO
PERFORM 100-SEND-MAP.
PERFORM 200-RECEIVE-MAP.
PERFORM PROCESS-DATA.
PERFORM FILE-FUNC.
PERFORM 100-SEND-MAP.
PERFORM 300-RETURN.
STOP RUN.
100-SEND-MAP.
EXEC CICS
SEND
MAP('ELBILL') MAPSET('ELECMAP')
ERASE
END-EXEC.
200-RECEIVE-MAP.
EXEC CICS
RECEIVE
MAP('ELBILL') MAPSET('ELECMAP')
END-EXEC.
PROCESS-DATA.
MOVE CUSNOI TO CUSNOO.
MOVE NAMEI TO NAMEO.
MOVE UNITSI TO UNITSO.
MOVE UNITSI TO BILLO.
MOVE WS-MSG TO MSGO.
FILE-FUNC.
OPEN OUTPUT INFL.
DISPLAY 'OPEN FILE STATUS IS' FS.
MOVE CUSNOI TO P-NUM.
MOVE NAMEI TO C-NAME.
MOVE UNITSI TO C-UNIT.
WRITE ELEC-REC.
DISPLAY 'WRITE FILE STATUS IS' FS.
CLOSE INFL.
DISPLAY 'CLOSE FILE STATUS IS' FS.
300-RETURN.
EXEC CICS
RETURN
END-EXEC.
Mine compile jcl :-
//CICSCOB JOB CLASS=A,MSGCLASS=A,NOTIFY=&SYSUID,MSGLEVEL=(1,1)
//PROCLIB JCLLIB ORDER=DFH320.CICS.SDFHPROC
//STEP01 EXEC PROC=DFHYITVL,
// INDEX='DFH320.CICS',
// AD370HLQ='IGY410',
// LE370HLQ='CEE',
// PROGLIB='DFH320.CICS.SDFHLOAD',
// DSCTLIB='DFH320.CICS.SDFHMAC'
//TRN.SYSIN DD DISP=SHR,DSN=RAHUL.COBOL.PROGRAM(ELECPRG)
//INFLDD DD DSN=RAHUL.CICS.OUTPUT,DISP=SHR
//LKED.SYSIN DD *
NAME ELECPRG(R)
/*
Compilation complete a condition code = 0004 , few warnings.
But when I execute the transaction in CICS it terminates with CICS Transaction ELEC failed with abend U4038.
I don't understand the nature of this abend. I just want to update dataset RAHUL.CICS.OUTPUT from my CICS screen input. provided the output file location. Without the file use program is working fine , no abend occurs.
This program is a combination of COBOL file control commands and CICS SEND / RECEIVE MAP commands. COBOL file commands such as OPEN, READ, WRITE and CLOSE are not supported in a CICS transaction.
In a CICS program you have to use the CICS API as documented here https://www.ibm.com/docs/en/cics-ts/5.5?topic=programs-understanding-file-control
I have a COBOL program that requires a transaction number every run of the program. I am planning to get the last transaction number from the file and add 1 to it. The problem is I don't know how to get the last recorded value.
IDENTIFICATION DIVISION.
PROGRAM-ID. INVENTORY-SYS.
AUTHOR. LINSEY.
DATE-WRITTEN. 2/22/2015.
DATE-COMPILED. 2/22/2015.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT MASTER-FILE ASSIGN TO "inventory-file.txt"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD MASTER-FILE.
01 IN-RECORDS.
02 IN-CODE PIC 9(7).
02 IN-NAME PIC X(30).
02 IN-PRICE PIC 9(3).
02 IN-STOCK PIC 9(4).
WORKING-STORAGE SECTION.
01 WS-EOF PIC A(1).
PROCEDURE DIVISION.
100-READ-FILE.
OPEN I-O MASTER-FILE.
PERFORM UNTIL WS-EOF = "Y"
READ MASTER-FILE
AT END
MOVE 'Y' TO WS-EOF
NOT AT END
DISPLAY IN-RECORDS
END-READ
END-PERFORM
CLOSE MASTER-FILE.
STOP RUN.
This is the sample program. The problem is it retrieves all the records from the file I only the last record from "inventory-file.txt"
Well, you are insistent, so:
IDENTIFICATION DIVISION.
PROGRAM-ID. INVENTORY-SYS.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT MASTER-FILE ASSIGN TO "inventory-file.txt"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS w-if-in-file-status.
DATA DIVISION.
FILE SECTION.
FD MASTER-FILE.
01 IN-RECORDS.
02 IN-CODE PIC 9(7).
02 IN-NAME PIC X(30).
02 IN-PRICE PIC 9(3).
02 IN-STOCK PIC 9(4).
WORKING-STORAGE SECTION.
01 w-if-in-file-status PIC XX.
88 master-file-status-good VALUE ZERO "10".
88 end-of-master-file VALUE "10".
01 w-save-code PIC 9(7).
PROCEDURE DIVISION.
OPEN INPUT MASTER-FILE
[code to check FILE STATUS field]
PERFORM UNTIL end-of-master-file
READ MASTER-FILE
[code to check FILE STATUS field]
MOVE IN-CODE to w-save-code
END-PERFORM
DISPLAY ">" w-save-code "<"
CLOSE MASTER-FILE
[code to check FILE STATUS field]
GOBACK
.
I don't know why your IN-CODE field is numeric. Are you going to do calculations with it?
You keep a Control File. That has a date (to match to the Business Date file) a logical file-name, an environment and the last transaction number.
You maintain that file, checking everything as you do so.
I'm not sure of OpenCobol supports it, but you might try using OPEN/REVERSED. It is an old school way of reading a tape backwards, or these days, a virtual tape. I've no idea if it is implemented, but it is an easy way to read a sequential file backwards.
IDENTIFICATION DIVISION.
PROGRAM-ID. PROGRAM1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT EMP-GRADE ASSIGN TO 'input.txt'
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL
FILE STATUS IS WS-STATUS.
DATA DIVISION.
FILE SECTION.
FD EMP-GRADE.
01 NEWFILE.
05 FS-EMPID PIC 9(5).
05 FS-NAME PIC A(5).
05 FS-STREAM PIC X(5).
05 FS-GRADE PIC A(1).
05 FILLER PIC X(64).
WORKING-STORAGE SECTION.
01 WS-EOF PIC A(1) VALUE "N".
01 WS-STATUS PIC X(2).
PROCEDURE DIVISION.
MAIN-PARA.
OPEN INPUT EMP-GRADE.
PERFORM PARA1 THRU PARA1-EXIT UNTIL WS-EOF="Y".
CLOSE EMP-GRADE.
STOP RUN.
MAIN-PARA-EXIT.
EXIT.
PARA1.
READ EMP-GRADE
AT END MOVE "Y" TO WS-EOF
NOT AT END
IF FS-GRADE='A'
DISPLAY FS-EMPID , FS-NAME , FS-STREAM , FS-GRADE
END-IF
END-READ.
PARA1-EXIT.
EXIT.
input provided:
1234 sita comp A
2345 tina main B
5689 riya math A
but the output is coming :
1234 sita comp A
It is reading only the first record.
As Brian Tiffin is hinting at in the comments, it is your data which is the problem.
This:
05 FILLER PIC X(64).
Means that your records should be 64 bytes longer than they are.
If you have a fixed-length record, or only fixed-length records, under an FD, then the data all have to be the same length, and equal to what you have defined in your program.
It means, and behaviour depends on compiler, you only have one record as far as the COBOL program is concerned.
A good way to spot such things is to always count your input records, and count your output records, and records which should not be selected for output. You can then easily tell if anything has fallen between a crack.
Leaving that aside, here's your program with some adjustments:
IDENTIFICATION DIVISION.
PROGRAM-ID. PROGRAM1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT EMP-GRADE ASSIGN TO 'input.txt'
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL
FILE STATUS IS WS-STUDENT-GRADE-STATUS.
DATA DIVISION.
FILE SECTION.
FD EMP-GRADE.
01 NEWFILE.
05 FS-EMPID PIC 9(5).
05 FS-NAME PIC X(5).
05 FS-STREAM PIC X(5).
05 FS-GRADE PIC X(1).
05 FILLER PIC X(64).
WORKING-STORAGE SECTION.
01 WS-STUDENT-GRADE-STATUS PIC X(2).
88 END-OF-STUDENT-GRADE-FILE VALUE "10".
88 ERROR-ON-STUDENT-GRADE-FILE VALUE ZERO.
PROCEDURE DIVISION.
OPEN INPUT EMP-GRADE
* perform a paragraph to check FILE STATUS field is zero, using an 88.
PERFORM PRIMING-READ
PERFORM PROCESS-STUDENT-GRADE-FILE
UNTIL END-OF-STUDENT-GRADE-FILE
CLOSE EMP-GRADE
* perform a paragraph to check FILE STATUS field is zero, using an 88.
GOBACK
.
PRIMING-READ.
PERFORM READ-STUDENT-GRADE
.
READ-STUDENT-GRADE.
READ EMP-GRADE
* perform a paragraph to check FILE STATUS field is zero, using an 88.
.
PROCESS-STUDENT-GRADE-FILE.
IF FS-GRADE='A'
* To see the problem with your data, DISPLAY the 01-level
DISPLAY NEWFILE
DISPLAY FS-EMPID
FS-NAME
FS-STREAM FS-GRADE
END-IF
PERFORM READ-STUDENT-GRADE
.
If you use the FILE STATUS field, you should check it. Since you use it, you can use it to check for end-of-file without the AT END. If you use a "priming read" you don't need the AT END/NOT AT END tangle. If you code the minimum of full-stops/periods in the PROCEDURE DIVISION, you won't have a problem with them. Commas are never needed, so don't use them. Format your program for human readability. Use good descriptive names for everything. The THRU on a PERFORM invites the use of GO TO. As a learning, avoid the invitation.
If your class itself enforces particular ways to code COBOL, you'll have to use those ways. If so, I'd suggest you do both. The first couple of times at least, submit both to your tutor. Even if they tell you not to do that, continue doing dual examples when given tasks (just don't submit them any more). There is no reason for you to start off with bad habits.
Keep everything simple. If your code looks bad, make it look good through simplification and formatting.
Remember also that COBOL is all about fixed-length stuff. Get's us back to your original problem.
I recently got an assignment to use the "EXTEND OPEN" command to add data to an already existing file. While I thought I understood what it did I find that my program is hitting a snag, giving me this error: "148 Wrong open mode or access mode for write". It is a simple program, meant to only add one new file of entries to a master file, but I can't quite get it. Here is what I have:
DATA DIVISION.
FILE SECTION.
FD OLD-MASTER-IN.
01 OLD-MASTER-REC-IN.
05 O-STATE-ABREV-IN PIC XX.
05 PIC X.
05 O-STATE-NAME-IN PIC X(17).
FD TRANS-FILE-IN.
01 TRANS-REC-IN.
05 N-STATE-ABREV-IN PIC XX.
05 PIC X.
05 N-STATE-NAME-IN PIC X(17).
WORKING-STORAGE SECTION.
01 ARE-THERE-MORE-RECORDS PIC X(3) VALUE 'YES'.
PROCEDURE DIVISION.
100-MAIN.
OPEN INPUT OLD-MASTER-IN
EXTEND TRANS-FILE-IN
PERFORM UNTIL ARE-THERE-MORE-RECORDS = 'NO '
READ OLD-MASTER-IN
AT END
MOVE 'NO' TO ARE-THERE-MORE-RECORDS
NOT AT END
PERFORM 200-REGULAR-UPDATE
END-READ
END-PERFORM
CLOSE OLD-MASTER-IN
TRANS-FILE-IN
STOP RUN.
200-REGULAR-UPDATE.
WRITE OLD-MASTER-REC-IN FROM TRANS-REC-IN.
Any Help will be appreciated.
I figured it out. I really stupid now. Seems I extended/read the wrong file. Silly me. The code is suppose to look like this:
PROCEDURE DIVISION.
100-MAIN.
OPEN INPUT TRANS-FILE-IN
EXTEND OLD-MASTER-IN
PERFORM UNTIL ARE-THERE-MORE-RECORDS = 'NO '
READ TRANS-FILE-IN
AT END
MOVE 'NO' TO ARE-THERE-MORE-RECORDS
NOT AT END
PERFORM 200-REGULAR-UPDATE
END-READ
END-PERFORM
CLOSE TRANS-FILE-IN
OLD-MASTER-IN
STOP RUN.
200-REGULAR-UPDATE.
WRITE OLD-MASTER-REC-IN FROM TRANS-REC-IN.
If you are writing with a modern compiler your code could be written to not look like it was written in the 70's.
Here is an example of what you could do:
OPEN INPUT TRANS-FILE-IN
OPEN EXTENT OLD-MASTER-IN
PERFORM UNTIL EXIT
READ TRANS-FILE-IN
AT END
EXIT PERFORM
END-READ
WRITE OLD-MASTER-REC-IN FROM TRANS-REC-IN
END-PERFORM
CLOSE TRANS-FILE-IN
CLOSE OLD-MASTER-IN
Of course, there is no error checking in here but that is a large topic.