Michael Coughlan

Home > Other > Michael Coughlan > Page 53


  Virgo

  Earth

  08-25

  09-22

  9

  Libra

  Air

  09-25

  10-22

  10

  Scorpio

  Water

  10-25

  11-21

  11

  Sagittarius Fire

  11-24

  12-20

  12

  Capricorn Earth

  12-23

  01-19

  13

  Cusp

  Cusp

  Cusp

  Cusp

  Processing

  Write a contained subprogram called IdentifySign to identify the Zodiac sign for a given birth date. the

  IdentifySign subprogram should take DateOfBirth as an input parameter and should return SignCode

  (shown in the previous table) as its return/output parameter. a code of 13 should be returned for cusp births.

  For each record in the file, do the following:

  • increment the TotalRecords count.

  • Call IdentifySign to get ZodiacSign for MaleDOB.

  • Call IdentifySign to get ZodiacSign for FemaleDOB.

  if either spouse had a cusp birth, then ignore the record. Otherwise, if the signs are compatible, increment the CompatiblePairs count; and if they are incompatible, increment the IncompatiblePairs count.

  430

  Chapter 16 ■ Creating Large SyStemS

  prOGraMMING eXerCISe: aNSWer

  Listing 16-9. Zodiac Sign Compatibility Tester

  IDENTIFICATION DIVISION.

  PROGRAM-ID. Listing16-9.

  AUTHOR. Michael Coughlan.

  ENVIRONMENT DIVISION.

  INPUT-OUTPUT SECTION.

  FILE-CONTROL.

  SELECT BirthsFile ASSIGN TO "Listing16-9MPDOB.DAT"

  ORGANIZATION IS LINE SEQUENTIAL.

  DATA DIVISION.

  FILE SECTION.

  FD BirthsFile.

  01 BirthsRec.

  88 EndOfFile VALUE HIGH-VALUES.

  02 MaleDOB PIC X(8).

  02 FemaleDOB PIC X(8).

  WORKING-STORAGE SECTION.

  01 Counts.

  02 CompatiblePairs PIC 9(7) VALUE ZEROS.

  02 CompatiblePrn PIC ZZZZ,ZZ9.

  02 CompatiblePercent PIC ZZ9.

  02 IncompatiblePairs PIC 9(7) VALUE ZEROS.

  02 IncompatiblePrn PIC ZZZZ,ZZ9.

  02 IncompatiblePercent PIC ZZ9.

  02 ValidRecs PIC 9(8) VALUE ZEROS.

  02 ValidRecsPrn PIC ZZ,ZZZ,ZZ9.

  02 TotalRecs PIC 9(9) VALUE ZEROS.

  02 TotalRecsPrn PIC ZZ,ZZZ,ZZ9.

  01 MaleSignType PIC 99.

  88 ValidMale VALUE 1 THRU 12.

  01 FemaleSignType PIC 99.

  88 ValidFemale VALUE 1 THRU 12.

  01 SumOfSigns PIC 99.

  PROCEDURE DIVISION.

  Begin.

  OPEN INPUT BirthsFile.

  READ BirthsFile

  AT END SET EndOfFile TO TRUE

  END-READ

  PERFORM ProcessBirthRecs UNTIL EndOfFile

  431

  Chapter 16 ■ Creating Large SyStemS

  COMPUTE ValidRecs = CompatiblePairs + IncompatiblePairs

  COMPUTE CompatiblePercent ROUNDED = CompatiblePairs / ValidRecs * 100

  COMPUTE InCompatiblePercent ROUNDED = InCompatiblePairs / ValidRecs * 100

  PERFORM DisplayResults

  CLOSE BirthsFile.

  STOP RUN.

  DisplayResults.

  MOVE CompatiblePairs TO CompatiblePrn

  MOVE IncompatiblePairs TO IncompatiblePrn

  MOVE TotalRecs TO TotalRecsPrn

  MOVE ValidRecs TO ValidRecsPrn

  DISPLAY "Total records = " TotalRecsPrn

  DISPLAY "Valid records = " ValidRecsPrn

  DISPLAY "Compatible pairs = " CompatiblePrn

  " which is " CompatiblePercent "% of total".

  DISPLAY "Incompatible pairs = " IncompatiblePrn

  " which is " InCompatiblePercent "% of total".

  ProcessBirthRecs.

  * Get the two sign types and add them together

  * If the result is even then they are compatible

  ADD 1 TO TotalRecs

  CALL "IdentifySign" USING BY CONTENT MaleDOB

  BY REFERENCE MaleSignType

  CALL "IdentifySign" USING BY CONTENT FemaleDOB

  BY REFERENCE FemaleSignType

  IF ValidMale AND ValidFemale

  COMPUTE SumOfSigns = MaleSignType + FemaleSignType

  IF FUNCTION REM(SumOfSigns 2) = ZERO

  ADD 1 TO CompatiblePairs

  ELSE

  ADD 1 TO IncompatiblePairs

  END-IF

  END-IF

  READ BirthsFile

  AT END SET EndOfFile TO TRUE

  END-READ.

  IDENTIFICATION DIVISION.

  PROGRAM-ID. IdentifySign IS INITIAL.

  DATA DIVISION.

  WORKING-STORAGE SECTION.

  01 WorkDate.

  88 Aquarius VALUE "0122" THRU "0218".

  88 Pisces VALUE "0221" THRU "0319".

  88 Aries VALUE "0322" THRU "0419".

  432

  Chapter 16 ■ Creating Large SyStemS

  88 Taurus VALUE "0422" THRU "0520".

  88 Gemini VALUE "0523" THRU "0620".

  88 Cancer VALUE "0623" THRU "0722".

  88 Leo VALUE "0725" THRU "0822".

  88 Virgo VALUE "0825" THRU "0922".

  88 Libra VALUE "0925" THRU "1022".

  88 Scorpio VALUE "1025" THRU "1121".

  88 Sagittarius VALUE "1124" THRU "1220".

  88 Capricorn VALUE "1223" THRU "1231", "0101" THRU "0119".

  02 WorkMonth PIC XX.

  02 WorkDay PIC XX.

  LINKAGE SECTION.

  01 DateOfBirth.

  02 BirthMonth PIC XX.

  02 BirthDay PIC XX.

  02 FILLER PIC 9(4).

  01 SignType PIC 99.

  PROCEDURE DIVISION USING DateOfBirth, SignType.

  Begin.

  MOVE BirthDay TO WorkDay.

  MOVE BirthMonth TO WorkMonth.

  EVALUATE TRUE

  WHEN Aquarius MOVE 1 TO SignType

  WHEN Pisces MOVE 2 TO SignType

  WHEN Aries MOVE 3 TO SignType

  WHEN Taurus MOVE 4 TO SignType

  WHEN Gemini MOVE 5 TO SignType

  WHEN Cancer MOVE 6 TO SignType

  WHEN Leo MOVE 7 TO SignType

  WHEN Virgo MOVE 8 TO SignType

  WHEN Libra MOVE 9 TO SignType

  WHEN Scorpio MOVE 10 TO SignType

  WHEN Sagittarius MOVE 11 TO SignType

  WHEN Capricorn MOVE 12 TO SignType

  WHEN OTHER MOVE 13 TO SignType

  END-EVALUATE.

  EXIT PROGRAM.

  END PROGRAM IdentifySign.

  END PROGRAM Listing16-9.

  433

  Chapter 17

  Direct Access Files

  When I learned COBOL many years ago, direct access files, and particularly indexed files, were the jewel in COBOL’s crown. No other mainstream programming language provided native support for file organizations of such versatility.

  Nowadays, the predominance of databases means that the importance of direct access files in modern COBOL

  programming is greatly reduced. Nevertheless, the huge inventory of legacy programs that still use direct access files makes these file organizations a worthwhile topic of discussion.

  This chapter introduces you to COBOL’s direct access file organizations: indexed and relative files. These organizations are called direct access organizations because they allow you to access data records directly based on a key field. Direct access files are more versatile than sequential files. They let you update or delete records in situ and access records sequentially or directly using a key field. Needless to say, direct access files only work on direct access media such as hard disks. You can’t use
indexed or relative files with serial media such as magnetic tapes. To take advantage of the versatility of direct access files, you use a number of new COBOL verbs and concepts. This chapter introduces the DELETE, REWRITE, and START verbs and the concepts of file status, the key of reference, and the next-record pointer.

  Sequential, indexed, and relative file organizations all have strengths and weaknesses. No one organization is best for all situations. This chapter concludes with a discussion of the advantages and disadvantages of all the COBOL

  file organizations and when you should use one rather than another.

  Direct Access vs.Sequential Files

  As you learned in Chapter 10, access to records in a sequential file is serial. To reach a particular record, you must read all the preceding records. You also learned that if the sequential file is unordered, the only practical operations are to read records from the file or add records to the end of the file. It is impractical to update records or delete records in an unordered sequential file. In addition, even if the file is ordered, inserting, updating, or deleting records is a problem because when you apply these operations, you must preserve the ordering of the file—and the only way to do that is to create a copy of the file to which these operations have been applied.

  Although sequential files have a number of advantages over other types of file organization (as discussed in the final section of this chapter), the fact that you must create a new file when you delete, update, or insert records is problematic.

  These problems are addressed by direct access files. Direct access files allow you to read, update, delete, and insert individual records in situ on the basis of a key value. For instance, to delete a customer record in a direct access file, you supply the customer ID of the record to be deleted and then execute a DELETE statement.

  In COBOL, there are two direct access file organizations: relative files and indexed files.

  435

  Chapter 17 ■ DireCt aCCess Files

  Organization of Relative Files

  Before you see how relative files are declared and used, let’s look at how they are organized. As you can see from the schematic representation in Figure 17-1, the records in a relative file are organized on ascending relative record number. You can visualize a relative file as a one-dimensional table stored on disk, and you can think of the relative record number as the index into that table.

  Figure 17-1. Schematic representation of a relative file

  Some restrictions should be obvious from Figure 17-1. First, only one relative key is supported, and that key must be numeric and take a value between 1 and the number of the highest relative record written to the file. Another restriction is that, even when the file is only sparsely populated, enough disk space has to be allocated to hold all the records between 1 and the record with the highest relative record number. For instance, if a record with a relative record number of 150,000 is written to the file, then room sufficient for 150,000 records is allocated to the file—even though that may be the only record actually written to the file. You can see this illustrated in Figure 17-1. In the example file, the record with the highest relative record number is 5,888, so disk space sufficient to store 5,888 records has been allocated. However, not all the record locations contain records. The record areas labelled “free” have been allocated but have not yet had record values written to them.

  Being restricted to a single numeric key in a defined range is onerous, but there are ways to loosen the shackles.

  For instance, you might add a base value to the relative record number to change the range. For instance, in Figure 17-1

  you could use a base of 10,000 so that the first record key value would be 10,001 and the last would be 15,888. Obviously, before you used the key, you would subtract 10,000 to convert it into the relative record number.

  Using a base value is a very simple key transformation, and in COBOL this is probably about as much

  manipulation as you want to do. In other languages, you might write a sophisticated hashing algorithm to map even alphanumeric keys onto range of relative record numbers; but in COBOL, when you need keys with this level of sophistication, you use indexed files.

  436

  Chapter 17 ■ DireCt aCCess Files

  In addition to showing how records are organized in a relative file, Figure 17-1 also shows how updates, insertions and, deletions are applied:

  • To update a record, you use the relative record number to READ the record from the file into the

  record buffer. Then you make the changes to the record data and REWRITE the record to the file.

  • To insert a record, you use the relative record number to tell the system where to WRITE the

  record. Obviously, the allocated space must be free, or an error condition will occur.

  • To delete a record, you use the relative record number to tell the system which record to

  DELETE. Obviously, the record must exist. For instance, in Figure 17-1, an error condition would occur if you tried to delete the record with the relative record number 5,887 because

  there is no record in that position. In a relative file, when you delete a record, all the file system

  does is to mark it as deleted. It does not really delete the record.

  Processing Relative Files

  As mentioned at the beginning of this chapter, direct access files are declared and processed using a number of new declaration clauses and verbs. Instead of boring you with a dry, formal introduction, this section shows you some simple examples. Once you have a feel for how it all works, I introduce the required clauses and verbs more formally.

  Let’s start with a simple program that reads a relative file both sequentially and directly. Then you learn how to create a relative file from a sequential file. Most programming environments have tools that allow you to do this, but it is interesting to see how to do it by hand. The final example shows you how to apply a file of transactions to the relative file.

  Reading a Relative File

  The program in Listing 17-1 reads a relative file either sequentially or directly, depending on the choice made by the user.

  Listing 17-1. Reading a Relative File Sequentially or Directly Using a Key

  IDENTIFICATION DIVISION.

  PROGRAM-ID. Listing17-1.

  AUTHOR. MICHAEL COUGHLAN.

  * Reads a Relative file directly or in sequence

  ENVIRONMENT DIVISION.

  INPUT-OUTPUT SECTION.

  FILE-CONTROL.

  SELECT VehicleFile ASSIGN TO "Listing17-1.DAT"

  ORGANIZATION IS RELATIVE

  ACCESS MODE IS DYNAMIC

  RELATIVE KEY IS VehicleKey

  FILE STATUS IS VehicleStatus.

  DATA DIVISION.

  FILE SECTION.

  FD VehicleFile.

  01 VehicleRec.

  88 EndOfVehiclefile VALUE HIGH-VALUES.

  02 VehicleNum PIC 9(4).

  02 VehicleDesc PIC X(25).

  02 ManfName PIC X(20).

  437

  Chapter 17 ■ DireCt aCCess Files

  WORKING-STORAGE SECTION.

  01 VehicleStatus PIC X(2).

  88 RecordFound VALUE "00".

  01 VehicleKey PIC 9(4).

  01 ReadType PIC 9.

  88 DirectRead VALUE 1.

  88 SequentialRead VALUE 2.

  01 PrnVehicleRecord.

  02 PrnVehicleNum PIC 9(4).

  02 PrnVehicleDesc PIC BBX(25).

  02 PrnManfName PIC BBX(20).

  PROCEDURE DIVISION.

  BEGIN.

  OPEN INPUT VehicleFile

  DISPLAY "Read type : Direct read = 1, Sequential read = 2 --> "

  WITH NO ADVANCING.

  ACCEPT ReadType

  IF DirectRead

  DISPLAY "Enter vehicle key (4 digits) --> " WITH NO ADVANCING

  ACCEPT VehicleKey

  READ VehicleFile

  INVALID KEY DISPLAY "Vehicle file status = " VehicleStatus />
  END-READ

  PERFORM DisplayRecord

  END-IF

  IF SequentialRead

  READ VehicleFile NEXT RECORD

  AT END SET EndOfVehiclefile TO TRUE

  END-READ

  PERFORM UNTIL EndOfVehiclefile

  PERFORM DisplayRecord

  READ VehicleFile NEXT RECORD

  AT END SET EndOfVehiclefile TO TRUE

  END-READ

  END-PERFORM

  END-IF

  CLOSE VehicleFile

  STOP RUN.

  DisplayRecord.

  IF RecordFound

  MOVE VehicleNum TO PrnVehicleNum

  MOVE VehicleDesc TO PrnVehicleDesc

  MOVE ManfName TO PrnManfName

  DISPLAY PrnVehicleRecord

  END-IF.

  438

  Chapter 17 ■ DireCt aCCess Files

  The first thing to note is that the SELECT and ASSIGN clause has a number of new entries. First, ORGANIZATION is now RELATIVE. Second, because a relative file allows you to access the records in the file directly or sequentially, you must have an ACCESS MODE phrase to say what kind of access you desire on the file. Three types of access are available: RANDOM (key-based access only), SEQUENTIAL (sequential only), and DYNAMIC (a mixture of keyed and sequential access). Third, to allow key-based access, you must specify a RELATIVE KEY phrase to tell the system where it can find the key value used for direct access. Note that the key mentioned here cannot be part of the record description.

  The final entry is the FILE STATUS clause. The FILE STATUS clause allows you to identify a two-character area of storage to hold the result of every I/O operation for the file. The FILE STATUS data item is declared as PIC X(2) in the WORKING-STORAGE SECTION. Whenever an I/O operation is performed on the file, some value is returned to FILE STATUS indicating whether the operation was successful. I introduce these FILE STATUS values as and when they occur; for this program, you only need to know that a value of "00" indicates that the operation (READ, in this case) was successful.

  The FILE STATUS clause is not restricted to direct access files. You can use it with sequential files, but that isn’t necessary because with those files there are not many states that you need to detect. However, with direct access files, a number of file states need to be detected. For instance, you need to detect when an attempt is made to READ, DELETE, or REWRITE a record when a record with that key value does not exist in the file. Similarly, you need to be able to detect when an attempt to WRITE a record finds that there is already a record with that key value in the file.

 

‹ Prev