Michael Coughlan
Page 23
CLAUSE until I dealt with print files. To refresh your memory, the metalanguage for the WRITE statement is given in Figure 8-9.
169
Chapter 8 ■ advanCed Sequential FileS
Figure 8-9. Metalanguage for the WRITE verb
The syntax for writing to print files is more complicated than that used for writing in ordinary sequential files because it must contain entries to allow you to control the vertical placement of the print lines. For instance, the statement WRITE PrintLine BEFORE ADVANCING 2 LINES sends the data in PrintLine to the printer, after which the printer advances two lines.
Notes on WRITE
The ADVANCING clause is used to position the lines on the page when writing to a print file or a printer. The ADVANCING
clause uses the BEFORE or AFTER phrase to specify whether advancing is to occur before the line is printed or after.
The PAGE option writes a form feed (goes to a new page) to the print file or printer. MnemonicName refers to a vendor-specific page control command. It is defined in the SPECIAL-NAMES paragraph.
When you write to a print file, you generally use the WRITE..FROM option because the print records are described in the WORKING-STORAGE SECTION. When the WRITE..FROM option is used, the data in the source area is moved into the record buffer and then the contents of the buffer are written to the print file. WRITE..FROM is the equivalent of a MOVE
SourceItem TO RecordBuffer statement followed by a WRITE RecordBuffer statement.
SOMe IGNOreD WrIte VerB eNtrIeS
i have ignored some print-related formats of the WRITE verb on the basis that if you need this level of print sophistication, you should be using the report Writer. the full WRITE syntax includes the END-OF-PAGE clause, as shown in the following illustration; this is connected to the LINAGE clause specified in the file’s Fd entry. the LINAGE clause specifies the number of lines that can fit on a page, and this in turn allows the end of the page to be automatically detected. if you want to explore this further, you should read your implementer manual.
170
Chapter 8 ■ advanCed Sequential FileS
Example Program
Listing 8-3 contains a program that produces a simple report to show a golf club’s membership list. The program keeps a count of the number of lines printed; it changes the page and prints the headings again when the line count is greater than 49. A page count is also kept, and this is printed at the bottom of each page. The report produced by running the program is shown in Figure 8-10.
Listing 8-3. Program to Print the Golf Club Membership Report
IDENTIFICATION DIVISION.
PROGRAM-ID. Listing8-3.
AUTHOR. Michael Coughlan.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT MembershipReport
ASSIGN TO " Listing8-3-Members.rpt"
ORGANIZATION IS SEQUENTIAL.
SELECT MemberFile ASSIGN TO "Listing8-3Members.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD MembershipReport.
01 PrintLine PIC X(44).
FD MemberFile.
01 MemberRec.
88 EndOfMemberFile VALUE HIGH-VALUES.
02 MemberId PIC X(5).
02 MemberName PIC X(20).
02 MemberType PIC 9.
02 Gender PIC X.
WORKING-STORAGE SECTION.
01 PageHeading.
02 FILLER PIC X(44)
VALUE "Rolling Greens Golf Club - Membership Report".
01 PageFooting.
02 FILLER PIC X(15) VALUE SPACES.
02 FILLER PIC X(7) VALUE "Page : ".
02 PrnPageNum PIC Z9.
01 ColumnHeadings PIC X(41)
VALUE "MemberID Member Name Type Gender".
01 MemberDetailLine.
02 FILLER PIC X VALUE SPACES.
02 PrnMemberId PIC 9(5).
171
Chapter 8 ■ advanCed Sequential FileS
02 FILLER PIC X(4) VALUE SPACES.
02 PrnMemberName PIC X(20).
02 FILLER PIC XX VALUE SPACES.
02 PrnMemberType PIC X.
02 FILLER PIC X(4) VALUE SPACES.
02 PrnGender PIC X.
01 ReportFooting PIC X(38)
VALUE "**** End of Membership Report ****".
01 LineCount PIC 99 VALUE ZEROS.
88 NewPageRequired VALUE 40 THRU 99.
01 PageCount PIC 99 VALUE ZEROS.
PROCEDURE DIVISION.
PrintMembershipReport.
OPEN INPUT MemberFile
OPEN OUTPUT MembershipReport
PERFORM PrintPageHeadings
READ MemberFile
AT END SET EndOfMemberFile TO TRUE
END-READ
PERFORM PrintReportBody UNTIL EndOfMemberFile
WRITE PrintLine FROM ReportFooting AFTER ADVANCING 5 LINES
CLOSE MemberFile, MembershipReport
STOP RUN.
PrintPageHeadings.
WRITE PrintLine FROM PageHeading AFTER ADVANCING PAGE
WRITE PrintLine FROM ColumnHeadings AFTER ADVANCING 2 LINES
MOVE 3 TO LineCount
ADD 1 TO PageCount.
PrintReportBody.
IF NewPageRequired
MOVE PageCount TO PrnPageNum
WRITE PrintLine FROM PageFooting AFTER ADVANCING 5 LINES
PERFORM PrintPageHeadings
END-IF.
MOVE MemberId TO PrnMemberId
MOVE MemberName TO PrnMemberName
MOVE MemberType TO PrnMemberType
MOVE Gender TO PrnGender
WRITE PrintLine FROM MemberDetailLine AFTER ADVANCING 1 LINE
ADD 1 TO LineCount
READ MemberFile
AT END SET EndOfMemberFile TO TRUE
END-READ.
172
Chapter 8 ■ advanCed Sequential FileS
Figure 8-10. Report produced by Listing 8-3
Report Writer Version
The Report Writer has been mentioned a number of times in this chapter, so it might be useful to compare the PROCEDURE DIVISION of the program in Listing 8-3 with the PROCEDURE DIVISION of the Report Writer version of the report shown in Example 8-6. How is it able to do so much work with so little PROCEDURE DIVISION code? A short answer is that that is the magic of the Report Writer and declarative programming. A detailed answer will have to wait until I examine the Report Writer in a later chapter.
173
Chapter 8 ■ advanCed Sequential FileS
Example 8-6. PROCEDURE DIVISION for Report Writer Version of the Golf Club Membership Report PROCEDURE DIVISION.
PrintMembershipReport.
OPEN INPUT MemberFile
OPEN OUTPUT MembershipReport
INITIATE ClubMemebershipReport
READ MemberFile
AT END SET EndOfMemberFile TO TRUE
END-READ
PERFORM UNTIL EndOfMemberFile
GENERATE MemberLine
READ MemberFile
AT END SET EndOfMemberFile TO TRUE
END-READ
END-PERFORM
TERMINATE ClubMemebershipReport
CLOSE MemberFile, MembershipReport
STOP RUN.
Variable-Length Records
COBOL programs normally process fixed-length records, but sometimes files contain records of different lengths.
In the first section of this chapter, you saw that a file might consist of a number of different record types. But even though, taken as a whole, the records in the file vary in size, each record type is a fixed-length record. You can, however, have true variable-length records, meaning you do not know the structure or size of the records (although you have to know the maximum size and may know the minimum size). For instance, in an ordinary text file such as might be produced by MS Notepad, the lines of text have no structure and vary in size from line to line. This
section demonstrates how files containing true variable-length records may be declared and processed.
FD Entries for Variable-Length Records
When the FD entry for sequential files was introduced, you only saw a simplified version that consisted of the letters FD followed by the file name. Actually, the FD entry can be more complex than you have seen so far, and it can have a large number of subordinate clauses (see your implementer manual or help files). Some of these clauses are not required for all computers. For instance, the BLOCK CONTAINS clause is only required for computers where the number of characters read or written in one I/O operation is under programmatic control. If the block size is fixed, it is not required. Other clauses are syntax retained from previous versions of COBOL and are now treated as comments.
I ignore these. Some clauses are important for direct-access file organizations; I deal with these when I examine these file organizations. The RECORD IS VARYING IN SIZE clause allows you to specify that a file contains variable-length records. The metalanguage for the expanded FD entry is given in Figure 8-11 and Example 8-7 demonstrates how to use these new FD entries.
Figure 8-11. RECORD IS VARYING clause for variable-length records
174
Chapter 8 ■ advanCed Sequential FileS
Notes on Varying-Length Records
The RECORD IS VARYING IN SIZE clause without the DEPENDING ON phrase is not strictly required, because the compiler can work out this information from the record sizes. That is why it was not included in the multiple record-type declarations in the first section of this chapter.
The RecordSize#i in the DEPENDING ON phase must be an elementary unsigned integer data-item declared in the WORKING-STORAGE SECTION. When a record defined with the RECORD IS VARYING IN SIZE..DEPENDING ON phrase is
read from a file, the length of the record read in to the buffer is moved into the RecordSize#i data item. When a record defined with RECORD IS VARYING IN SIZE..DEPENDING ON is written to a file, the length of the record to be written must first be moved to RecordSize#i data-item, and then the WRITE statement must be executed.
Example 8-7. FD Entries with the RECORD IS VARYING Phrase
FD Textfile
RECORD IS VARYING IN SIZE
FROM 1 TO 80 CHARACTERS
DEPENDING ON TextLineLength.
Or we may define the file as -
FD Textfile
RECORD IS VARYING IN SIZE
DEPENDING ON TextLineLength.
Example Program
Listing 8-4 is an example program that demonstrates how to read a file that contains variable-length records. One problem with variable-length records is that although the records are variable length, the buffer into which they are read is fixed in size. So if only the characters that have been read from the file are required, they must be extracted from the record buffer. In this program, reference modification and NameLength are used to slice NameLength number of characters from the buffer. Reference modification is a COBOL string-handling facility that you explore in a later chapter. To demonstrate that you have extracted only the required characters, asterisks are used to bracket the names.
Figure 8-12 is a diagrammatic representation of how reference modification is used to extract the name from the record buffer.
Listing 8-4. Processing Variable-Length Records
IDENTIFICATION DIVISION.
PROGRAM-ID. Listing8-4.
AUTHOR. Michael Coughlan.
* This program demonstrates how to read variable length records.
* It also demonstrates how a file may be assigned its actual name
* at run time rather than compile time (dynamic vs static).
* The record buffer is a fixed 40 characters in size but the
* lengths or names vary so Reference Modification is used to extract
* only the number of characters from the record buffer.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT LongNameFile
ASSIGN TO NameOfFile
ORGANIZATION IS LINE SEQUENTIAL.
175
Chapter 8 ■ advanCed Sequential FileS
DATA DIVISION.
FILE SECTION.
FD LongNameFile
RECORD IS VARYING IN SIZE
DEPENDING ON NameLength.
01 LongNameRec PIC X(40).
88 EndOfNames VALUE HIGH-VALUES.
WORKING-STORAGE SECTION.
01 NameLength PIC 99.
01 NameOfFile PIC X(20).
PROCEDURE DIVISION.
Begin.
DISPLAY "Enter the name of the file :- "
WITH NO ADVANCING
ACCEPT NameOfFile.
OPEN INPUT LongNameFile.
READ LongNameFile
AT END SET EndOfNames TO TRUE
END-READ
PERFORM UNTIL EndOfNames
DISPLAY "***" LongNameRec(1:NameLength) "***"
READ LongNameFile
AT END SET EndOfNames TO TRUE
END-READ
END-PERFORM
CLOSE LongNameFile
STOP RUN.
Figure 8-12. Using reference modification to extract the name from the record
Summary
This chapter examined how files that contain records of different lengths may be defined and used. The first section of the chapter dealt with files in which the record lengths are different because the file contains fixed-length records of different types. The last section dealt with files that contain real variable-length records. The middle section of the chapter discussed the problem of print files. It explained why the different types of print lines required when printing a report cannot be declared as different records in the file’s FD entry but must instead be declared in the WORKING-STORAGE SECTION.
176
Chapter 8 ■ advanCed Sequential FileS
In the next chapter, you continue your exploration of printed output by examining edited pictures. Edited
pictures allow you to format data for output. In some of the example programs in this and previous chapters, I have used edited pictures without explanation because the context made obvious what was happening. But seeing edited pictures in action and knowing how to use them are different things. The next chapter examines edited pictures in detail and discusses how to format data so that leading zeros are suppressed; so that the currency symbol floats against the non-zero digits of the number; and so that blanks, commas, zeros, and slashes are inserted where they are required. Table 8-1 gives a preview of some of the formatting that can be applied to data.
Table 8-1. Preview of Some of the Edited Picture Formatting Effects
Effect
Value
Original value
00014584.95
With commas inserted
00,014,584.95
With zero-suppression added
14,584.95
With check security and currency symbol added
$***14,584.95
With floating + sign
+14,584.95
With floating currency symbol
$14,584.95
With zeros inserted after the decimal point
$14,584.00
With slashes inserted in the middle of the number
00/014/584.95
With three zeros inserted in the number
00014000584.95
With three blanks inserted in the number
00014 584.95
prOGraMMING eXerCISe 1
it is exercise time again. now, where did you put that 2B pencil? Write a program to satisfy the following specification.
University entrants Summary report
a program is required that will process the first-year-student entrants file (Entrants.dat) to produce a summary that shows the number of first-year students in each course. the summary should be displayed on the screen ordered by ascending CourseCode. an output template is given next.
177
<
br /> Chapter 8 ■ advanCed Sequential FileS
Output Template
First Year Entrants Summary
Course Code NumOfStudents
LM999 9,999
LM999 9,999
: :
: :
LM999 9,999
LM999 9,999
Total Students: 99,999
Entrants File
The entrants file (Entrants.dat) is a sequential file sequenced on ascending CourseCode. The records in the file have the following description:
Field
Type
Length
Value
StudentId
9
8
0-99999999
CourseCode
X
5
-
Gender
X
1
M/F
Some Statements You Need for Your Program
To make this programming exercise easier, some of the statements and data declarations required for your program are given next.
Executable Statements
DISPLAY Headingline1
DISPLAY Headingline2
DISPLAY CourseLine
DISPLAY SPACES
DISPLAY FinalTotalLine
MOVE CourseCode TO PrnCourseCode
MOVE CourseTotal TO PrnCourseTotal
MOVE FinalTotal TO PrnFinalTotal
READ EntrantsFile
AT END SET EndOfFile TO TRUE
END-READ
OPEN INPUT EntrantsFile
CLOSE EntrantsFile
ADD 1 TO CourseTotal, FinalTotal
MOVE ZEROS TO CourseTotal
MOVE ZEROS TO FinalTotal
MOVE CourseCode TO PrevCourseCode
178
Chapter 8 ■ advanCed Sequential FileS
Some Data Descriptions
01 HeadingLine1 PIC X(31) VALUE " First Year Entrants Summary".
01 HeadingLine2 PIC X(31) VALUE " Course Code NumOfStudents".
01 CourseLine.
02 FILLER PIC X(5) VALUE SPACES.
02 PrnCourseCode PIC X(5).
02 FILLER PIC X(10) VALUE SPACES.
02 PrnCourseTotal PIC Z,ZZ9.