Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I am trying to get this move statement in 01-WS-PRINT REC to work but for some reason when i compile it says "MOVE" was invalid. Scanning was resumed at next....Thoughts?
01 WS-PRINT-REC
10 M-DESC PIC X(25).
10 FILLER PIC X(02).
10 M-DATA PIC X(25).
MOVE 'STOCK SYMBOL' TO M-DESC.
MOVE MK-SYMBOL TO M-DATA.
PERFORM 700-PRINT-LINE.
COBOL programs are structured.
There is a data division (divided in a working-storage section and a local-storage section). Your data declarations should be done there.
Then you have a procedure division where you put your code (here the move statement).
You can't use "MOVE" in a data division. As you can't declare variable in a procedure division.
Moreover, as previously said, you shouldn't use a period at the end of each sentence.
For instance :
DATA DIVISION.
WORKING-STORAGE DIVISION.
01 WS-PRINT-REC
10 M-DESC PIC X(25).
10 FILLER PIC X(02).
10 M-DATA PIC X(25).
PROCEDURE DIVISION.
MAIN.
MOVE 'STOCK SYMBOL' TO M-DESC
MOVE MK-SYMBOL TO M-DATA
PERFORM 700-PRINT-LINE
.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
05 nStateNumOut PIC 99.
05 filler PIC XX VALUE SPACES.
05 xOutputName PIC X(20).
05 filler PIC XX VALUE SPACES.
05 neOutputPop PIC ZZZ,ZZZ,ZZZ9(8).
05 filler PIC XX VALUE SPACES.
05 neOutputArea PIC ZZZ,ZZZ9(6).
05 neOutputDen PIC ZZZ,ZZZ9,999.99.
05 neTotalPopOut PIC ZZZ,ZZZ9(10).
I need to get rid of leading zeros and place commas where needed. This what I get for as my end result.
Alabama 04447100 050750 00087
00 Alaska 00626932 570374 00001
00 Arizona 05130632 113642 00045
As far as I recall from 45 years ago. PIC ZZZ ,ZZZ9(6) is a 12-digit number that has 6 zero-suppressed digits and 6 non-zero-suppressed digits, as well as a single curiously-placed comma separator.
Don't write 9(6) if you don't want leading zeroes. Using Z(6). Or maybe Z(5)9.
Did you really need 12 digits for 'area' with a comma every 3 digits? If so, that would be PIC ZZZ,ZZZ,ZZZ,ZZ9.
Example: executed at https://www.jdoodle.com/execute-cobol-online/
IDENTIFICATION DIVISION.
PROGRAM-ID. ZERO.
DATA DIVISION.
WORKING-STORAGE SECTION.
77 X PIC Z(8)9.
77 Y PIC 9(9).
PROCEDURE DIVISION.
MOVE 1234 TO X.
MOVE 1234 TO Y.
DISPLAY 'X=', X, ' Y=', Y.
STOP RUN.
Displays
X= 1234 Y=000001234
Your declarations define too large fields. e.g.
05 neOutputPop PIC ZZZ,ZZZ,ZZZ9(8).
This is equivalent to:
05 neOutputPop PIC ZZZ,ZZZ,ZZZ99999999.
Now only numbers larger than 99999999 will have any digits in the positions where you want zero suppression. In your sample data, the population numbers are 8 digit numbers, so no non-zero digit in the "Z" places.
Your declarations already do have the leading zero suppression, and in fact it does work, because you don't see zeros in the "Z" positions. Right?
What you need is
05 neOutputPop PIC ZZZ,ZZZ,ZZ9.
I do not know how many digits you want to display at most, so I post a general solution:
05 9digits pic zzz,zzz,zz9.
This will show
1
12
123
1,234
12,345
123,456
1,234,567
12,345,678
123,456,789
What am I missing?
QualityPoints PIC 9v99 VALUE 4.00.
XValue PIC 9v99 VALUE 3.00.
Total PIC 999v99.
outTotal PIC zz9V99.
COMPUTE Total = QualityPoints * XValue.
MOVE Total to outTotal.
When I perform this compute my outTotal is 11.2 what happened?
Please see the reproducable results using online compiler which has all my code and files available.
There is absolutely nothing wrong with your code other than the fact that it's not a complete program that you posted (no divisions or sections, no levels on your data, possibly other things that I couldn't be bothered testing)
Well, that and the fact that the link to the online compiler site has long since gone, proof once again that SO question should be completely self-contained with all information needed. When posting questions and answers, I always ask myself if they'll still be useful if the rest of the internet totally disappears.
However, using that same site, the following program(a) does work as expected:
IDENTIFICATION DIVISION.
PROGRAM-ID. PAX-DIABLO.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 QualityPoints PIC 9v99 VALUE 4.00.
01 XValue PIC 9v99 VALUE 3.00.
01 Total PIC 999v99.
01 outTotal PIC zz9.99.
PROCEDURE DIVISION.
COMPUTE Total = QualityPoints * XValue.
MOVE Total to outTotal.
DISPLAY outTotal.
STOP RUN.
It produces the expected answer, as per the below transcript:
$cobc -x -free *.cobc -o main
$main
12.00
(a) See, this answer is self-contained, see how easy that was :-)
I am trying to use the SORT feature of COBOL.
IDENTIFICATION DIVISION.
PROGRAM-ID. ******.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT IN-FILE ASSIGN TO IFILE.
SELECT OUT-FILE ASSIGN TO OFILE.
SELECT SORT-FILE ASSIGN TO SORTWK.
DATA DIVISION.
FILE SECTION.
SD SORT-FILE.
01 SORT-REC.
05 S-NAME PIC X(20).
05 S-ADDRESS PIC X(20).
05 S-ID PIC 9(9).
05 S-CREDITS PIC 99.
05 FILLER PIC X(29).
FD IN-FILE.
01 IN-REC.
05 IN-NAME PIC X(20).
05 IN-ADDRESS PIC X(20).
05 IN-ID PIC 9(9).
05 IN-CREDITS PIC 99.
05 FILLER PIC X(29).
FD OUT-FILE.
01 OUT-REC PIC X(80).
WORKING-STORAGE SECTION.
01 WS-WORK-AREA.
05 EOF-SW PIC X VALUE SPACES.
01 WS-DETAIL-LINES.
05 RPT-LINE.
10 OUT-NAME PIC X(20).
10 OUT-ADDRESS PIC X(20).
10 OUT-ID PIC 9(9).
10 OUT-CREDITS PIC 99.
10 FILLER PIC X(29) VALUE SPACES.
PROCEDURE DIVISION.
MAIN-RTN.
SORT SORT-FILE
ON ASCENDING KEY S-ID
INPUT PROCEDURE READ-RELEASE
OUTPUT PROCEDURE RETURN-WRITE.
STOP RUN.
OPEN-FILES-RTN.
OPEN INPUT IN-FILE.
OPEN OUTPUT OUT-FILE.
OPEN-FILES-RTN-EXIT. EXIT.
READ-RELEASE.
PERFORM OPEN-FILES-RTN.
PERFORM READ-INPUT
UNTIL EOF-SW = 'F'.
READ-RELEASE-RTN-EXIT. EXIT.
READ-INPUT.
READ IN-FILE
AT END MOVE 'F' TO EOF-SW.
RELEASE SORT-REC FROM IN-REC.
RETURN-WRITE.
MOVE SPACES TO EOF-SW.
PERFORM WRITE-FL
UNTIL EOF-SW = 'F'.
PERFORM CLOSE-FILES-RTN.
RETURN-WRITE-RTN-EXIT. EXIT.
WRITE-FL.
RETURN SORT-FILE RECORD INTO OUT-REC
AT END MOVE 'F' TO EOF-SW.
WRITE OUT-REC.
WRITE-FL-RTN-EXIT. EXIT.
CLOSE-FILES-RTN.
CLOSE IN-FILE OUT-FILE.
CLOSE-FILES-RTN-EXIT. EXIT.
I am able to compile this program but when it comes to execute, it gives the following error:
CEE3204S The system detected a protection exception (System Completion
Code=0C4). From compile unit SU98PGM6 at entry point SU98PGM6
at compile unit offset +0005517A at address 1F45517A.
I have searched about this error but I couldn't figure out what is causing this problem in my program.
I have made some changes after taking note of the comments, but am still getting the same problem with this changed code.
READ-RELEASE.
PERFORM OPEN-FILES-RTN.
PERFORM READ-INPUT
UNTIL EOF-SW = 'F'.
READ-RELEASE-RTN-EXIT. EXIT.
READ-INPUT.
READ IN-FILE
AT END MOVE 'F' TO EOF-SW
NOT AT END PERFORM PROCESS-INPUT.
PROCESS-INPUT.
MOVE IN-NAME TO S-NAME.
MOVE IN-ADDRESS TO S-ADDRESS.
MOVE IN-ID TO S-ID.
MOVE IN-CREDITS TO S-CREDITS.
RELEASE SORT-REC.
PROCESS-INPUT-RTN-EXIT. EXIT.
RETURN-WRITE.
MOVE SPACES TO EOF-SW.
PERFORM WRITE-FL
UNTIL EOF-SW = 'F'.
PERFORM CLOSE-FILES-RTN.
RETURN-WRITE-RTN-EXIT. EXIT.
WRITE-FL.
RETURN SORT-FILE RECORD INTO OUT-REC
AT END MOVE 'F' TO EOF-SW
NOT AT END PERFORM PROCESS-OUTPUT.
WRITE-FL-RTN-EXIT. EXIT.
PROCESS-OUTPUT.
MOVE S-NAME TO OUT-NAME.
MOVE S-ADDRESS TO OUT-ADDRESS.
MOVE S-ID TO OUT-ID.
MOVE S-CREDITS TO OUT-CREDITS.
WRITE OUT-REC.
PROCESS-OUTPUT-RTN-EXIT. EXIT.
Here is my JCL
//******** JOB 1,'*****',NOTIFY=*******
//JOBLIB DD DSN=*******.*******.*******,DISP=SHR
//STEP0 EXEC PGM=SU98PGM6
//IFILE DD DSN=*******.*******.*******.*******(*******),DISP=SHR
//SORTWK DD DSN=*******.*******.*******.*******,DISP=SHR
//OFILE DD DSN=*******.*******.*******.*******,
// DISP=(NEW,CATLG,DELETE),
// DCB=(BLKSIZE=0,LRECL=80,RECFM=FB),
// SPACE=(CYL,(1,1),RLSE),
// UNIT=SYSDA
/*
The output for the //SYSOUT DD can be confusing when using COBOL, SORT (DFSORT or SyncSORT) and Language Environment which may give you run-time messages, as they all use SYSOUT by default, and the messages will appear intermingled.
Fortunately, you can change the default behaviour, as shown here for DFSORT and Language Envrionment (there are many ways in LE to specify the option, the most flexible is a //CEEOPTS DD in your JCL): https://stackoverflow.com/a/29521423/1927206
COBOL itself has a compiler option, OUTDD. the value defaults to SYSOUT, but you can specify any OUTDD(xxxx)
OK, having seen your JCL and your comments about how a DISPLAY statement in your program affects the data, I've managed a partial reproduce.
I use DFSORT, and I don't get your exact behaviour so I'm going to assume you use SYNCSORT.
The behaviour I can get having removed the //SYSOUT DD from my JCL is this message:
IGZ0026W The SORT-RETURN special register was never referenced, but
the current content indicated the sort or merge operation in program
STOB87 on line number 46 was unsuccessful.
When I add the //SYSOUT back into the JCL, the program runs successfully.
When I take the //SYSOUT out and add a DISPLAY before the SORT, the program works. This is because if there is no //SYSOUT in the JCL the first DISPLAY which is executed will cause one to be dynamically created (the output will appear in the spool as though it were a separate JOB, with the same name and jobnumber).
In my case DFSORT is complaining about the missing //SYSOUT. With the DISPLAY, the //SYSOUT is not missing at the time DFSORT starts.
I have to assume that SYNCSORT is facing a similar issue, but the run-time COBOL message is not produced and SYNCSORT itself fails on the next RELEASE.
Although this seems like a simple and common issue, because we always copy a piece of JCL to make a new piece of JCL, //SYSOUT is always there.
Consult the Enterprise COBOL Programming Guide, Chapter 12 I think, and see how to use SORT-RETURN to confirm that the SORT completed successfully.
I'm pretty sure that if you include the //SYSOUT in your JCL you will no longer get the abend, whether or not you have a DISPLAY.
The reason for the high "offset" is that the abend processor is unable to identify the entry-point of your SORT product, so keeps searching backwards to find something it can identify, and locates your program entry-point and then calculates the incorrect offset. This can also happen when CALLing some Assembler programs.
Firstly, to your S0C4, which is a Protection Exception, which means you are attempting to access storage which doesn't "belong" to you for the access you want.
You are getting a S0C4 in program SU98PGM6. You have cunningly obliterated your PROGRAM-ID name when posting here, which probably hasn't helped.
SU98PGM6 is not your program. The abend (Abnormal End) is at offset X'0005517A' in the failing program. That means, from the "start" of the program (the Entry Point) the instruction at offset/displacement X'0005517A' is the one which attempted the bad thing. That offset, which in decimal is 348538, indicates a fairly large program. Your program is very small.
There are many ways that this can come about. For instance, you may have copied the JCL from somewhere else, and failed to change the EXEC PGM=. You may have a program of the same name as yours earlier in the STEPLIB concatenation. You may have compiled the wrong program. Etc.
When you get an abend, always confirm that the compile listing you have is for the program that abended. An easy and useful way to do this is:
01 W-WHEN-COMPILED PIC X(8)BX(8).
...
* where it can only be executed once:
MOVE WHEN-COMPILED TO W-WHEN-COMPILED
DISPLAY
"yourname COMPILED ON "
W-WHEN-COMPILED
"yourname" you replace with the text following PROGRAM-ID.
The output will be like this:
yourname COMPILED ON 11/24/15 10.35.26
That will match the date/time in the heading on each page of the compile listing.
If you run a program and don't get that output, or you get output but it is not the output expected, then you know your program is not the one running.
Now to your program.
You do not need to use input/output procedures to be able to SORT
You should always use the FILE STATUS clause of the SELECT statement, and always check the file-status fields (one per file) that you define, after each IO operation. Testing the file-status field for an input file will allow you to identify end-of-file without the need for the tortuous AT END/NOT AT END construct
If you use sort procedures, COBOL does the IO. If you don't, and use compiler option FASTSRT, your SORT product will do the IO, which will be much more efficient than COBOL.
Unless you are selecting or reformatting records, you don't need the sort procedures
Since you are using INTO, which does an implicit MOVE of the record, you don't need to also MOVE the data individually
COBOL, since compilers supporting the 1985 Standard, which I'm fairly sure you will have, have "scope terminators". Prior to that, the only scope-terminator was the full-stop/period. These days, use the explicit, specific scope-terminators when using "imperative statements" and for all conditional statements. In your case, replace use READ/END-READ, RETURN/END-RETURN
Only use full-stops/periods in the PROCEDURE DIVISION where they are required, and not on a line of code. This aids the moving/copying of code from one location to another
Use 88-level condition-names for tests, rather than literals. You can make the name exactly meaningful, so nobody ever has to wonder what 'F' means in a particular context
To simply SORT a file in a COBOL program, look at SORT ... USING ... GIVING... and use compiler option FASTSRT (if possible).
You are not yet aware of the implications of paragraphs (or SECTIONs) and the EXIT statement.
When using PERFORM or a SORT PROCEDURE execution is transferred to the code in the paragraph, and returns control when the next paragraph is reached.
Your "exit" paragraphs as you have coded are never used, but someone looking at the code will assume (if they are silly, and a lot of people will make the assumption) that you have used THRU and they'll stick in a GO TO the "exit" paragraph. Then they'll be surprised that the program behaves badly (if they're luck) and will eventually work out that they have used GO TO to transfer control out of the range of the PERFORM/PROCEDURE.
If your local standards enforce the use of exit-paragraphs, then you must use THRU in your PERFORM and PROCEDURE statements.
Exit-paragraphs are entirely useless, and do nothing but provide a target-label for a GO TO, meaning that someone in the future will likely use a GO TO for "convenience".
Here's your original program with the exit-paragraphs removed:
IDENTIFICATION DIVISION.
PROGRAM-ID. ******.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT IN-FILE ASSIGN TO IFILE.
SELECT OUT-FILE ASSIGN TO OFILE.
SELECT SORT-FILE ASSIGN TO SORTWK.
DATA DIVISION.
FILE SECTION.
SD SORT-FILE.
01 SORT-REC.
05 S-NAME PIC X(20).
05 S-ADDRESS PIC X(20).
05 S-ID PIC 9(9).
05 S-CREDITS PIC 99.
05 FILLER PIC X(29).
FD IN-FILE.
01 IN-REC.
05 IN-NAME PIC X(20).
05 IN-ADDRESS PIC X(20).
05 IN-ID PIC 9(9).
05 IN-CREDITS PIC 99.
05 FILLER PIC X(29).
FD OUT-FILE.
01 OUT-REC PIC X(80).
WORKING-STORAGE SECTION.
01 WS-WORK-AREA.
05 EOF-SW PIC X VALUE SPACES.
01 WS-DETAIL-LINES.
05 RPT-LINE.
10 OUT-NAME PIC X(20).
10 OUT-ADDRESS PIC X(20).
10 OUT-ID PIC 9(9).
10 OUT-CREDITS PIC 99.
10 FILLER PIC X(29) VALUE SPACES.
PROCEDURE DIVISION.
SORT SORT-FILE
ON ASCENDING KEY S-ID
INPUT PROCEDURE READ-RELEASE
OUTPUT PROCEDURE RETURN-WRITE
GOBACK
.
OPEN-FILES-RTN.
OPEN INPUT IN-FILE
OPEN OUTPUT OUT-FILE
.
READ-RELEASE.
PERFORM OPEN-FILES-RTN
PERFORM READ-INPUT
UNTIL EOF-SW = 'F'
.
READ-INPUT.
READ IN-FILE
AT END MOVE 'F' TO EOF-SW
END-READ
RELEASE SORT-REC FROM IN-REC
.
RETURN-WRITE.
MOVE SPACES TO EOF-SW
PERFORM WRITE-FL
UNTIL EOF-SW = 'F'
PERFORM CLOSE-FILES-RTN
.
WRITE-FL.
RETURN SORT-FILE RECORD INTO OUT-REC
AT END MOVE 'F' TO EOF-SW
END-RETURN
WRITE OUT-REC
.
CLOSE-FILES-RTN.
CLOSE IN-FILE OUT-FILE
.
I've also changed the STOP RUN to GOBACK, which is much more flexible, and removed your first paragraph-name, as it is unnecessary and for people new to COBOL implies too much (COBOL itself has no concept of "main" as it may be pertinent in other languages you may know).
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I am trying to figure out why my file definitions are incorrect. From what I can tell this is the same way that they were defined in my last program and all will be fixed block records
Code:
FILE-CONTROL.
SELECT INFILE1 ASSIGN TO UT-S-INPUT1.
SELECT INFILE2 ASSIGN TO UT-S-INPUT2.
SELECT OUTPUT-FILE1 ASSIGN TO UT-S-OUTPUT1.
SELECT OUTPUT-FILE2 ASSIGN TO UT-S-OUTPUT2.
DATA DIVISION.
FILE SECTION.
FD INFILE1.
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS F
LABEL RECORDS ARE STANDARD.
01 INF-LINE1.
05 STATE-1 PIC X(02).
05 KEY-1 PIC X(10).
05 TRANSID1 PIC X(10).
05 FILLER PIC X(58).
FD INFILE2.
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS F
LABEL RECORDS ARE STANDARD.
01 INF-LINE2.
05 KEY-2 PIC X(10).
05 TRANSID2 PIC X(10).
05 FILLER PIC X(60).
FD OUTPUT-FILE1
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS F
LABEL RECORDS ARE STANDARD.
01 OUTLINE1 PIC X(80).
FD OUTPUT-FILE2
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS F
LABEL RECORDS ARE STANDARD.
01 OUTLINE2 PIC X(80).
Error Code: Some of these error codes do not pertain to the file errors but I copied all of them and placed in this section.
20 IGYGR1216-I A "RECORDING MODE" of "F" was assumed for file "INFILE1".
21 IGYDS1089-S "BLOCK" was invalid. Scanning was resumed at the next area "A" item, level-number, or the start of the next
clause.
Same message on line: 31
30 IGYGR1216-I A "RECORDING MODE" of "F" was assumed for file "INFILE2".
283 IGYPA3043-E Data-item "INF-LINE1 (GROUP)" and record "INF-LINE1 (GROUP)" had overlapping storage. Movement of data may
not occur at execution time.
293 IGYPA3043-E Data-item "INF-LINE2 (GROUP)" and record "INF-LINE2 (GROUP)" had overlapping storage. Movement of data may
not occur at execution time.
304 IGYPS2015-I The paragraph or section prior to paragraph or section "X-COMP-FILE" did not contain any statements.
321 IGYPS2121-S "STUB4" was not defined as a data-name. The statement was discarded.
If you remove the period after the file name on our definition statement it should work without compiler errors.
Code:
FD INFILE1
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS F
LABEL RECORDS ARE STANDARD.
01 INF-LINE1.
05 STATE-1 PIC X(02).
05 KEY-1 PIC X(10).
05 TRANSID1 PIC X(10).
05 FILLER PIC X(58).
FD INFILE2
BLOCK CONTAINS 0 RECORDS
RECORDING MODE IS F
LABEL RECORDS ARE STANDARD.
01 INF-LINE2.
05 KEY-2 PIC X(10).
05 TRANSID2 PIC X(10).
05 FILLER PIC X(60).
This is a common mistake that happens when you look at a green screen all day long. I would recompile this and see if the other errors go away. It is always a good idea to recompile a program and then start fresh. Do you print the compile listing to scan through every-now-and-then. I would I think. The compile listing gives you all of the memory locations and the size of each record. It is very handy.
Code:
30 IGYGR1216-I A "RECORDING MODE" of "F" was assumed for file "INFILE2".
I am not certain on this error but I bet that you have the F a V for fixed block files. I would check this and if that is the case fix it. Do you start from scratch on programs or do you take a working program and then gut out what you do not need and then start working from that perspective. If this is the case you want to make certain that you have the recording mode set correctly for fixed block and variable block files.
321 IGYPS2121-S "STUB4" was not defined as a data-name. The statement was discarded.
The above error is simple that there is no working storage or variable named STUB4.
Hope this helps.
This is my code where iIam declaring a variable using OCCURS.
IDENTIFICATION DIVISION.
PROGRAM-ID. ARRAYEX.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT StudentFile ASSIGN TO "STUDENTS.DAT"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
WORKING-STORAGE SECTION.
77 WS-FIRSTARR OCCURS 10 TIMES PIC 9(5).
PROCEDURE DIVISION.
DISPLAY "HELLO WORLD".
STOP RUN.
Error:
arrayex.cbl:12: Error: Level 77 item 'WS-FIRSTARR' cannot have OCCURS clause
Any reasons the compilation fails?
A 77 cannot have OCCURS. An 01 cannot have OCCURS. Levels 02-49 can have OCCURS.
Forget level 66 (used for the RENAMES clause) as your should not use it and are unlikely to ever see it.
An 88-level, a Condition Name, cannot have an occurs, but if the field which it is defined on is part of an OCCURS or subordinate to an OCCURS, the 88 will need subscripting like any 02- - 49-level which is also part of, or subordinate to, an OCCURS.
01 a-simple-array-structure.
05 the-data occurs 5 times pic 9(5).
Or you can get more complex.
01 b-structure.
95 the-key pic x(8).
05 some-data pic x(10).
05 some-more-data pic 9(7).
05 a-simple-array.
10 a-simple-array-item occurs 5 times
pic 9(5).
05 a-more-complex-array.
10 complex-entry occurs 10 times.
15 some-complex-data pic xx.
15 another-bit-of-complex-data
pic 9(5).
OCCURS can also be used to define multi-dimensional tables.
05 first-occurs occurs 5 times.
10 second-occurs occurs 5 times.
15 an-item pic xx.
This is still far from the full gamut of OCCURS, so start simple, practice, get it working, become more complex.
There is also OCCURS DEPENDING ON, a variable-length table. One thing at a time. Get a simple OCCURS working, not just the definition, but the use as well, with a field for a subscript, an index for a subscript and a literal for a subscript.
Then get more complex.
COBOL has several "magic" level numbers...
Level-66 items indicate a RENAMES clause is to be expected
Level-77 items are atomic, cannot be subdivided, cannot have an OCCURS clause.
Level-88 indicates a condition-name entry
See pages 5-4 and 5-5 of the programmer's guide.