I have FD
FD CR1
LABEL RECORD IS STANDARD
DATA RECORDS ARE FIRSTSTR, SECONDSTR, THIRDSTR.
and 3 structures
01 FIRSTSTR.
05 FIRSTFIVE PIC X(05).
05 SECONDFIVE PIC X(05).
01 SECONDSTR.
05 FIRSTTWO PIC X(02).
05 SECONDONE PIC X(01).
05 THIRDFOUR PIC X(04).
01 THIRDSTR.
05 FIRSTTHREE PIC X(03).
05 SECONDTHREE PIC X(03).
05 THIRDTHREE PIC X(03).
Can I write all info in file like this:
WRITE FIRSTSTR, SECONDSTR, THIRDSTR.
And read from file in 3 structures like this:
READ CR1 INTO FIRSTSTR, SECONDSTR, THIRDSTR AT END
Yes, you can write more than one type of record to a file, but no, you can't do it the way you want to.
The record-definitions (structures) under the FD all occupy the same storage, meaning the all the 01-levels start at the same byte address. The individual records cannot simultaneously contain different data.
This is called an "implicit REDEFINES".
The READ ... INTO ... is to read and at the same time copy the current record to the INTO item (singular) that you specify. The INTO item would usually be in the WORKING-STORAGE (although they could also be in LOCAL-STORAGE). It would be exotic to use the LINKAGE SECTION and very, very, odd to use something in the FILE SECTION as a target for a READ ... INTO....
You only READ one record at a time. Unless you file has a set, fixed-in-stone, sequence of different records, we'd usually READ the file, identify the record, and then process that particular type of record.
You can only specify one receiving item for READ ... INTO ... and only one source item for WRITE ... FROM ....
Related
I am using CopybookInputFormat on git https://github.com/tmalaska/CopybookInputFormat/ to generate hive table definition from COBOL copybook. My copybook has many Fillers (duplicate columns)
but it looks like JRecord is not handling duplicate column name correctly.
For below copybook, when I iterate columns, JRecord only prints second Filler and ignores first filler.
05 Birth-day PIC X(002)
05 Filler PIC X(008)
05 Birth-Month PIC X(002)
05 Filler PIC X(008)
05 Birth-year PIC X(004)
Does anyone have any solution for this? I know JRecord 0.80.6 onward is handling duplicate columns, but method getUniqueField("FIRST-NAME", "PRESIDENT") needs a group name.. but what if group has duplicate columns?
You should not need to import a Filler. In Cobol, a Filler can not be directly accessed. In Cobol a Filler say's Ignore this Field (or access it by another method).
A Cobol-Copybook is like a mask over a block of memory; A filler is used to skip some memory.
Data !##........##........## (# - accessible bytes; . - inaccessible bytes)
^ ^ ^
! ! !
Birth-day ---+ ! !
Filler ! !
Birth-Month -------------+ !
Filler !
Birth-year -----------------------+
A filler can be used to:
Mask fields that are no longer used.
Used mask data in a redefines
Create a simplified version of a copybook when you do not need all the fields
Initializing an output field i.e
05 report-Birth-date
10 dd pic 99.
10 filler pic '/'.
10 mm pic 99.
10 filler pic '/'.
10 yyyy pic 9999.
setting up Table data
05 codes.
10 code occurs 5 pic 99.
05 filler redefines codes pic x(10)
value '0204050612'.
I would ask the Cobol specialists where you work what is going on ???. Possible answers could be:
The filler data may not be needed.
You should be using a different more complicated Copybook.
The copybook should be updated with the Fillers given real names.
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.
the format of input file is like this:
Region ******* Company Name
A
B
C
A
C
with many lines.
I need to get a output file to rearrange the file with headers like this:
Company in Region A:
name
name
name...
Company in Region B:
name
name
name..
Company in Region C:
name
name
name..
My question is because the region in input file is not ordered. How can I add the second Region A company back in the header "Company in Region A"? I can only read the file one time (I cannot first all do lines with region A then reopen the file to read again). And I can only have 1 output file.
You could use the Sort verb with input/output procedure to sort the file into Region Sequence.
You can find many examples in Google. This ShorExample has a short Sort example,
there is more info here
You will probably need both input and output procedures
Sort Example:
PROCEDURE DIVISION.
000-SORT SECTION.
010-DO-THE-SORT.
SORT SORT-FILE ON ASCENDING KEY SORT-KEY-1
ON DESCENDING KEY SORT-KEY-2
USING INPUT-FILE
OUTPUT PROCEDURE IS 200-WRITE-OUTPUT
THRU 230-DONE-OUTPUT.
DISPLAY "END OF SORT".
STOP RUN.
200-WRITE-OUTPUT SECTION.
210-OPEN-OUTPUT.
OPEN OUTPUT OUTPUT-FILE.
220-GET-SORTED-RECORDS.
RETURN SORT-FILE AT END
CLOSE OUTPUT-FILE
GO TO 230-DONE-OUTPUT.
MOVE SORT-RECORD TO OUTPUT-RECORD.
WRITE OUTPUT-RECORD.
GO TO 220-GET-SORTED-RECORDS.
230-DONE-OUTPUT SECTION.
240-EXIT-OUTPUT.
EXIT.
If you are doing homework, remember that the goal of homework is not to solve a problem, it is to demonstrate that you have learned the class material. So, if this is homework, create your own solution based on what you have been taught. If you are trying to solve a real-life problem, the example below might help point you in the right direction. If you have not been taught sorting using an output procedure, you do not want to use the example below to do your homework. That said, the following program works using the sample data shown with GNUCobol. Notice in particular how paragraph OUTPUT-CO-BY-REGION-REPORT is used by the SORT.
--- contents of sample data file COMPANY.DAT ---
A WAL-MART
B EXXON
C CHEVRON
B BERKSHIRE
A APPLE
C GENERAL MOTORS
IDENTIFICATION DIVISION.
PROGRAM-ID. COMPANY-BY-REGION.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT COMPANY-FILE
ASSIGN TO 'COMPANY.DAT'
ORGANIZATION IS LINE SEQUENTIAL.
SELECT COMPANY-SORT-FILE
ASSIGN TO DISK.
SELECT REGION-REPORT-FILE
ASSIGN TO 'COMPANY-BY-REGION.RPT'
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD COMPANY-FILE.
01 COMPANY-RECORD.
02 COM-REGION PIC X.
02 FILLER PIC X.
02 COM-NAME PIC X(20).
SD COMPANY-SORT-FILE.
01 COMPANY-SORT-RECORD.
02 SORT-REGION PIC X.
02 FILLER PIC X.
02 SORT-NAME PIC X(20).
FD REGION-REPORT-FILE.
01 REGION-REPORT-RECORD PIC X(20).
WORKING-STORAGE SECTION.
01 SORTED-DATA-REMAINS PIC X VALUE 'Y'.
88 NO-SORTED-DATA-REMAINS VALUE 'N'.
01 WS-SORTED-RECORD.
02 WS-REGION PIC X.
02 FILLER PIC X.
02 WS-NAME PIC X(20).
01 REGION-REPORT-HEADER.
02 FILLER PIC X(18) VALUE 'COMPANY IN REGION '.
02 HEAD-REGION PIC X VALUE SPACE.
02 FILLER PIC X VALUE ':'.
01 REGION-DETAIL.
02 DET-NAME PIC X(20).
01 PRIOR-REGION PIC X.
PROCEDURE DIVISION.
WRITE-COMPANY-BY-REGION-REPORT.
SORT COMPANY-SORT-FILE
ASCENDING KEY SORT-REGION
SORT-NAME
USING COMPANY-FILE
OUTPUT PROCEDURE OUTPUT-CO-BY-REGION-REPORT
STOP RUN
.
OUTPUT-CO-BY-REGION-REPORT.
OPEN OUTPUT REGION-REPORT-FILE
PERFORM UNTIL NO-SORTED-DATA-REMAINS
RETURN COMPANY-SORT-FILE INTO WS-SORTED-RECORD
AT END SET NO-SORTED-DATA-REMAINS TO TRUE
NOT AT END
PERFORM WRITE-COMPANY-RECORD
END-PERFORM
CLOSE REGION-REPORT-FILE
.
WRITE-COMPANY-RECORD.
IF HEAD-REGION = SPACE
OR WS-REGION NOT = PRIOR-REGION
PERFORM PRINT-HEADER
END-IF
MOVE WS-NAME TO DET-NAME
WRITE REGION-REPORT-RECORD FROM REGION-DETAIL
.
PRINT-HEADER.
IF HEAD-REGION NOT = SPACE
MOVE SPACES TO REGION-REPORT-RECORD
WRITE REGION-REPORT-RECORD
END-IF
MOVE WS-REGION TO HEAD-REGION
PRIOR-REGION
WRITE REGION-REPORT-RECORD FROM REGION-REPORT-HEADER
.
You should do this in a single pass of the file. Instead of just checking one item at a time, check all of them in the single pass...
I need to make a table out of the data structure below because I am not certain how many records that are each one line long will be in my input file. If I can make a table then I will be able to loop through them at a later time which is what I need to be able to do.
**Question: How to make a table out of the data structure before?
Part B: An array in Cobol is an OCCURS 100 TIMES
01 PRECORD.
05 JE.
10 NE PIC X(6) VALUE SPACES.
10 NM PIC X(2) VALUE SPACES.
05 FILL1 PIC X(16) VALUE SPACES.
05 TM PIC X(7) VALUE SPACES.
05 FILL2 PIC X(6) VALUE SPACES.
05 TT PIC X(7) VALUE SPACES.
05 FILL3 PIC X(13) VALUE SPACES.
05 TTY PIC X(10) VALUE SPACES.
05 FILL4 PIC X(13) VALUE SPACES.
01 PRECORD.
02 table-counter <-- this is used to hold the number of records
02 tTable occurs 300 times. <-- creates a table with three hundred occurences
05 JE.
10 NE PIC X(6) VALUE SPACES.
10 NM PIC X(2) VALUE SPACES.
05 FILL1 PIC X(16) VALUE SPACES.
05 TM PIC X(7) VALUE SPACES.
05 FILL2 PIC X(6) VALUE SPACES.
05 TT PIC X(7) VALUE SPACES.
05 FILL3 PIC X(13) VALUE SPACES.
05 TTY PIC X(10) VALUE SPACES.
05 FILL4 PIC X(13) VALUE SPACES.
The code above is update with how I think that table should look. The table has to have a counter at the top and then under than it will have to have a occur and how many times the table should occur.
The question that I was asking was how do you make a table like above actually a table I did not know that you had to create an Occurs and then put everything below that level of the occurs.
01 mytable.
02 counter...
02 tablevar occures 200 times.
05 var...
05 var2..
I just was not sure of the structure of a Cobol table. My question is what was the format of a Cobol data structure?
Your table-counter will need a PICture.
What PICture? Opinions vary.
There are three numeric formats which are useful for this, binary, packed-decimal, and display-numeric.
nn table-counter COMP/COMP-4/BINARY/COMP-5 PIC 9(4).
nn table-counter COMP-3/PACKED-DECIMAL PIC 9(3).
nn table-counter PIC 9(3).
The most efficient definition will be a binary one. If you use packed-decimal, the compiler will generate code to convert it to binary when used in comparison with anything you use for subscripting (except literals). When using display-numeric, the compiler will generate code to first convert to packed-decimal, then to binary.
Do these things matter with the speed of machines these days? Well, if they don't matter, may as well be efficient, but opinions do vary.
What size for the PICture? 9(4) for binary allows up to 9999 as a maximum value. You can code 999, but it does not give you much advantage (can't limit it to 300), so I go for optimal for the size (for a packed-decimal (COMP-3) it would be 999, as you don't get a fourth digit for nothing). Same if using display-numeric. Again, opinions vary.
If those are records, as Magoo has pointed out, you can't just add the count to the beginning of the record. You can't keep your table in the FILE SECTION under and FD. It will need to go into the WORKING-STORAGE SECTION.
Then there is the problem of keeping two structures "in step" for where they should match each other.
You probably have a copybook for the record-layout. The best is if you can parameterise the names in the copybook, so that you can use REPLACING on the COPY statement, allowing you to use the same copybook for the two different purposes. It would then be important that the copybook does not contain an 01-level. Again opinions vary on the inclusion of 01s in copybooks, but you may get lucky.
Which, given all the opinion, gets us to "well, what do I do?". What you do is the way they do it at your site. There should be documentation of local standards. This may not cover everything, you may have to seek the opinions of colleagues. If you all code in about the same way, it makes the code easier to understand.
Personally, I'd declare table-counter as a 77-level with a PIC 9(03). And you really should remove the VALUE clauses. Of course, this would need to be a WORKING-STORAGE entry, not an FD since the table isn't on the file. Other than that, what you've dome appears valid - but it's difficult to see what question you are asking.
May I ask, what is the usage of the keyword REDEFINES in COBOL?
I can not understand the manual's definition.
What is the meaning of the following code?
01 WS_CHARGE_TXT_8X PIC X(08) VALUE "10000000".
01 WS_CHARGE_NUM_8 REDEFINES WS_CHARGE_TXT_8X.
05 WS_CHARGE_8 PIC 9(05)V9(03).
Thank you!
Basically Redefines reuses the spaces so in the above example WS_CHARGE_TXT_8X and WS_CHARGE_8 will point to the same block of memory. This allows you to look at a block of memory in different ways, in this case the variable can be viewed as a text PIC X and a signed numeric PIC S9. The -8X to -8 in the variable name is just stylistic to indicate the variable is being recast to another type or format to other programmers.
In the above example
the value of WS_CHARGE_TXT_8X is
"10000000"
the value of WS_CHARGE_8 is
of 10000.000.
If you moved 123.456 to WS_CHARGE_8 the value of WS_CHARGE_TXT_8X "00123456".
A more useful example is
03 Birth-Date-YYYYMMDD pic 9(8).
03 filler redefines Birth-Date-YYYYMMDD.
05 Birth-Date-YYYY pic 9(4).
05 Birth-Date-MM pic 99.
05 Birth-Date-DD pic 99.
In this case you can access the whole date Birth-Date-YYYYMMDD or the year / month / day individually (Birth-Date-YYYY etc).
It is analogous to union in 'C'.
It saves working storage space, and MOVE statements, and is also useful for transposing arrays of PIC(X), or accessing repeated fields as an array.
In the OP's case a numeric "type" is being created for the char contents of the prototype field.
A REDEFINES allows a different data description for storage which has already been defined.
That might be to allow entirely different data to be held there.
05 RL-AGENT-DATA.
...
05 RL-CUSTOMER-DATA REDEFINES RL-AGENT-DATA.
...
Or to give a description which allows a use of a part of the data, as in Bruce's example.
Or to use a piece of data that is the same, but for a different purpose:
05 INPUT-AMOUNT PIC X(10).
05 INPUT-AMOUNT-NUMERIC REDEFINES PIC 9(8)V99.
Whatever is in INPUT-AMOUNT it can be reported without problem, but only if it is a valid numeric (by testng it for NUMERIC), is INPUT-AMOUNT-NUMERIC used for some purpose.
Note that each 01 subsequent to the first under an FD is an "implicit REDEFINES".
Note also that items in the LINKAGE SECTION have the effect of "redefining" "something", even though if the address of the data is from a CALLing program, the definition is often the same as the original definition, and should usually at least match the PICtures of the original.