You are on page 1of 88

11 March 2003

The Unit

• Delivered as IT52/IS22
• Lecturing by Richard Bland, practical support from Mr WS
Johnstone
• Unit co-ordinator: Richard Bland
• Email addresses etc are on the syllabus sheet
• Course materials will be placed on the WWW at appropriate
times as the unit proceeds

11 March 2003 IT52/IS22 COBOL 1

Teaching, Assessment, Textbook

• Daytime teaching
– 3 lectures per week, times on syllabus sheet
– 1 Practical session per week in 1A11 (starts week 3)
– 1 Tutorial per week (starts week 3)
– IT PGs have been allocated to groups, ISMs should see me
• Assessment
– A COBOL assignment (40%) and an exam (60%)
– Assignment date 3rd April
• Parkin, A. & Yorke COBOL for Students, 4th edition, Edward
Arnold, 1995
– or any other text based on the 85 standard
– if you buy MicroFocus COBOL (as used in this unit) for
your own machine, you get a reference manual as well

11 March 2003 IT52/IS22 COBOL 2

IT52/IS22 COBOL 1
11 March 2003

COBOL

• COBOL: COmmon Business-Oriented Language


– a language designed for commercial data processing
• That is: handling large amounts of data, normally a large number
of “records” with a regular structure
• “regular structure”: data are in fixed “fields” in the records:
123456789012345678901234567890 ..
Mr R Bland 7424
Mr CMIRattray 7429
– we talk about “the surname field” occupying “columns 8-27”
• COBOL is a language specifically designed for processing
fixed-format data with great speed and a high level of control
– accuracy, robustness, and control are very important

11 March 2003 IT52/IS22 COBOL 3

Some COBOL History

• COBOL is one of the oldest “third generation” languages


• It was developed in 1959 to replace machine code dependent
assemblers (about same time as FORTRAN)
• CODASYL committee: COnference on Data System Languages.
• Made up from Government agency reps
• Grace Hopper, who was on the committee, was the “mother” of
COBOL (and, on one version of the story, coined “bug”)
• First ANSI (American National Standards Institute) version was
COBOL 68, although it had been commonly used since 61
• COBOL became very popular in business. Led to 74, and 85
standards. The vast majority of COBOL programs in existence
today follow the 85 standard

11 March 2003 IT52/IS22 COBOL 4

IT52/IS22 COBOL 2
11 March 2003

Status Now

• 100+ billion of lines of COBOL exist today


• The is a considerable demand for COBOL programmers to work
on “legacy systems”
• (and in 1999 there was particular interest in ones that stored the
year in two digits ..)
• A great deal of development is still done in COBOL
– 5 billion lines of code per year?
• Several companies make version for PCs, UNIX, and other
operating systems.
• Still the choice for a business oriented language
• The new standard ("2002+") contains proposals for OO features:
but we shall focus on classic COBOL

11 March 2003 IT52/IS22 COBOL 5

COBOL 85 compared with the ALGOL family

• No block structure: all variables global


• Procedures ("Methods") are parameterless (unless externally
linked)
• Weaker typing
• Numbers: much closer to human arithmetic
– stress on length of number
– numbers decimal not floating-point
• I/O record oriented not stream oriented
• No recursion
• “Bigger” (because facilities not packaged as libraries)

11 March 2003 IT52/IS22 COBOL 6

IT52/IS22 COBOL 3
11 March 2003

Programming in COBOL compared with Java

• There are a number of differences in the paradigm


– a new way of thinking is required (not OO)
• COBOL is closer to the machine
• In terms of data:
– before the steps of the program, we reserve all the memory
that we shall need (instead of asking for new objects
dynamically)
– we think of memory as contiguous bytes (instead of hardly
thinking of memory at all)
• In terms of program flow:
– instead of an implied loop through events (e.g. waiting for a
mouse click), we explicitly program a loop through the input
data

11 March 2003 IT52/IS22 COBOL 7

The COBOL that we shall use

• We shall use the MicroFocus Personal COBOL for Windows,


running on the machines in 1A11 and CS labs
• This offers an environment (“Animator”) in which the program
can be edited and tested
• Notice that we shall not be producing executables, but MF .int
files
– these can be run by Animator
– or by special MF shells (RunW and RunFront)
• Personal COBOL offers features that we shall not be using
– Facilities to build programs that use the Windows GUI
– OO facilities that anticipate the forthcoming standard
• So we shall restrict ourselves to COBOL 85, with terminal i/o in
a plain text window
11 March 2003 IT52/IS22 COBOL 8

IT52/IS22 COBOL 4
11 March 2003

An aside: The set-up of your environment

• The names of files in the MS enviroments (MS-DOS, Windows


3.1, 95, 98, NT) usually end with a dot and three characters: the
extension)
• Windows allows you to hide these: but some people think that it
is better to be able to see the extensions
– you set this using the options under View in an Explorer
window (next slide)
• Each extension can be “associated” with one application
– for example, .ppt is usually associated with MS
PowerPoint

• If there is an association
– the file displays the icon of the application
– and that application starts when the icon is double-clicked
11 March 2003 IT52/IS22 COBOL 9

Aside continued: File extensions


• (It is easy to be confused by this,
and think that a file with a .ppt
extension “is a PowerPoint file”
– it should be, but isn’t
necessarily)
• The lab machines are set up thus:
– .cbl is associated with
Animator
– .int is associated with RunW
• So you ought to see appropriate
behaviour when you double-click
their icons

11 March 2003 IT52/IS22 COBOL 10

IT52/IS22 COBOL 5
11 March 2003

Hello, world

• Here’s a complete COBOL program:


* This is a demonstration program
*
PROCEDURE DIVISION.
DISPLAY "Hello, world"
STOP RUN.
– (we shall see later that each line starts with six blanks)
• We could either:
– Put this text in a plain ASCII file called (say) hello.cbl
(using any simple text editor, such as Notepad) and then
double-click the file’s icon to bring up Animator
– Bring up Animator from the Start button, and type in the text
directly, then save the file from Animator
• Let us try some of that:
11 March 2003 IT52/IS22 COBOL 11

Hello, world in Animator

• We can compile the program (using the button with a tick on it,
or through the Compile/Run menu)
– if there are errors, we can edit and recompile (Animator will
always save an altered file before recompilation)
• If Animator is open in Edit+Execute mode, then we can run the
program: otherwise we close, & reopen the file in Execute mode

11 March 2003 IT52/IS22 COBOL 12

IT52/IS22 COBOL 6
11 March 2003

Hello, world (continued)

• Animator puts the output into a plain black window


– to see it, you may need to cycle round the windows using alt-
tab
• We can step or free-run
• And we can set breakpoints
• We shall see later that we can inspect the values of variables as a
run proceeds

11 March 2003 IT52/IS22 COBOL 13

Layout of lines of code


• Before we look at the specific features of hello, a note about
the layout of a 74 standard program
– COBOL programs were typically entered on punched cards
(one program line = one punched card). It was a catastrophe
if the deck got dropped, and so the cards had sequence-
numbers punched on them in columns 1-6. (A dropped deck
could then be restored using a counter-sorter.)
– Column 7 was the indicator-area: '*' for a comment, '-' for a
continuation line (with e.g. a long text constant split across
the continuation)
– Columns 8-11 was Area A, where division, section and
paragraph names had to start (and some level numbers,
discussed later)
– Columns 12-72 were for everything else in the code
– Columns 73-80 were alternative locations for card-numbers
11 March 2003 IT52/IS22 COBOL 14

IT52/IS22 COBOL 7
11 March 2003

Layout of lines of code (continued)

• When disks got big and cheap enough, programs were held on
disk and the need for the above format disappeared
– non-standard formats appeared
• However, Animator preserves the special nature of columns 1-7
and 73-80
• I shall (try to) show program examples with the first six
characters omitted, and using Area A and Area B conventionally

11 March 2003 IT52/IS22 COBOL 15

Hello, world (continued)

• Some more points about the program text


– The full-stops are significant. And double-quotes (not single
quotes) in a standard-conforming program.
– We see two statements and one sentence. The full-stop
terminates a sentence.
– What terminates a statement?
– Not newline (can be split across lines)
– Can be some explicit terminator (full-stop, END-something) ...
– or the start of a new statement
– Comma and semicolon followed by space are equivalent to
space. This can be put to good or bad effect
ADD bonus overtime TO pay
ADD bonus, overtime TO pay
DISPLAY ; "Hello World", , STOP ; RUN.

11 March 2003 IT52/IS22 COBOL 16

IT52/IS22 COBOL 8
11 March 2003

Hello, world (continued)

• Yet more points about the program text


– Sentences can be grouped into (named) paragraphs (later).
(Our Procedure Division, above, has a single anonymous
paragraph.)
– Paragraphs into (named) sections (later)
– then divisions. Here we see the Procedure Division. This is
always present. In a program conforming to the 74 standard,
all four divisions must be present.

11 March 2003 IT52/IS22 COBOL 17

COBOL: That is data processing - I.E. D.P.


* This is a demonstration program
*
IDENTIFICATION DIVISION.
* (This division could be replaced by comments)
PROGRAM-ID. Hello.
AUTHOR. Richard Bland.
DATE-WRITTEN. February 3rd 2003.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. Viglen-Genie.
OBJECT-COMPUTER. Viglen-Genie.
DATA DIVISION.
PROCEDURE DIVISION.
DISPLAY "Hello, world"
STOP RUN.

– This has an empty Data Division because the program has no


variables. However ...

11 March 2003 IT52/IS22 COBOL 18

IT52/IS22 COBOL 9
11 March 2003

Answer, Echo, Answer


IDENTIFICATION DIVISION.
PROGRAM-ID. Echo.
AUTHOR. Richard Bland.
DATE-WRITTEN. February 3rd 2003.
ENVIRONMENT DIVISION.
*
DATA DIVISION.
WORKING-STORAGE SECTION.
77 x PIC 999.
*
PROCEDURE DIVISION.
DISPLAY "Please enter a number"
ACCEPT x
DISPLAY "That number was ", x
STOP RUN.
• We see that a variable is declared and used
• We can get Animator to show its current value

11 March 2003 IT52/IS22 COBOL 19

An echo from the East Indies


// Read a number from the keyboard and echo it
//
import java.io.*;
public class Echo {
public static void main(String[] args) {
String line ;
int x ;
BufferedReader br =
new BufferedReader(new
InputStreamReader(System.in)) ;
System.out.print("Please enter a number:") ;
try {
line = br.readLine() ;
x = Integer.parseInt(line) ;
System.out.println("That was " + x) ; }
catch (Exception e)
{System.out.println(e.getMessage()) ; }
} // main
} // class

11 March 2003 IT52/IS22 COBOL 20

IT52/IS22 COBOL 10
11 March 2003

Echo: syntax

• The statements in the Procedure Division are typical: they


consist of (imperative) verbs followed by (mainly) nouns and
prepositions
FEED cat
PUT canary INTO cage.
• We can use syntax formats or diagrams to describe all parts of
COBOL. In these notes I’ll use formats, as in (e.g.) Appendix D
of Parkin and Yorke. I’ll use italic for these
ACCEPT ident [FROM name]
• Caps for words to be entered as-is, l/c for an element to be
replaced
ACCEPT x

11 March 2003 IT52/IS22 COBOL 21

Syntax (continued)

• Square brackets enclose optional parts


ACCEPT x FROM DAY-OF-WEEK
* Integer from 1 (Mon) to 7, returned by system
• Underline indicates that word must be present if element is used.
DISPLAY { ident | literal} ... [WITH NO
ADVANCING]
DISPLAY "Enter a number" NO ADVANCING
• Curly brackets with a vertical bar indicate a choice
DISPLAY x
DISPLAY 42
DISPLAY "Goodbye"
• Three dots (ellipsis) indicate that the previous element can be
repeated as often as you like
DISPLAY "The number was" x ", was it not?"

11 March 2003 IT52/IS22 COBOL 22

IT52/IS22 COBOL 11
11 March 2003

Declaring variables
• Let us now turn to the Data Division of echo
DATA DIVISION.
WORKING-STORAGE SECTION.
77 x PIC 999.
• Before the detail, let's look at the big picture. The Data Division
of any COBOL program can consist of three Sections: File,
Working-Storage and Linkage. We shall not deal with the last.
The first two relate to COBOL's model of data movement.

11 March 2003 IT52/IS22 COBOL 23

COBOL's data model

• Parkin Figure E1
Data Division
File Section
Input File Input Record Output Record Output File
READ WRITE

Working-Storage Section

11 March 2003 IT52/IS22 COBOL 24

IT52/IS22 COBOL 12
11 March 2003

COBOL's data model (continued)


• In the echo program we used the low-volume verbs ACCEPT
and DISPLAY, used for terminal I/O
• The high-volume, file-related verbs are READ and WRITE
• In the general case, data movement is as follows:
– Input data are transferred to an input area which is
essentially a map of the input record.
– Output data are similarly written from an area which is a
map of the desired output record.
– The output area is built up in two ways: by moving data
from the input directly; and by moving data to working-
storage, transforming it and moving it to the output area
• We shall see examples later on. In the case of the present
example, we had no File Section because we had no files.

11 March 2003 IT52/IS22 COBOL 25

Returning to echo's Data Division


DATA DIVISION.
WORKING-STORAGE SECTION.
77 x PIC 999.
• This says that we are declaring a variable x. It is "at level 77":
which means that it has no internal structure and no defined
relationship to any other variable. The PIC clause shows that it
is numeric, integer, and can hold numbers 0-999. It occupies 3
locations in memory.
• If we experiment:
4 That number was 004
42 That number was 042
41. That number was 041
424 That number was 424
• It is not always easy to grasp what ACCEPT/DISPLAY are doing.
But a guess that three digits were being stored would be correct.
11 March 2003 IT52/IS22 COBOL 26

IT52/IS22 COBOL 13
11 March 2003

An Aside about ACCEPT

• With MF (but not all COBOLs), ACCEPT into a numeric always


produces a numeric. Consider the echo program:
Keyed Value Stored
123 123
12 012
1 001
– so far so good. But:
12X 012
1XY 001
ZXY 000
• This behaviour is defensible, but not much help if you want to
check user input. One possible solution involves constructs that
we shall cover later. For the moment, concentrate on dealing
with genuinely-numeric input.
11 March 2003 IT52/IS22 COBOL 27

First look at the PIC clause: decimal fractions


• If we were using READ the system would expect three digits
(possibly with leading blanks)
• In order to handle decimal points:
DATA DIVISION.
WORKING-STORAGE SECTION.
77 x PIC 99V9.
• This means that a decimal point is implied at the indicated
position. It is not held in the variable: and indeed it does not
appear on the output.
42 That number was 420
4.9 That number was 049
• We shall see later how to edit to obtain less brutal output.

11 March 2003 IT52/IS22 COBOL 28

IT52/IS22 COBOL 14
11 March 2003

First look at the PIC clause: signed numbers

• How about a sign?


77 x PIC S999.
• In this case the sign is stored in the same locations as the digits
(in an implementation-dependent way)
• There is an optional phrase:
[[SIGN IS] { LEADING | TRAILING } [SEPARATE
CHARACTER]]
• So we can write
77 x PIC S999 SIGN IS LEADING SEPARATE.
now the number is stored in four locations
• Instead of (e.g.) 9999999 we can write 9(7)

11 March 2003 IT52/IS22 COBOL 29

First look at the PIC clause: alphabetic and alphanumeric

• We have been looking at “simple” PIC clauses (as opposed to


edited ones, later). There are three types: numeric (as above),
and
• alphabetic ('A' - 'Z' and 'a' - 'z')
PIC AAAAA
PIC A(5)
• alphanumeric (any characters)
PIC XXXXX
PIC X(5)

11 March 2003 IT52/IS22 COBOL 30

IT52/IS22 COBOL 15
11 March 2003

Name-formation and constants

• We called our variable 'x'. In fact we can use up to 30


characters, using letters, digits, and hyphen (not first or last)
Pay-Rate
payrate
PayRate
Day-7
watch out for the reserved words! (Count)
• Alpha constants in double-quotes.
• There are symbolic constants (“figurative constants”)
ZERO ZEROS ZEROES SPACE SPACES
HIGH-VALUE LOW-VALUE
– so the following are equivalent:
MOVE 0 TO I
MOVE ZERO TO I

11 March 2003 IT52/IS22 COBOL 31

Constants continued, and VALUE


or
MOVE " " TO NAME
MOVE SPACES TO NAME
• In Working-storage only, we can declare-and-initialise
77 x PIC 999 VALUE IS ZERO.
77 Vat-Rate PIC 99V9 VALUE IS 17.5 .
• Question: why is it only in Working-storage that we can declare-
and-initialise?

11 March 2003 IT52/IS22 COBOL 32

IT52/IS22 COBOL 16
11 March 2003

More verbs

• We shall return to data-declaration and data-structures, but for


the next few slides we look at some new Procedure Division
verbs
• The arithmetic verbs: we start with ADD (and spend quite a long
time on it)
• We can have ADD-TO and ADD-GIVING
ADD { ident | literal } ...
TO {ident [ROUNDED]} ...
– ident is a variable-name, literal is a constant
– where does the result go??
ADD 1 TO Kount
ADD Vat TO Price
ADD Vat, Delivery TO Price
ADD 1 TO Kount, Stack-Ptr
ADD Vat TO Price ROUNDED
11 March 2003 IT52/IS22 COBOL 33

ADD (continued)
– rounding is to the number of decimal places specified in the
PIC of the result. 5 and over rounds up.
• The ADD-GIVING version is
ADD {ident | literal} ...
GIVING {ident [ROUNDED]} ...
• (We can have an optional TO before the final input operand. I
have omitted this in the syntax.)
• In both cases, the ellipsis in the result comes after the optional
ROUNDED. So we can construct a total in number of different
ways: to different precisions and with/without rounding
ADD x,y,z GIVING Int-Ans ROUNDED, Real-Ans
• Let's write a complete program:

11 March 2003 IT52/IS22 COBOL 34

IT52/IS22 COBOL 17
11 March 2003

A complete ADD example


* Addition
*
DATA DIVISION.
WORKING-STORAGE SECTION.
77 a PIC 99V999 VALUE 1.777 .
77 b PIC 99V99 VALUE ZERO .
77 c PIC 9V9 VALUE 5.5 .
77 d PIC 9V9 VALUE 5.5 .
PROCEDURE DIVISION.
ADD a TO b ROUNDED
DISPLAY "b is ", b
ADD c TO d
DISPLAY "d is ", d
STOP RUN.

11 March 2003 IT52/IS22 COBOL 35

What the example does

• The output is
b is 0178
d is 10
• The value for b is correct, but something nasty has happened to
d. What is the problem?
• It is this:
– the numbers to be added are aligned on their decimal points
– added
– and then moved to the result variable
– which in this case is too small
• In fact the syntax is more complicated: in both cases we can
have SIZE ERROR clauses

11 March 2003 IT52/IS22 COBOL 36

IT52/IS22 COBOL 18
11 March 2003

SIZE ERROR clauses


ADD { ident | literal } ...
TO {ident [ROUNDED]} ...
[ON SIZE ERROR imperative-statement]
[NOT ON SIZE ERROR imperative-statement]
[END-ADD]
– imperative-statement can be several statements
– To terminate this series of statements we use either full-stop
(74) or END-ADD (85).
– Let us first program on the assumption that any size error
should stop the program:

11 March 2003 IT52/IS22 COBOL 37

Add example (continued)


PROCEDURE DIVISION.
ADD a TO b ROUNDED
ON SIZE ERROR
DISPLAY "Size Error" ; STOP RUN
END-ADD
DISPLAY "b is ", b
ADD c TO d ON SIZE ERROR
DISPLAY "Size Error" ; STOP RUN
END-ADD
DISPLAY "d is ", d
STOP RUN.
• The output is
b is 0178
Size Error

11 March 2003 IT52/IS22 COBOL 38

IT52/IS22 COBOL 19
11 March 2003

ADD example in 74 style

• The 74 style with full-stops is a bit more succinct.


PROCEDURE DIVISION.
ADD a TO b ROUNDED
ON SIZE ERROR
DISPLAY "Size Error" ; STOP RUN.
DISPLAY "b is ", b
ADD c TO d ON SIZE ERROR
DISPLAY "Size Error" ; STOP RUN.
DISPLAY "d is ", d
STOP RUN.
• We could also anticipate later material about program structure
(“performing a paragraph”):

11 March 2003 IT52/IS22 COBOL 39

ADD example using PERFORM


PROCEDURE DIVISION.
Main-para.
ADD a TO b ROUNDED
ON SIZE ERROR
PERFORM Add-Error.
DISPLAY "b is ", b
ADD c TO d
ON SIZE ERROR
PERFORM Add-Error.
DISPLAY "d is ", d
STOP RUN.
Add-Error.
DISPLAY "Size Error" ; STOP RUN.
• This example introduces
– paragraph-names (note full-stops)
– the idea that we can ask for a paragraph to be PERFORMed:
that is, control passes to the code in the paragraph
11 March 2003 IT52/IS22 COBOL 40

IT52/IS22 COBOL 20
11 March 2003

The ADD example using NOT

• Alternatively we could program so that any size-error is non-


fatal
PROCEDURE DIVISION.
ADD a TO b ROUNDED
ON SIZE ERROR DISPLAY "Size Error"
NOT SIZE ERROR DISPLAY "b is ", b
END-ADD
ADD c TO d
ON SIZE ERROR DISPLAY "Size Error"
NOT SIZE ERROR DISPLAY "d is ", d
END-ADD
STOP RUN.
• There's no absolute "best way": it depends on circumstances.

11 March 2003 IT52/IS22 COBOL 41

Defensive programming

• Should we always test for size errors?


DATA DIVISION.
WORKING-STORAGE SECTION.
77 c PIC 9V9 .
77 d PIC 9V9 .
77 e PIC 99V9 .
PROCEDURE DIVISION.
...
ADD c, d GIVING e
• This can never have a size error
• - but suppose a later change alters the PICs of the input variables
• A sense of proportion must be kept: but bitter experience teaches
us the value of testing for “impossible” errors
– “Can’t happen” messages

11 March 2003 IT52/IS22 COBOL 42

IT52/IS22 COBOL 21
11 March 2003

SUBTRACT
• Subtract is very similar. First, the version without GIVING
SUBTRACT { ident | literal} ...
FROM {ident [ROUNDED]} ...
– The total of the values on the left is subtracted from each of
the variables on the right
SUBTRACT Tax, Insurance, Sports, Union FROM Pay
SUBTRACT 1 FROM Loop1, Loop2
• Then the version with GIVING
SUBTRACT { ident | literal} ...
FROM { ident | literal}
GIVING {ident [ROUNDED]} ...
– The total of the values on the left is subtracted from a single
value, and the result is stored, possibly in several variables
11 March 2003 IT52/IS22 COBOL 43

SUBTRACT (continued)

SUBTRACT a, b, c FROM 100 GIVING d


• Notice that with ADD-GIVING the TO was optional, but with
SUBTRACT-GIVING the FROM is compulsory
• Rounding can be used as with ADD
• We can also have the same size error clauses, and can terminate
the statement with END-SUBTRACT in the same style as with
ADD
• But do we need size error clauses? Surely subtracting something
always gives you a result smaller than the value you started
with?

11 March 2003 IT52/IS22 COBOL 44

IT52/IS22 COBOL 22
11 March 2003

MULTIPLY

• Versions with and without GIVING


MULTIPLY {ident | literal}
BY {ident [ROUNDED]} ...
– A single value on the left is used to multiply each of a
number of variables on the right
MULTIPLY {ident | literal}
BY {ident | literal}
GIVING {ident [ROUNDED]} ...
– Two values are multiplied together and the result is stored,
possibly in several variables
MULTIPLY x BY y GIVING z ROUNDED, w
• We can have size error clauses and END-MULTIPLY

11 March 2003 IT52/IS22 COBOL 45

DIVIDE
DIVIDE {ident | literal}
INTO {ident [ROUNDED]} ...
• A single value on the left is divided-into each of a number of
variables on the right
DIVIDE {ident | literal}
INTO {ident | literal}
GIVING {ident [ROUNDED]} ...
• A value is divided into another value and the result is stored,
possibly in several variables.
DIVIDE 2 INTO x GIVING y, z
• We can write this the other way round using BY
DIVIDE x BY 2 GIVING y, z
• Can have size error clauses and END-DIVIDE (and REMAINDER)
11 March 2003 IT52/IS22 COBOL 46

IT52/IS22 COBOL 23
11 March 2003

Some of these are wrong


MULTIPLY Salary BY 2
MUTLIPLY Salary BY 2 GIVING Delirium, Ecstasy
MULTIPLY 2 BY Salary
DIVIDE Cake INTO 5
DIVIDE 3 INTO Gaul
ADD 5, 6, 8, 3, 7, 4, 5, 4, 7 GIVING Outward
SUBTRACT 1, 2, 1, 1, 2, 1, 2, 1, 1
FROM Outward GIVING Handicapped
MULTIPLY x ROUNDED BY y
MULTIPLY x BY y ROUNDED
ADD Mark-up AND Tax TO Net GIVING Gross

11 March 2003 IT52/IS22 COBOL 47

COMPUTE

COMPUTE { ident [ROUNDED] } ...


= arithmetic-expression
– with possible size error clauses and END-COMPUTE
• the arithmetic expression is constructed using the usual operators
(** to raise to a power) and brackets
• strictly, a space on either side of each operator: usually the
compiler only enforces this for minus (why?)
• evaluation follows the usual precedence and left-to-right rules
COMPUTE Celsius = (Fahrenheit - 32) / 1.8
COMPUTE Area = 3.1416 * Radius ** 2
• some programmers feel it is safer to carry out the calculation in
stages

11 March 2003 IT52/IS22 COBOL 48

IT52/IS22 COBOL 24
11 March 2003

Transfer of control: IF

IF Tax > 100 THEN


DISPLAY "Surely not"
ELSE
DISPLAY "Oh, all right"
END-IF
• We shall look at conditions soon.
• The word THEN is optional, as is the ELSE part: and END-IF
was introduced in the 85 Standard as an option
IF Tax > 100 DISPLAY "Rats" .
• But the use of END-IF is strongly recommended. (The full-stop
closes all open IFs and so some nested constructions cannot be
coded in a natural way if it is used)

11 March 2003 IT52/IS22 COBOL 49

IF (continued)

• Each branch can contain a sequence of statements. (But,


obviously, no full-stops)
• (The old NEXT SENTENCE construct is unnecessary post-85)
• Obviously, we should adopt some sensible indentation
convention (such as two spaces)
• We can nest Ifs
IF c1 THEN
IF c2 THEN
s1
ELSE
s2
END-IF
ELSE
s3
END-IF

11 March 2003 IT52/IS22 COBOL 50

IT52/IS22 COBOL 25
11 March 2003

Matching ELSE with its IF


• In that example, we could omit the END-IFs
IF c1 THEN IF c1 THEN
IF c2 THEN IF c2 THEN
s1 s1
ELSE ELSE
s2 s2
END-IF ELSE
ELSE s3 .
s3
END-IF
• The version on the right has the same effect and is shorter...
• This temptation should be firmly resisted. Consider the
example on the next slide

11 March 2003 IT52/IS22 COBOL 51

Catastrophe caused by omitting inner END-IF

• The indentation suggests that the programmer thinks that these


two fragments are equivalent: but (s)he is wrong
IF c1 THEN IF c1 THEN
IF c2 THEN IF c2 THEN
s1 s1
END-IF ELSE
ELSE s2 .
s2
END-IF
• The ELSE is matched with the closest un-elsed IF.
• Moral: always put in the END-IFs
• (Note: for the equivalent of a C or Java switch (Pascal CASE)
see EVALUATE on Slide 174)

11 March 2003 IT52/IS22 COBOL 52

IT52/IS22 COBOL 26
11 March 2003

Transfer of control: Out-of-line PERFORM


• Using PERFORM is a bit like using a Java method
PROCEDURE DIVISION.
Main-para.
PERFORM Greeting
PERFORM Doit
PERFORM Sign-Off
STOP RUN.
Doit.
DISPLAY "Please enter a number"
ACCEPT x
DISPLAY "That number was " x .
Greeting.
DISPLAY "Hello".
Sign-off.
DISPLAY "Goodbye".
• The blocks of code are terminated by full-stop-followed-by-new-
paragraph-name (or by end of program text)
11 March 2003 IT52/IS22 COBOL 53

Out-of-line PERFORM, continued


• When the flow of control encounters PERFORM
– control passes to the paragraph to be performed (like a jump)
– but the system remembers where we jumped from
– and at the end of the paragraph we jump back to the
statement after the PERFORM
• So the example on the previous slide is equivalent to
PROCEDURE DIVISION. Greeting
DISPLAY "Hello".
DISPLAY "Please enter a number"
Doit ACCEPT x
DISPLAY "That number was " x .
DISPLAY "Goodbye".
STOP RUN.
Sign-off

11 March 2003 IT52/IS22 COBOL 54

IT52/IS22 COBOL 27
11 March 2003

Benefits of out-of-line PERFORM

• The example on the last two slides shows (in a trivial example)
how we can obtain clarity by moving details into subsidiary
paragraphs
• The first paragraph then corresponds to a top-level description of
the algorithm. We refer to this as the “main paragraph”
– for example, many programs have a three-phase structure:
initialise, process, tidy-up
* This is the Procedure Division's first para
Main-para.
PERFORM Start-up
PERFORM Process-data
PERFORM Tidy-up
STOP RUN.
* The code for the three paragraphs follows

11 March 2003 IT52/IS22 COBOL 55

Global variables

• However, procedures / functions / methods in Pascal / C / Java /


Fortran can have private variables
• and we can pass parameters to them, applying them to particular
objects
// draw circle at (10,10), radius 2
mycircle.draw(10,10,2) ;

• In COBOL, on the other hand, all paragraphs share the same


variables. All variables are “global”
• Instead of passing parameters, we initialise the variables that we
know that the paragraph will use, and perform the paragraph.
On return, we use the variables as modified by the paragraph
• There should always be comments at the top of each paragraph
to say what variables are used and which are changed
11 March 2003 IT52/IS22 COBOL 56

IT52/IS22 COBOL 28
11 March 2003

Out-of-line PERFORM (continued)

• On Slide 54, the paragraphs were in an order that showed that


control does not simply fall through from paragraph to paragraph
• Here’s an extension of PERFORM
PROCEDURE DIVISION.
Main-para.
PERFORM Greeting THROUGH Sign-off.
STOP RUN.
Greeting.
DISPLAY "Hello".
Doit.
DISPLAY "Please enter a number" .
ACCEPT x .
DISPLAY "That number was " x .
Sign-off.
DISPLAY "Goodbye".
• We can spell THROUGH as THRU

11 March 2003 IT52/IS22 COBOL 57

Order of execution of COBOL paragraphs

• In C, Java, Pascal, Fortran (etc) the only way of entering a


procedure/function/method is by an explicit call
– and whenever we leave it, we return to the point after the call
• In COBOL, too, we can PERFORM a paragraph, in which case
– when we get to the end of the called paragraph we return to
the point after the call
• But in COBOL we can also execute a paragraph just by falling
off the end of the paragraph before, in which case we don't
return anywhere: we just fall into the next paragraph
• The next slide has an unlikely but possible arrangement that
illustrates these two possibilities

11 March 2003 IT52/IS22 COBOL 58

IT52/IS22 COBOL 29
11 March 2003

Order of execution (continued)

PROCEDURE DIVISION.
Main-para.
DISPLAY "Main-para".
A.
DISPLAY "A".
B.
DISPLAY "B1"
PERFORM A
DISPLAY "B2".
• What is the order of execution?
• So: we executed paragraph A twice
– the first time we fell into it (and so we fell out of it when it
was finished)
– the second time we jumped into it with PERFORM (and so we
jumped back when it was finished).

11 March 2003 IT52/IS22 COBOL 59

Order of execution: STOP


• Programs don’t always need STOP
– because they will stop anyway if they are about to go past
the last line
– so we only need as explicit STOP if the program is meant to
stop at some earlier point
– as in, say, Slide 54
• But STOP is normally a useful visual clue. We might expect to
find it at the end of a “main-para” or a “closedown” para

11 March 2003 IT52/IS22 COBOL 60

IT52/IS22 COBOL 30
11 March 2003

Nested Out-of-line PERFORMS


• Of course, the code executed as a result of a PERFORM may itself
contain PERFORM.
Main-para. Main-para.
... ...
PERFORM A PERFORM A THRU C
STOP RUN. STOP RUN.
A. A.
... ...
PERFORM B PERFORM B
... ...
B. B.
... ...
C.
...
• These are nested PERFORMs
– while PERFORMing A, we PERFORM B
11 March 2003 IT52/IS22 COBOL 61

Nested Out-of-line PERFORMS (continued)


• We say that the range of a PERFORM is all the statements
executed as the result of the PERFORM.
• The rule for nesting: the range of the inner must lie entirely
outside the range of the outer (left-hand example) or entirely
within it (right-hand example)
• The ranges must not overlap, or share the same end point.
• (MF COBOL does not enforce this rule, and it even allows
recursion (a procedure that calls itself). But this is very non-
standard.)
• (We can speculate where the rule comes from: it allows the
implementer to do the returns by patching the code at run-time.)

11 March 2003 IT52/IS22 COBOL 62

IT52/IS22 COBOL 31
11 March 2003

Out-of-line PERFORM : loops

• There are three other optional additions: these give us various


types of loop
[num TIMES]
[UNTIL condition]
[VARYING ident FROM num BY num UNTIL condition]
– num is an integer variable or constant
– we shall look at conditions in detail later
– “until” here describes a test that (by default) is done at the
top of the loop (a “leading” test)
PERFORM Read-Line 2 TIMES
PERFORM Read-Line UNTIL End-File = "Y"
PERFORM Add-up VARYING i FROM 1 BY 1
UNTIL i > 10

11 March 2003 IT52/IS22 COBOL 63

Types of loop

• The use of these is obvious:


• If you don’t need a loop variable inside the loop
– For a condition-controlled loop, equivalent to while, use
plain UNTIL condition
– For a count-controlled loop, use plain num TIMES
• But if you do need a loop variable inside the loop, use VARYING
• As an example, let’s compute factorials:
1! is 1
2! is 2*1 = 2
3! is 3*2*1 = 6
– factorials are used in all sorts of ways (for example, in
computing probabilities)
– they get very big!

11 March 2003 IT52/IS22 COBOL 64

IT52/IS22 COBOL 32
11 March 2003

PERFORM-VARYING
* Form factorial n
DATA DIVISION.
WORKING-STORAGE SECTION.
77 i PIC 99.
77 n PIC 99.
77 fact PIC 99999.
PROCEDURE DIVISION.
DISPLAY "Enter n: " WITH NO ADVANCING
ACCEPT n
MOVE 1 TO fact
PERFORM Mult-para VARYING i FROM 1 BY 1
UNTIL i > n
DISPLAY n, "! is ", fact
STOP RUN.
Mult-para.
MULTIPLY i BY fact
ON SIZE ERROR
DISPLAY "Overflow”
STOP RUN
END-MULTIPLY.

11 March 2003 IT52/IS22 COBOL 65

Loops (continued) : In-line PERFORM

• In the 74 Standard, repeatedly performing a paragraph was the


only form of loop
• But the 85 Standard introduced in-line loops. Here the code-
sequence follows the verb.
PERFORM UNTIL No-more = "Y"
...
END-PERFORM

PERFORM VARYING i FROM 1 BY 1 UNTIL i > 10


...
END-PERFORM
• If the body of the loop is fairly small, then use in-line code

11 March 2003 IT52/IS22 COBOL 66

IT52/IS22 COBOL 33
11 March 2003

Sample program: count-controlled out-of-line loop


* Average of five numbers read from keyboard
DATA DIVISION.
WORKING-STORAGE SECTION.
77 x PIC 999.
77 average PIC 999.
77 total PIC 9999.
77 i PIC 9.
*
PROCEDURE DIVISION.
Main-para.
MOVE ZERO TO total
PERFORM Read-para 5 TIMES
DIVIDE 5 INTO total GIVING average ROUNDED
DISPLAY "Average is " average
STOP RUN.
Read-para.
* Read a number from a line and add to "total"
DISPLAY "Please enter a number: "
WITH NO ADVANCING
ACCEPT x
ADD x TO total.

11 March 2003 IT52/IS22 COBOL 67

Sample program re-written with in-line loop

• We can re-write this to use in-line code


PROCEDURE DIVISION.
Main-para.
MOVE ZERO TO total
PERFORM 5 TIMES
DISPLAY "Please enter a number: "
WITH NO ADVANCING
ACCEPT x
ADD x TO total
END-PERFORM
DIVIDE 5 INTO total GIVING average ROUNDED
DISPLAY "Average is " average
STOP RUN.
• In this case (because the code is short) the in-line version is
probably clearer

11 March 2003 IT52/IS22 COBOL 68

IT52/IS22 COBOL 34
11 March 2003

Loops (continued): trailing test

• Leading tests are far more common than trailing tests


• We can obtain a trailing test (Pascal REPEAT-UNTIL, or C (or
Java) do-while) by inserting the optional element WITH TEST
AFTER
* Perform at least once
PERFORM Body-para
WITH TEST AFTER UNTIL Got-one = "Y"
* Perform 0 to n times
PERFORM Body-para
VARYING i FROM 1 BY 1 UNTIL i > n
* Perform at least once
PERFORM Body-para
WITH TEST AFTER
VARYING i FROM 1 BY 1 UNTIL i = n

11 March 2003 IT52/IS22 COBOL 69

Writing conditions (simplified)

• Conditions can be simple or complex.. Here are two “simple”


ones:
Tax = 42
Tax NOT > 100
• Paradoxically, complex ones are easy: they are just simple ones
connected with AND OR brackets and NOT
Tax > 100 AND NOT (Age > 65)
• “Simple” ones are quite complicated to describe:
– Relation
– Class
– Condition-name
– (Sign (redundant: can use relation))
– (Switch-status (specialised))
11 March 2003 IT52/IS22 COBOL 70

IT52/IS22 COBOL 35
11 March 2003

Relation conditions

• These have the form:


arith-exp rel-op arith-exp
– arith-exp is “arithmetic expression”: in the simplest case,
just a variable name or a constant
Tax
42
(Net + Markup) * 1.175
– a rel-op is a “relation operator”: > >= = < <= possibly
preceded by NOT (examples on previous slide)
– These can be spelled out in words if you like
Age >=21
Age IS GREATER THAN OR EQUAL TO 21
– and there are multiple forms like EXCEEDS

11 March 2003 IT52/IS22 COBOL 71

The evaluation of relation conditions

• If both operands are simple numeric, ordinary rules apply


• If both are non-numeric, then
– compare chars l-to-r
– pad shorter with trailing spaces (unlike e.g. C)
– use collating sequence implied (native) or specified in
OBJECT-COMPUTER paragraph
• If mixed (!)
– if the numeric is integer then it’s treated as a sequence of
characters
– otherwise it is an error (but it’s not clear where this error is
detected: the MF compiler doesn’t fault it)
– but these are shady dealings anyhow

11 March 2003 IT52/IS22 COBOL 72

IT52/IS22 COBOL 36
11 March 2003

Class condition

• The class condition has the form


ident IS [NOT] class-name
• the predefined class-names are NUMERIC, ALPHABETIC,
ALPHABETIC-LOWER and ALPHABETIC-UPPER
WORKING-STORAGE SECTION.
77 Month PIC AAA.
PROCEDURE DIVISION.
DISPLAY "Please enter a month, JAN to DEC”
ACCEPT Month
IF Month NOT ALPHABETIC-UPPER
DISPLAY "Wrong Format" ; STOP RUN
END-IF
• This is useful, but the example is rather crude in its approach.
We can do better using condition-names
11 March 2003 IT52/IS22 COBOL 73

Condition-names

• An (elementary) variable can have an associated variable called


a condition-name. We regard the condition-name as being true
or false: that is, the name itself is (all of) a simple condition
IF valid-data THEN ...
• The mechanism is best explained through an example:
WORKING-STORAGE SECTION.
77 Month PIC AAA.
88 Valid-Month VALUE "JAN" "FEB" "MAR"
"APR" "MAY" "JUN" "JUL"
"AUG" "SEP" "OCT" "NOV" "DEC".
PROCEDURE DIVISION.
DISPLAY "Please enter a month, JAN to DEC"
ACCEPT Month
IF NOT Valid-Month
DISPLAY "Wrong Format" ; STOP RUN

11 March 2003 IT52/IS22 COBOL 74

IT52/IS22 COBOL 37
11 March 2003

Condition-names (continued)

• We can associate several condition-names with a variable


77 Lottery-number PIC 99.
88 L-num-unlucky VALUE 13.
88 L-num-date VALUE 1 THRU 31.
88 L-num-invalid VALUE 0, 51 THRU 99.
PROCEDURE DIVISION.
DISPLAY "Please enter a lottery number, 1-50"
ACCEPT Lottery-number
IF L-num-invalid
DISPLAY "That's not a valid number"
ELSE
DISPLAY "That's a valid number"
IF L-num-date
DISPLAY "Everyone chooses birthdays"
END-IF
IF L-num-unlucky
DISPLAY "Lucky for some!"
END-IF
END-IF
11 March 2003 IT52/IS22 COBOL 75

Loop and condition-name

• We can put together several pieces of the preceding material:


77
Lottery-number PIC 99.
88 L-num-valid VALUE 1 THRU 50.
PROCEDURE DIVISION.
Main-para.
PERFORM Get-num
DISPLAY "That was ", Lottery-number
STOP RUN.
*
* Return valid Lottery-number, obtained from
* the keyboard
Get-num.
PERFORM WITH TEST AFTER UNTIL L-num-valid
DISPLAY "Enter a lottery number, 1-50"
ACCEPT Lottery-number
IF NOT L-num-valid
DISPLAY "Wrong format"
END-PERFORM.

11 March 2003 IT52/IS22 COBOL 76

IT52/IS22 COBOL 38
11 March 2003

Group and elementary

• So far, we have seen only two level-numbers, 77 and 88. 77 was


used for unstructured working-storage, 88 for condition-names
• Data in a COBOL program are more usually arranged in a
hierarchy:

Student-record

Student-number Student-name Degree-scheme

Year Seq Surname Initials Title

11 March 2003 IT52/IS22 COBOL 77

Hierarchical data

• The terminal nodes of the tree are elementary items: single


variables each with a PIC (and hence a type defined by that PIC)
• The interior nodes of the tree are group items. They do not have
PICs and are all of type “alphanumeric” (even though they may
be entirely composed of numeric items)
• The length of an elementary item can be deduced from its PIC
• The length of a group item is the sum of the lengths of its
components

11 March 2003 IT52/IS22 COBOL 78

IT52/IS22 COBOL 39
11 March 2003

Level-numbers

• We declare these structures using level-numbers 01 to 49


– reserving 01 for complete records (the top level)
– leaving gaps (01, 05, 10, etc) to allow for possible definition
of intermediate layers later
– 01 in Area A, others in Area B
• All items immediately subordinate to a given item should be
declared with the same level number

11 March 2003 IT52/IS22 COBOL 79

Declaration of hierarchical data in records


DATA DIVISION.
WORKING-STORAGE SECTION.
01 Student-record.
05 Stu-num.
10 Stu-num-year PIC 99.
10 Stu-num-seq PIC 9(5).
05 Stu-name.
10 Stu-name-surname PIC X(20).
10 Stu-name-inits PIC X(3).
10 Stu-name-title PIC A(4).
05 Stu-degree PIC X(6).
• How long is the whole record?
• It makes no sense to say ADD 1 TO Stu-num (and the compiler
should say so)
• It makes complete sense to say DISPLAY Student-record

11 March 2003 IT52/IS22 COBOL 80

IT52/IS22 COBOL 40
11 March 2003

Declaration of records (continued)

• We can declare constant parts of records (in working-storage)


01 Student-record-out.
05 Stu-num.
10 Stu-num-year PIC 99.
10 PIC X VALUE ":" .
10 Stu-num-seq PIC 9(5).
• In pre-85 programs, these anonymous elementary items were all
given the name FILLER
10 FILLER PIC X VALUE ":" .
• In fact, we can have a record that is all fillers

11 March 2003 IT52/IS22 COBOL 81

Declaration of records (continued)


01 Column-headings.
05 PIC A(7) VALUE "NUMBER".
05 PIC A(8) VALUE SPACES.
05 PIC A(4) VALUE "NAME".
05 PIC A(8) VALUE SPACES.
05 PIC A(7) VALUE SPACES.
05 PIC A(6) VALUE "DEGREE".
• Then DISPLAY Column-headings will output headings in the
right places for (the first version of) the student record

11 March 2003 IT52/IS22 COBOL 82

IT52/IS22 COBOL 41
11 March 2003

MOVE (first look)

• Coming from an Algol-family background we tend to think of


MOVE as being just assignment: but there is more to it than that.
MOVE {ident | literal} TO ident ...
• We speak of the source and receiving items. What happens in
the move is determined by their types. (Remember that a group
item is alphanumeric)
• If source and receiving items are both alphabetic or
alphanumeric, then the item is left-justified in the receiver and
space-filled or truncated as necessary
• Note the figurative constant ALL literal
MOVE ALL "*~" TO Out-line

11 March 2003 IT52/IS22 COBOL 83

MOVE (continued)

• If source and receiving items are both numeric,


– align the decimal point
– truncate/zero-fill at each end
– if receiver is unsigned, it gets absolute value
• It is possible to have moves between numeric and alphanumeric
- the transmitted item must be an integer
• Examples of moves
N-var PIC 999V99 .
A-var PIC X(6) .
MOVE 12 TO N-var 01200
MOVE "Ed" TO A-var Ed____
MOVE 1234.567 TO N-Var 23456
MOVE "Edinburgh" TO A-Var Edinbu

11 March 2003 IT52/IS22 COBOL 84

IT52/IS22 COBOL 42
11 March 2003

Corresponding
• There is a wonderful extension of MOVE. First we have to re-
visit our data declarations
• The names of data-items need not be unique: they must only be
unique within their wider group-item.
01 Home-address.
05 Street PIC X(20).
05 Town PIC X(20).
05 Postcode PIC X(8).
01 Work-address.
05 Street PIC X(20).
05 Town PIC X(20).
05 Postcode PIC X(8).
• We make references unique by qualification by OF or IN
MOVE "FK9 4LA" TO Postcode OF Work-address

11 March 2003 IT52/IS22 COBOL 85

Corresponding (continued)

• The amazing move:


MOVE CORRESPONDING group-item1 TO group-item2
• The move is between all pairs of elementary items within the
two groups that match in name (and are 01-49 and not FILLER)
01 Student-record.
05 Stu-name.
10 Stu-name-surname PIC X(20).
10 Stu-name-inits PIC X(3).
10 Stu-name-title PIC A(4).
* etc
01 Student-out.
05 Stu-name.
10 Stu-name-title PIC A(4).
10 PIC X VALUE SPACE.
10 Stu-name-inits PIC X(3).
10 PIC X VALUE SPACE.
10 Stu-name-surname PIC X(20).
11 March 2003 IT52/IS22 COBOL 86

IT52/IS22 COBOL 43
11 March 2003

Corresponding (continued)
• Assuming we have data in Student-record (from a file,
perhaps) we could say
MOVE CORRESPONDING Student-Record
TO Student-out
DISPLAY Student-out
• This example shows that the fields can be re-arranged in the two
group-items
• Also, there need not be a complete correspondence: fields (on
either side) that do not match are just ignored
• This kind of MOVE is very powerful, but
– you can lose track of what is copied and what is ignored
– it can involve the use of lengthy identifiers (as we shall see)

11 March 2003 IT52/IS22 COBOL 87

Files: Overview

• As in most programming languages, a file will have an external


name, governed by the conventions of the host system (e.g.
Transact.dat)
• But within the program it will be referred to by an internal name,
governed by the conventions of the language (e.g.
Transact-file)
• The two are connected at a single point in the code
• In COBOL this happens in the Environment Division.
• Thereafter we use the internal name
– Declaring the structure of the record(s) in the Data Division
– and using the verbs OPEN, READ, WRITE and CLOSE in the
Procedure Division

11 March 2003 IT52/IS22 COBOL 88

IT52/IS22 COBOL 44
11 March 2003

Reading a (sequential) file: example plus commentary

• Starting with the Environment Division:


ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT File-in ASSIGN TO "Input.dat"
ORGANIZATION IS LINE SEQUENTIAL.
– The SELECT connects the internal name to the external
– The external name here is a literal: if your OS is case-
sensitive, be very careful!
– Or could be a symbolic reference (set by the OS: e.g. in an
environment variable).
– Or we can have ASSIGN DYNAMIC with an alpha variable
(so we could e.g. capture the filename from the keyboard))

11 March 2003 IT52/IS22 COBOL 89

Reading a file: example plus commentary (continued)


– organiZation
– Line sequential is an MF feature. It makes “... your COBOL
system ... compatible ... with the editor software in any ...
system.” You must use this clause on MF for the PC. On
most systems you can miss out the ORGANIZATION clause
• Now the Data Division:
DATA DIVISION.
FILE SECTION.
FD File-in.
01 Student-record.
05 Stu-num.
Etc
• The FD prefaces the declaration of a record that will act as an
input buffer. Note the use of the internal name

11 March 2003 IT52/IS22 COBOL 90

IT52/IS22 COBOL 45
11 March 2003

Reading a file: example plus commentary (continued)


– We have (exactly) one FD for each file referenced in the
Environment Division
– but we can have one or more descriptions at the 01 level for
that FD. We would have this if we expected records in
several different formats. It is an implicit redefinition of the
input buffer for this file (but the lengths may vary)
• Now we have any working-storage declarations. These will
include variables to keep track of the status of our file(s)
01 Flags.
05 File-in-eof-flag PIC A VALUE "N".
88 File-in-ended VALUE "Y".
• On to the Procedure Division. Here we shall open the file, read
to the end, and close it

11 March 2003 IT52/IS22 COBOL 91

Reading a file: example plus commentary (continued)


• The syntax of OPEN
OPEN [INPUT internalname ...]
[OUTPUT internalname ...]
[EXTEND internalname ...]
OPEN INPUT File-in
• This opens the file and positions it at the start.
• Now we must construct a read loop. Central fact: the only way
we can tell if we are at EOF is by trying to read: a Cobol READ
will either read a record or detect EOF. We need to implement
the following algorithm:
read
while not at EOF
process record just read
read

11 March 2003 IT52/IS22 COBOL 92

IT52/IS22 COBOL 46
11 March 2003

Reading a file: example plus commentary (continued)


• The syntax of READ
READ internalname [INTO ident]
[AT END imperative-statement]
[END-READ]
– why is the INTO part optional? Because the data is always
read into the associated buffer (i.e. all the 01 records under
the FD): this merely gives us the option of having another
copy somewhere else
– if the actual data read is too long, error
– if it is too short, then the remainder of the buffer is (usually)
unaltered (MF line sequential will space-fill)
– imperative-statement can be several statements (remember to
terminate the sequence!
– If EOF but no AT END, error

11 March 2003 IT52/IS22 COBOL 93

Reading a file: example plus commentary (continued)

• We shall put our READ into its own paragraph (because it’s
quite a long bit of code and we need it twice)
Read-record.
READ File-in
AT END
MOVE "Y" TO File-in-eof-flag
CLOSE File-in
END-READ.
• (Remember that the flag has an associated condition-name: we
shall use that to control the read loop)
• Here’s the whole of the Procedure Division:

11 March 2003 IT52/IS22 COBOL 94

IT52/IS22 COBOL 47
11 March 2003

Reading a file: example plus commentary (continued)

Main-para.
OPEN INPUT File-in
PERFORM Read-record
PERFORM UNTIL File-in-ended
* Process the record (just display)
DISPLAY Student-record
PERFORM Read-record
END-PERFORM
STOP RUN.
Read-record.
READ File-in
AT END
MOVE "Y" TO File-in-eof-flag
CLOSE File-in
END-READ.

11 March 2003 IT52/IS22 COBOL 95

More than one type of input record

• We saw above that there can be several 01 definitions under a


single FD
• Suppose our input data look like this:
19712345Davidson
21997A31311A
21997A46113C
19912345Wilkinson-Smyth
22000S31322A
22000S46122B
22000S31322F
• There are two kinds of record
• Header records start with ‘1’, detail records start with ‘2’
– Headers have registration-number and name
– Details have semester, unit-code and grade

11 March 2003 IT52/IS22 COBOL 96

IT52/IS22 COBOL 48
11 March 2003

More than one type of input record (continued)

• We give an 01 definition for each


DATA DIVISION.
FILE SECTION.
FD Students-file.
01 Header-rec.
05 Rec-type-H PIC X.
88 Is-header VALUE IS "1".
05 Regno PIC 9(7).
05 Student-name PIC X(30).
01 Detail-rec.
05 Rec-type PIC X.
05 Semester PIC X(5).
05 U-code PIC X(4).
05 Grade PIC XX.
• There is only one buffer area for the input record (38 bytes long)
• The two 01s give different identifiers for the same area

11 March 2003 IT52/IS22 COBOL 97

More than one type of input record (continued)


PROCEDURE DIVISION.
OPEN INPUT Students-file
PERFORM Read-S-record
PERFORM UNTIL S-file-ended
IF Is-header
DISPLAY Regno, " ", Student-name
ELSE
DISPLAY " ", Semester, " ",
U-code, " ", Grade
END-IF
PERFORM Read-S-Record
END-PERFORM
STOP RUN.
* Read-S-Record follows ...
9712345 Davidson
1997A 3131 1A
1997A 4611 3C
9912345 Wilkinson-Smyth
2000 S3132 2A
2000 S4612 2B
2000 S3132 2F
11 March 2003 IT52/IS22 COBOL 98

IT52/IS22 COBOL 49
11 March 2003

Writing a (sequential) file

• Writing a file doesn’t introduce much new material.


WRITE recordname [FROM ident]
– notice the potentially confusing (but necessary) fact that
READ references a (internal) filename but WRITE references
a record (one of those specified under an FD). The system
writes to the file associated with that record
– the optional FROM part gives us an implied move which
takes place before the write. The ident must not be part of
the file’s record-area
– the contents of the record-area are “unavailable” after the
write
– trailing spaces are removed in Line Sequential

11 March 2003 IT52/IS22 COBOL 99

Demonstration: read, transform, write

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT File-in ASSIGN TO "Input.dat”
ORGANIZATION IS LINE SEQUENTIAL.
SELECT File-out ASSIGN TO "Output.dat”
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD File-in.
01 Student-record.
* etc
FD File-out.
01 Student-out.
* etc

11 March 2003 IT52/IS22 COBOL 100

IT52/IS22 COBOL 50
11 March 2003

Demonstration: read, transform, write (continued)

WORKING-STORAGE SECTION.
01 Flags.
05 File-in-eof-flag PIC A VALUE "N".
88 File-in-ended VALUE "Y".
PROCEDURE DIVISION.
Main-para.
OPEN INPUT File-in
OUTPUT File-out
PERFORM Read-record
PERFORM UNTIL File-in-ended
MOVE CORRESPONDING Student-record
TO Student-out
WRITE Student-out
PERFORM Read-record
END-PERFORM
CLOSE File-out
STOP RUN.
* Read-record para just as before

11 March 2003 IT52/IS22 COBOL 101

Edited PICs

• We have seen how to read structured input and write structured


output
• So far, all our PIC clauses have been “simple”. These were all
we needed for input: but our output was very crude.
• The basic idea of “editing” : we MOVE data from a variable with
a “simple” PIC to a variable with an “edited” PIC, and this
causes formatting to take place. (Or as the target of GIVING)
• This extends the action of MOVE, adding to its power
– but the basic principle remains the same: the effect of MOVE
is determined by the types of the source and receiving items
– the 85 Standard introduced “de-editing” - moves from edited
items to simple items

11 March 2003 IT52/IS22 COBOL 102

IT52/IS22 COBOL 51
11 March 2003

Simple example of editing


DATA DIVISION.
WORKING-STORAGE SECTION.
01 Variables.
05 Simple PIC 999.
05 No-zero PIC ZZ9.
PROCEDURE DIVISION.
DISPLAY "Please enter a number”
ACCEPT Simple
MOVE Simple TO No-zero
DISPLAY "Original o/p was '", Simple,
"', edited format is '", No-zero,
"'"
• The Z editing character gives “zero-suppression”
Please enter a number
4
Original o/p was '004', edited format is ' 4'

11 March 2003 IT52/IS22 COBOL 103

Editing in detail: Alphanumeric edited


• Alphanumeric PICs contain Xs
• Alphanumeric edited PICs contain, additionally, one or more of
B / 0 (zero). These are insertion characters that are added
during a move.
05 Date-1 PIC XX/XXX/XXXX.
05 Date-2 PIC XXBXXXBXXXX.
MOVE "25Feb1998" TO Date-1, Date-2
will give 25/Feb/1998 and 25 Feb 1998 in the target
variables
• Notice that we can still calculate the width of a variable. These
are 11 locations long. This is a general point: we can always
work out how long an item is

11 March 2003 IT52/IS22 COBOL 104

IT52/IS22 COBOL 52
11 March 2003

Editing in detail: Numeric edited


• Numeric PICs contain S 9 V
• Numeric edited PICs don't (usually) contain S V , but do
contain, additionally, one or more of a range of other characters
that control the formatting.
• Editing takes places as a result of a MOVE to a numeric-edited
item, or as the result of GIVING
• A numeric-edited data item is not numeric - the only
meaningful things you can do with it are:
– move it to an alphanumeric
– output it
– you cannot do arithmetic with it

11 March 2003 IT52/IS22 COBOL 105

Numeric edited in detail


The characters in numeric edited PICs are:
• , B / 0 (zero). (Simple insertion characters)
05 Num-1 PIC 9,999,999.
05 Num-2 PIC 9B999B999.
MOVE 1000000 TO Num-1, Num-2
will give 1,000,000 and 1 000 000 in the target variables
(more on comma later)
• the special insertion character full-stop. This replaces V and
causes an actual full-stop to appear in the result
05 DP-raw PIC 9V99 .
05 DP-edited PIC 9.99 .
DIVIDE 1 BY 100 GIVING DP-raw, DP-edited
will give 001 (numeric) and 0.01 (non-numeric) in the target
variables (more on full-stop later)
11 March 2003 IT52/IS22 COBOL 106

IT52/IS22 COBOL 53
11 March 2003

Numeric edited in detail (continued)


• £ + - DB CR as fixed insertion characters. (I am using £ to
indicate currency-sign (see Slide 110).) These are fixed because
– plus or minus must be first or last in the PIC
– DB or CR must be last in the PIC
– £ must be first, or after plus or minus
05 Balance-out PIC £999.99BDB .
* Debit is 200 and Balance is 100
SUBTRACT Debit FROM Balance GIVING Balance-out
will give £100.00 DB in the target variable
• if the result is +ve then only plus is inserted: the others are
replaced by space(s).
• if the result is -ve then plus is inserted as minus: the others are
inserted as themselves
11 March 2003 IT52/IS22 COBOL 107

Numeric edited in detail (continued)


• If we have repeated £ + - then these are floating insertion
characters, “floating” because the symbol “floats” to the right, to
the first non-zero digit, with spaces coming in from the left
05 Balance-out PIC £££9.99BDB .
* Debit is 100 and Balance is 105.75
SUBTRACT Debit FROM Balance GIVING Balance-out
will give __£5.75___ in the target variable (showing blanks
as underscores for clarity)
if Debit is 110 and Balance is 105.75 then we get
__£4.25_DB
• Z * are the zero-suppression characters. They cause leading
zeros to be replaced by space or asterisk
05 Cheque-amount PIC £**9.99 .

11 March 2003 IT52/IS22 COBOL 108

IT52/IS22 COBOL 54
11 March 2003

CURRENCY SIGN

• The compiler’s definition of the character which is the currency-


symbol in PIC clauses can be set by the programmer
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
CURRENCY SIGN IS "£".
• You must do this before using a symbol other than the
compiler’s default (probably dollar)
• There are rules about the permissible characters
– obviously, £ and $ are both allowed (can be “L” in 85)

11 March 2003 IT52/IS22 COBOL 109

More on comma

• More on comma: if floating or suppression would leave a


floating or suppression character to the left of a comma, then the
comma is replaced by the floating or suppression character
05 Demo PIC Z,ZZZ,ZZ9.
If (say) 1 is moved to this, then we get ________1 and not
_,___,__1

11 March 2003 IT52/IS22 COBOL 110

IT52/IS22 COBOL 55
11 March 2003

More on full-stop

• More on full-stop: full-stop terminates floating or suppression


05 Demo PIC ZZZ.ZZ .
If (say) 0.01 is moved to this, then we get ___.01 and not
___._1 or _____1

but if item would otherwise be all blank then that’s what we


get: if zero is moved to Demo, then we get ______ and not
___.__

11 March 2003 IT52/IS22 COBOL 111

Example of file input & editing


• Suppose an input file, calls.dat, contains details of individual
phone calls, by extension and cost (as £ to two decimal places)
7424 00005
7421 02795
7433 00096
• We wish to print this file, formatting the cost field
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
CURRENCY SIGN IS "£".
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT File-in ASSIGN TO "Calls.dat"
ORGANIZATION IS LINE SEQUENTIAL.

11 March 2003 IT52/IS22 COBOL 112

IT52/IS22 COBOL 56
11 March 2003

Example of file input & editing (continued)


DATA DIVISION.
FILE SECTION.
FD File-in.
01 Call-record.
05 Extension PIC 9999.
05 PIC X.
* Charge in £
05 Call-charge PIC 999V99.
WORKING-STORAGE SECTION.
01 Header.
05 PIC AAAA VALUE "Extn".
05 PIC XXXX VALUE SPACES.
05 PIC AAAA VALUE "Cost".
01 Print-record.
05 Extension PIC 9999.
05 PIC X.
05 Call-charge PIC £££9.99 .
01 Flags.
05 File-in-eof-flag PIC A VALUE "N".
88 File-in-ended VALUE "Y".

11 March 2003 IT52/IS22 COBOL 113

Example of file input & editing (concluded)


PROCEDURE DIVISION.
OPEN INPUT File-in
PERFORM Read-record
DISPLAY Header
PERFORM UNTIL File-in-ended
MOVE CORRESPONDING Call-record
TO Print-Record
DISPLAY Print-Record
PERFORM Read-record
END-PERFORM
STOP RUN.
* Read-record just as before
Read-record.
READ File-in
AT END
MOVE "Y" TO File-in-eof-flag
CLOSE File-in
END-READ.

11 March 2003 IT52/IS22 COBOL 114

IT52/IS22 COBOL 57
11 March 2003

Back to the Data Division - REDEFINES

• Any data item can be redefined. (This is equivalent to Pascal's


variant records or C's unions)
01 Client-record.
05 Client-name PIC X(20).
05 Client-currency PIC A(3).
05 Client-balance-stg PIC **,***.** .
05 Client-balance-yen
REDEFINES Client-balance-stg
PIC *,***,*** .
• This redefines the same area and so must be the same length
PROCEDURE DIVISION.
MOVE "Smith" TO Client-name
MOVE "GBP" TO Client-currency
MOVE 27.23 TO Client-balance-stg
DISPLAY Client-Record

11 March 2003 IT52/IS22 COBOL 115

REDEFINES (continued)
This gives the output
Smith GBP****27.23
• However, if we use the other identifier:
MOVE "Kawasaki" TO Client-name
MOVE "JYE" TO Client-currency
* 183 Yen to the £, and 27.23 * 183 = 4983
MOVE 4983 TO Client-balance-yen
DISPLAY Client-Record
Then we obtain
Kawasaki JYE****4,983
• Formal syntax is
level new-id REDEFINES old-id [pic-clause]

11 March 2003 IT52/IS22 COBOL 116

IT52/IS22 COBOL 58
11 March 2003

REDEFINES (continued)

• Some rules:
– level numbers must be the same and with no lower number
intervening:
05 this
04 is
05 wrong REDEFINES this
– if in FILE SECTION, not 01 (same effect achieved with other
means, as we have seen)
– either/both item(s) can be elementary (as in the currency
example) or group
05 Weight-metric PIC 9V999.
05 Weight-imperial REDEFINES Weight-metric.
10 Weight-lbs PIC 99.
10 Weight-oz PIC 99.

11 March 2003 IT52/IS22 COBOL 117

REDEFINES (continued)
– same original item can be redefined more than once
05 This PIC 99.
05 That REDEFINES This PIC AA.
05 Other REDEFINES This PIC XX.
– cannot redefine the redefinitions
05 This PIC 99.
05 That REDEFINES This PIC AA.
05 Wrong REDEFINES That PIC XX.
– redefinitions cannot have VALUE (why?)

11 March 2003 IT52/IS22 COBOL 118

IT52/IS22 COBOL 59
11 March 2003

Using REDEFINES with condition-name

• A neat technique for inspecting several variables (e.g. error


flags) is to redefine them against a condition-name:
01 Status-area.
03 Check-flags.
05 Check-fuel PIC A VALUE "N".
05 Check-icing PIC A VALUE "N".
05 Check-runway PIC A VALUE "N".
03 All-flags REDEFINES Check-flags PIC AAA.
88 All-OK VALUE "YYY".
• Now we can replace
IF Check-fuel = "Y" AND Check-icing = "Y" AND
Check-runway = "Y" THEN
– by
IF All-OK THEN

11 March 2003 IT52/IS22 COBOL 119

Still in the Data Division: OCCURS

• COBOL has a simple but powerful way of declaring arrays:


these are “tables”.
05 Monthly-takings OCCURS 12 TIMES PIC 999v99.
• The number-of-times must be a constant, of course (why?)
• This gives us a simple array of values. Subscripts start at 1.
Subscripting is easy (but round brackets)
* January’s total is in Gross
MOVE Gross TO Monthly-takings(1)
• The permissible subscript forms are:
integer-constant
integer-variable
integer-variable { + | - } integer constant

11 March 2003 IT52/IS22 COBOL 120

IT52/IS22 COBOL 60
11 March 2003

Simple one-dimensional table: example

* ENVIRONMENT DIVISION sets up £ as currency


DATA DIVISION.
WORKING-STORAGE SECTION.
01 Sales .
05 Month-takings PIC 999 OCCURS 12 TIMES.
77 Loop-var PIC 99.
77 Annual-total PIC 99999 VALUE ZERO .
77 Annual-total-out PIC £££££9 .
PROCEDURE DIVISION.
DISPLAY "Enter 12 sales figures”
* Read and store, form total on the fly
PERFORM VARYING Loop-var FROM 1 BY 1
UNTIL Loop-var > 12
ACCEPT Month-takings(Loop-var)
ADD Month-takings(Loop-var) TO Annual-total
END-PERFORM
MOVE Annual-total TO Annual-total-out
DISPLAY "Total is ", Annual-total-out

11 March 2003 IT52/IS22 COBOL 121

One-dimensional array of group item


• Any item (including a group item) can be declared with OCCURS
05 Airport-line OCCURS 4 TIMES.
10 Airport-code PIC A(3).
10 PIC X.
10 Airport-name PIC A(20).
• This is an array of records in Pascal, or an array of structs in C
• How would we initialise this? If it was a large or volatile table,
from a file. If small or static, we could use constants and
REDEFINES

11 March 2003 IT52/IS22 COBOL 122

IT52/IS22 COBOL 61
11 March 2003

Initialisation using REDEFINES

• We declare the same area twice, once with coarser structure and
constants, then again in full detail
DATA DIVISION.
WORKING-STORAGE SECTION.
01 Airports.
03 Airport-strings.
05 PIC A(24) VALUE "LHR*London Heathrow" .
05 PIC A(24) VALUE "LCY*London City" .
05 PIC A(24) VALUE "GLA*Glasgow" .
05 PIC A(24) VALUE "EDI*Edinburgh" .
03 Airport-table REDEFINES Airport-strings.
05 Airport-line OCCURS 4 TIMES.
10 Airport-code PIC A(3).
10 PIC X.
10 Airport-name PIC A(20).

11 March 2003 IT52/IS22 COBOL 123

A simple table look-up

• Now let us try table look-up


77 A-code PIC A(3) .
77 Loop-var PIC 99.
PROCEDURE DIVISION.
DISPLAY "Enter an airport code"
ACCEPT A-code
PERFORM VARYING Loop-var FROM 1 BY 1
UNTIL Loop-var > 4
OR A-code = Airport-code(Loop-var)
* Might need CONTINUE here for loop body
END-PERFORM
IF Loop-var > 4
DISPLAY A-code, " not found"
ELSE
DISPLAY Airport-name(Loop-var)
END-IF

11 March 2003 IT52/IS22 COBOL 124

IT52/IS22 COBOL 62
11 March 2003

What are we subscripting?

• Notice in the previous example that we had a subscript in a


natural-seeming place, but surprising to a grammarian
Airport-name(Loop-var)
• This is surprising because Airport-name is the name of an
item that does not have OCCURS. It is shorthand for
Airport-name OF Airport-line(Loop-var)

11 March 2003 IT52/IS22 COBOL 125

Multi-dimensional tables

• We can declare multi-dimensional tables using our existing


tools:
01 Sales-Table.
05 Month-takings OCCURS 12 TIMES.
10 Branch-takings PIC 999
OCCURS 5 TIMES
VALUE ZERO.
• The order of the subscripts follows the order of declaration, e.g.
we refer to Branch-takings(Month,Branch)
• Of course, when we loop across the table we can choose which
subscript varies faster/fastest (next slide)

11 March 2003 IT52/IS22 COBOL 126

IT52/IS22 COBOL 63
11 March 2003

Looping across multi-dimensional tables

• This outputs month-within-branch: months as columns, branches


as rows
Show-table.
* Transpose sales table to save paper:
* display 5 rows each with 12 columns
PERFORM VARYING Bloop FROM 1 BY 1
UNTIL Bloop > 5
PERFORM VARYING Mloop FROM 1 BY 1
UNTIL Mloop > 12
DISPLAY " ", Branch-takings(Mloop,Bloop)
NO ADVANCING
END-PERFORM
DISPLAY " "
END-PERFORM.

11 March 2003 IT52/IS22 COBOL 127

Tables: indexing versus subscripting

• Refer back to Slide 122: we can add an extra phrase:


05 Airport-line OCCURS 4 TIMES
INDEXED BY Airport-idx.
10 Airport-code PIC A(3).
10 PIC X.
10 Airport-name PIC A(20).
– In that previous example, we now delete the (redundant)
declaration of the variable Loop-var and replace every
reference to it by Airport-idx
• Although superficially nothing has changed
– the format of indexing is just the same as subscripting (Slide
120)
– we drive the index using PERFORM VARYING just as
before

11 March 2003 IT52/IS22 COBOL 128

IT52/IS22 COBOL 64
11 March 2003

Tables: indexing versus subscripting (continued)

• But we are “indexing” and not “subscripting”. Indexing is safer


– the index cannot be declared too small
– the index cannot be driven out of range
– the compiler will not allow arithmetic to be done on the
index (indeed, how the index works is hidden: it may not be
an integer starting at 1)
– we can only use PERFORM VARYING and SET to change the
index ourselves
SET index-name ...
TO {index-name | ident | integer}

SET index-name ... { UP | DOWN }


BY {ident | integer}

11 March 2003 IT52/IS22 COBOL 129

Searching an indexed table

• Also, there is a built-in lookup that we can use on indexed tables


DISPLAY "Enter an airport code"
ACCEPT A-code
SET Airport-idx TO 1
SEARCH Airport-line VARYING Airport-idx
AT END
DISPLAY A-code, " not found"
WHEN A-code = Airport-code(Airport-idx)
DISPLAY Airport-name(Airport-idx)
END-SEARCH
– You must initialise the index (so you can start anywhere in
the table)
– The condition can be any conditional expression
– There are two branches: each can contain several statements
– At the end of each branch, control passes out of the search
(so only the first matching occurrence is found)
11 March 2003 IT52/IS22 COBOL 130

IT52/IS22 COBOL 65
11 March 2003

Searching a sorted table

• The coding above is only a little easier than hand-coding (but is


safer). But a binary chop is much easier using the built-in
search. Remember binary chop?
– Order log(n) rather than Order n
– so (e.g.) 10 comparisons not 500 when searching 1000
• First we must specify the column on which the table is (to be)
sorted (the example in Parkin & Yorke, page 196, shows this
wrongly)
05 Airport-line OCCURS 10000 TIMES
ASCENDING KEY Airport-code
INDEXED BY Airport-idx.

11 March 2003 IT52/IS22 COBOL 131

Searching a sorted table (continued)


– Then we must ensure that the data actually are sorted on the
key column (e.g. by rearranging the lines of literals)
– now we can use the binary version:
SEARCH ALL Airport-line
AT END
DISPLAY A-code, " not found"
WHEN Airport-code(Airport-idx)= A-code
DISPLAY Airport-name(Airport-idx)
END-SEARCH
– Here we neither set nor vary the index-variable
– the condition must have the form
WHEN key-col(index-var) = expression
– (or else be a condition-name, with a single value, on the key-
column)

11 March 2003 IT52/IS22 COBOL 132

IT52/IS22 COBOL 66
11 March 2003

Tables that aren’t full

• So far we have assumed that the table is completely occupied by


useful data
– this may not always be the case
• We may not know the exact number of entries at the time the
program is written (perhaps we are reading in the table from a
file)
– but in classic COBOL we cannot acquire space dynamically
• So we must take a guess at the maximum number of entries and
declare the table at that maximum size (OCCURS 10000 TIMES,
say)
• As we read the table from the file, we must count the rows as the
table is loaded

11 March 2003 IT52/IS22 COBOL 133

Reading a table from a file: declarations


ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT Air-File ASSIGN TO "airtable.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD Air-File.
01 File-record.
10 Code-field PIC X(4).
10 PIC X.
10 Name-field PIC X(16).
WORKING-STORAGE SECTION.
01 Airports.
05 Airport-line OCCURS 10000 TIMES.
10 Airport-code PIC X(4) .
10 PIC X.
10 Airport-name PIC X(16).
05 Table-size PIC 99999.

11 March 2003 IT52/IS22 COBOL 134

IT52/IS22 COBOL 67
11 March 2003

Reading a table from a file: counting the rows as we read


PROCEDURE DIVISION.
* Initialise table
OPEN INPUT Air-file
MOVE ZERO TO Table-size.
* Now use standard read loop with read para
PERFORM Read-airport
PERFORM UNTIL Air-file-ended
ADD 1 TO Table-size
IF Table-size > 10000
DISPLAY "Too many airports in file”
STOP RUN
END-IF
MOVE File-record
TO Airport-line(Table-size)
PERFORM Read-airport
END-PERFORM
DISPLAY "Table of ", Table-size,
" lines built ..."

11 March 2003 IT52/IS22 COBOL 135

Tables that aren’t full, continued

• Now that we have built the table, we could write our own code
to search the table from 1 ... Table-size
• But how could we use the clever built-in SEARCHes?
• As it stands, they would search the whole of the declared space
of the table (all 10,000 rows) and not just the useful data
• The answer to this problem is DEPENDING ON
• So the full declaration of the table now is
05 Airport-line OCCURS 10000 TIMES
DEPENDING ON Table-size
ASCENDING KEY Airport-code
INDEXED BY Airport-idx.
10 Airport-code PIC X(4) .
10 PIC X.
10 Airport-name PIC X(16).

• Now the built-in searches will work correctly


11 March 2003 IT52/IS22 COBOL 136

IT52/IS22 COBOL 68
11 March 2003

Sorting

• We have already seen that COBOL has a built-in table-lookup.


It also has a built-in (external) sort. This can save a huge
amount of programming: the programming of external sorts is
non-trivial (very)
• Overview of the simplest sort of sort:
– we have an input file, and will generate an output file. We
declare these as before (but we need give only elementary
descriptions of the records)
– we must declare a working file, using SD (Sort-Merge file
description). The records of this file must be declared so
that the sort field(s) can be referenced
– We don’t need any i/o statements other than the sort verb
itself (or even anything else in the Procedure Division)

11 March 2003 IT52/IS22 COBOL 137

Basic sort: example

• We shall sort some live data: all 20,639 grades obtained in units
in Autumn 2002. This file is 314 Kbytes in size
• A few records:
1023197 NM77 2C
1023180 NM77 2B
1023176 NM77 2D
1023195 NM77 1B
• The file is in no particular order. Let's sort it on registration-
number within unit

11 March 2003 IT52/IS22 COBOL 138

IT52/IS22 COBOL 69
11 March 2003

Basic sort: example (continued)

• Remember, we need three files:


ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT File-in ASSIGN TO "Regist.dat”
ORGANIZATION IS LINE SEQUENTIAL.
SELECT File-out ASSIGN TO "Sorted.dat”
ORGANIZATION IS LINE SEQUENTIAL.
SELECT Work-file ASSIGN TO "Work.tmp".
• We don’t know (or need to know) how the work file is
organised; also, in some systems the external name of the work
file may be conventional

11 March 2003 IT52/IS22 COBOL 139

Basic sort: example (continued)


:
DATA DIVISION.
FILE SECTION.
FD File-in.
01 Registration-in PIC X(15).
FD File-out.
01 Registration-out PIC X(15).
SD Work-file.
01 Registration.
05 Stu-num PIC 9(7).
05 PIC A.
05 Unit-code PIC X(4).
05 PIC A.
05 Grade PIC X(2).
PROCEDURE DIVISION.
SORT Work-file
ASCENDING KEY Unit-code
ASCENDING KEY Stu-num
USING File-in
GIVING File-out
STOP RUN.

11 March 2003 IT52/IS22 COBOL 140

IT52/IS22 COBOL 70
11 March 2003

Basic sort: example (continued)

• Here’s (some of) the output file


0020575 0192 W
0011631 0192 2F
...
1123580 IT21 2B
1018350 IT31 1B
...
9954199 XXP7 H
• Sorting is of crucial importance for commercial DP
– classic sequential master-file/transaction-file merge (later)
– rapid access to data via indexes

11 March 2003 IT52/IS22 COBOL 141

Sorting plus user programming

• So far, the COBOL sort gives us little more than we could have
obtained from the system’s built-in sort (in MS-DOS, Unix ..)
• But we can add our own programming ..
• We can manipulate (even create) the records that are input to the
sort
• The USING filename part of the verb is replaced by
INPUT PROCEDURE IS proc1 [THRU proc2]
• The procs are the names of paragraphs (or sections) in the
Procedure Division. (Sections, as in Check-input SECTION. ,
are a way of giving the following paragraphs a collective name)
• This is sometimes called “own-coding” the input to the sort

11 March 2003 IT52/IS22 COBOL 142

IT52/IS22 COBOL 71
11 March 2003

Own-coding the input to a sort

• The basic idea is that our code repeatedly places values in the
fields of the work-file record and “releases” each new record to
be included in the sort. The form is
SORT workfile
ASCENDING KEY field
INPUT PROCEDURE IS para
GIVING outfile.
...
para.
<loop>
<form workfile record>
RELEASE <workfile record>
<end-loop> .
• It is as if the own-coding “writes” a sequence of records into the
input of the sort. Often it reads (another) file to get the data
11 March 2003 IT52/IS22 COBOL 143

Telephone bills

• Let us suppose that the University telephone exchange generates


a record for every outgoing call. These are of the form
– calling extension ; duration (minutes) ; cost-band of call (e.g.
local, national, international) ; [timestamp, etc]
7424 189 1 (189 minutes of local call(!))
7448 027 3 (27 minutes of international call)
7421 045 2
7424 026 1
7448 013 1
7421 156 2
7424 012 3
• We want to work out each extension’s bill (e.g. 7424 owes £2.87)
• As a first step in processing, we decide to
– compute the cost of each call
– sort by extension (this groups the data conveniently)
11 March 2003 IT52/IS22 COBOL 144

IT52/IS22 COBOL 72
11 March 2003

Telephone bills, continued

• Suppose the tariffs are


– local calls are 1.0p per minute; national calls 2.5p;
international 6.0p
• First, we want to work out the cost per call
7424 189 1 => 189 @ 1.0p => 7424 189.0p
7448 027 3 => 27 @ 6.0p => 7446 162.0p
7421 045 2 => 45 @ 2.5p => 7421 112.5p
...
– then we want to sort the records by extension
7421 112.5
7421 ...
...
7424 189.0
7424 ...
...
7446 162.0
7446 ...
...

11 March 2003 IT52/IS22 COBOL 145

Telephone bills: Own-coding the input

• We need three files, as before


INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT File-in ASSIGN TO "Calls.dat”
ORGANIZATION IS LINE SEQUENTIAL.
SELECT File-out ASSIGN TO "Sorted.dat”
ORGANIZATION IS LINE SEQUENTIAL.
SELECT Work-file ASSIGN TO "Work.tmp".
DATA DIVISION.
FILE SECTION.
FD File-in.
01 Call-record.
05 Extension PIC 9999.
05 PIC X.
05 Duration PIC 999.
05 PIC X.
05 Band PIC 9.

11 March 2003 IT52/IS22 COBOL 146

IT52/IS22 COBOL 73
11 March 2003

Telephone bills: Own-coding the input (continued)

FD File-out.
01 Call-out PIC X(9)
SD Work-file.
01 Call-charge-record.
05 Extension PIC 9999.
05 Call-charge PIC 9999V9.
• We need a a table to give the cost for each band. In a real
application we would read this from a file
WORKING-STORAGE SECTION.
01 Tariff-bands.
05 Three-costs PIC X(12)
VALUE "010*025*060*".
05 REDEFINES Three-costs.
10 OCCURS 3 TIMES.
15 Tariff PIC 99V9.
15 PIC X.

11 March 2003 IT52/IS22 COBOL 147

Telephone bills: Own-coding the input (continued)

• We need an item to keep track of the input file’s status (identical


to Slide 91)
01 Flags.
05 File-in-eof-flag PIC A VALUE "N".
88 File-in-ended VALUE "Y".
• Now we’re ready to go (cf Slide 140)
PROCEDURE DIVISION.
Main-para.
SORT Work-file
ASCENDING KEY Extension
OF Call-charge-record
INPUT PROCEDURE IS Compute-cost
GIVING File-out
STOP RUN.

11 March 2003 IT52/IS22 COBOL 148

IT52/IS22 COBOL 74
11 March 2003

Telephone bills: Own-coding the input (continued)


• Remember, the task of Compute-cost is to create records to be
sorted and “release” them to the sort
Compute-cost.
OPEN INPUT File-in
PERFORM Read-record
PERFORM UNTIL File-in-ended
MOVE Extension OF Call-record
TO Extension OF Call-charge-record
MULTIPLY Duration BY Tariff(Band)
GIVING Call-charge
RELEASE Call-charge-record
PERFORM Read-record
END-PERFORM.
• We see that the paragraph uses a conventional read-loop, just as
on Slide 95 (Read-record is identical, and not shown here)

11 March 2003 IT52/IS22 COBOL 149

Telephone bills: Own-coding the input (continued)

• Comparing the input and output files, we see

7424 189 1 742101125 (45 @ 2.5)


7448 027 3 742103900
7421 045 2 742401890 (189 @ 1.0)
7424 026 1 742400260
7448 013 1 742400720
7421 156 2 744801620 (27 @ 6.0)
7424 012 3 744800130

• The results appear to be correct (if not very readable)


• But actually they are just an intermediate stage: we now wish to
aggregate the records to work out each extension’s bill.
• This involves own-coding of the output
11 March 2003 IT52/IS22 COBOL 150

IT52/IS22 COBOL 75
11 March 2003

Telephone bills: Own-coding the output

• As you might expect, there is quite a lot of symmetry with the


input side
– just as we replaced USING with INPUT PROCEDURE, we
replace GIVING with OUTPUT PROCEDURE (cf Slide 148)
PROCEDURE DIVISION.
Main-para.
SORT Work-file
ASCENDING KEY Extension
OF Call-charge-record
INPUT PROCEDURE IS Compute-cost
OUTPUT PROCEDURE IS Sum-bill
STOP RUN.
• So the paragraph Sum-bill will add-up the various calls made
by an extension

11 March 2003 IT52/IS22 COBOL 151

Telephone bills: Own-coding the output, continued


742101125 7421 £5.03
742103900
742401890 7424 £2.87
742400260
742400720
744801620 7448 £1.75
744800130

• We'll skip the details of the coding: but the main point is
– Sum-bill will “read” the sort’s output as if it were a file
– it has a read-loop, and detects end-of-file, in the same way
– except it uses the verb RETURN instead of READ
– just as input coding is like “writing into the sort”, so output
coding is like “reading from the sort”: RELEASE is like
WRITE , RETURN is like READ

11 March 2003 IT52/IS22 COBOL 152

IT52/IS22 COBOL 76
11 March 2003

Classic master/transaction processing

• The classic style of DP is based on batch processing. We


maintain master files: changes to these files (transactions) are
applied in batches. A batch of transactions are placed in an
update file
• The master is always sorted on unique key field(s)
• The update file(s) are sorted into order on the same key field(s):
may have several transactions for the same master record
• Then we read record-at-time, in order, keeping the files in step.
This means
– small memory requirement as very few records in memory
simultaneously
– efficient i/o because access to next record has low (average)
cost (probably already in memory)
11 March 2003 IT52/IS22 COBOL 153

On-line Transaction Processing

• We can contrast this with On-Line Transaction Processing


(OLTP) in which each transaction is applied to master record(s)
as soon as it is originated
• This means that all records in the master file(s) must be
accessible within a (very) short time: in practice we achieve this
by holding a much higher proportion of the file in memory
• Batch is computationally much cheaper (and in the early stages
of commercial DP was the only feasible approach)
• Batch is still a sound approach for applications where
– continuously updated masters are not needed (cost of phone
call so far this month)
– data is inherently cyclic (payroll, exam records)

11 March 2003 IT52/IS22 COBOL 154

IT52/IS22 COBOL 77
11 March 2003

Designing a batch application

• The application must be very robust: must survive all possible


abnormal data conditions and run to completion
• Must ensure that all data problems can be dealt with later
– by editing transaction records and re-running
– by appropriate administrative action (e.g. writing to the
customer)
• An error-log should be produced: also, it is useful to place the
aberrant transaction records in suspense files
• We can distinguish between errors in transaction records
– that can be detected in the absence of the master record:
record has wrong structure, contains invalid codes
– that can only be detected by reference to master record(s): no
such customer, customer exceeded credit limit

11 March 2003 IT52/IS22 COBOL 155

Designing a batch application (continued)

• The first kind can be dealt with in a first pass, using a stand-
alone program, generating its own error log and suspense file(s)
• Then we execute the main pass, merging transaction and master
files

Old master Pass 2 New master

Suspense file
Transaction file Pass 1
Log file

Suspense file

Log file
11 March 2003 IT52/IS22 COBOL 156

IT52/IS22 COBOL 78
11 March 2003

Classic merge of transaction and master

• Remember, both the transaction and master files are sorted (by
e.g. client-number)
• The transaction records will be of three types:
– update (so there should be a matching master record)
– insertion (there should not be a matching master record)
– deletion (there should be a matching master record)
• A neat solution must deal cleanly with the ends of the files: it
greatly simplifies the algorithm if we use sentinels: dummy extra
records with keys higher than any valid key
– so the Master, Transaction and Suspense files are all
maintained with sentinel records at the end
• It's neat if the suspense file is the error log as well
– containing the dud transactions plus error messages
11 March 2003 IT52/IS22 COBOL 157

A sample problem

• Assume Departments are charged for the cost of phone calls.


We have master records with four fields:
– Telephone extension
– Chargeable department
– “Owner” of the extension
– Current balance (pence: negative if Dept owes)
7332M&O Dept Office -01538
7370M&O Dr R Thomas -01033
7421CS&M Dept Office -00503
• Three kinds of transaction records:
– Deletions: 7370D (Delete extension 7370)
– Insertions: 7427ICS&M Dr RG Clark +00000
(Insert extension 7427)
– Updates: 7332U-00057 (Charge 7332 57 pence)
11 March 2003 IT52/IS22 COBOL 158

IT52/IS22 COBOL 79
11 March 2003

Sample run of batch update


Old master
Transaction
New master
7332M&O Dept Office -01538
7370M&O Dr R Thomas -01033 Suspense file
7421CS&M Dept Office -00503
7424CS&M R Bland -00287 7332U-00057
7448CS&M Dr SP Marsh -00175 7332U+00100
9999 7333U+00100
7335D+00100
7421ICS&M Dr Wibble +00000
7332M&O Dept Office -01495 7427ICS&M Dr RG Clark +00000
7370M&O Dr R Thomas -01033 7427U-00050
7421CS&M Dept Office -00503 7448D
7424CS&M R Bland -00287 7999X+00100
7427CS&M Dr RG Clark -00050 9999
9999
7333U+00100 No master, or files unsorted
7335D+00100 No master, or files unsorted
7421ICS&M Dr Wibble +00000 Duplicate extension
7999X+00100 Transact code not recognised
9999

11 March 2003 IT52/IS22 COBOL 159

Batch update, algorithm

• The algorithm for batch update is fairly easy if we only have


updates or deletions
read master and transaction files
while (m-id < sentinel or t-id < sentinel)
if (m-id > transaction)
write transaction to suspense
read transaction
else if (m-id = t-id)
if (update)
do update
read transaction
else // deletion
read master
read transaction
else
write master to new-master
read master
write sentinels to new-master & suspense
11 March 2003 IT52/IS22 COBOL 160

IT52/IS22 COBOL 80
11 March 2003

Files and OLTP

• So far, we have looked at files that are read serially, starting at


the beginning, as if they were on reel-to-reel tape
• Such files cannot support OLTP. For that we need direct access
• Of course, disc is inherently direct access: we have the h/w
• So we just need language features to support it
• COBOL, like e.g. C, supports access-by-position-in-file - in
COBOL’s case,
– this is called RELATIVE organisation
– access is by record position (1, 2, 3, ...) in the file
• If the record position is inherently meaningful (e.g. data on
Room1, Room 2 ...) then this is all we need
• But in most cases our key fields do not run 1, 2, 3, ...

11 March 2003 IT52/IS22 COBOL 161

Indexes

• The programmer must know how to map between features of


interest in the data (key values such as student number) and
position in file. This is an index
Index Main file
9900018 003 001 Smith ...
9905924 001 002 Jones ...
9907013 005 003 Robinson ...
... 004 Farquharson
005 Wu ...
...

• (Most of) the index is held in memory: (most of) the main file is
not.
11 March 2003 IT52/IS22 COBOL 162

IT52/IS22 COBOL 81
11 March 2003

Managing indexes

• Under such an arrangement, the programmer is responsible for


building and maintaining the index and for providing fast look-
up (e.g. binary search)
• This is non-trivial, especially if we allow inserts and deletions
• COBOL will do all this work for us. If we use INDEXED
organisation then the index becomes part of the file structure and
all operations on it are handled for us.
• The facilities are very easy to use
• Of course, we do not know how any particular COBOL system
implements them: but, in general, files of this kind can be
unbalanced by “lumpy” inserts so that the retrieval of some
records becomes slow

11 March 2003 IT52/IS22 COBOL 163

Loading an indexed file

• To avoid this, we load as high a proportion of records as possible


in one pass, in sorted order
• The easiest way of doing this is to adapt the basic sort of Slides
139-142. Not many changes are needed.
• Suppose that we want a file with one record per student, indexed
by registration number. Suppose that the (unsorted) input
records are up to 60 columns long, with the registration number
at the start, like this:
9755864 Ms ABCSmith ..
9943814 Mr DE Jones ..
9612537 MissAN Other ..

11 March 2003 IT52/IS22 COBOL 164

IT52/IS22 COBOL 82
11 March 2003

Loading an indexed file (continued)


* Create an indexed file
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT File-in ASSIGN TO "idxin.dat"
ORGANIZATION IS LINE SEQUENTIAL.
SELECT File-out ASSIGN TO "idxout.dat"
ORGANIZATION IS INDEXED
ACCESS MODE IS SEQUENTIAL
RECORD KEY IS Stu-num.
SELECT Work-file ASSIGN TO "Work.tmp".
DATA DIVISION.
FILE SECTION.
FD File-in.
01 Student-in PIC X(60).
FD File-out.
01 Student-out.
05 Stu-num PIC 9(7).
05 Text-field PIC X(53).
SD Work-file.
01 Student-work.
05 Work-num PIC 9(7).
05 Text-field PIC X(53).

11 March 2003 IT52/IS22 COBOL 165

Loading an indexed file (continued)

• Notes on the previous slide:


– Obviously, the key field must occur in an FD associated with
the file (PC MF requires it to be unique).
– This means that the record description of the output file has
to be expanded to show the key field.
• The Procedure Division still contains only the SORT verb
PROCEDURE DIVISION.
SORT Work-file
ASCENDING KEY Work-num
USING File-in
GIVING File-out
STOP RUN.
• The file thus created cannot (on most systems) be manipulated
by (e.g.) editors. But with ACCESS IS SEQUENTIAL we can
read (and, say, list) it using our existing COBOL techniques
11 March 2003 IT52/IS22 COBOL 166

IT52/IS22 COBOL 83
11 March 2003

Direct access to an indexed file

• To obtain direct access, we make a number of changes to the


methods we used with sequential files
– Change the SELECT to use ACCESS IS RANDOM
– In the Procedure Division, change the OPEN to use
OPEN I-O internal-name
• Now, to read a record from anywhere, we move the required key
value to the key field
MOVE 9712345 TO Stu-num
and then read. If successful, this will bring in the rest of
9712345’s data into the record.
READ internal-name
[INVALID KEY imperative-statement]
[NOT INVALID KEY imperative-statement]
[END-READ]

11 March 2003 IT52/IS22 COBOL 167

Direct access to an indexed file (continued)

• As usual, these are two possible branches each of which can


contain several statements
• It would be very bad practice not to code the “invalid” branch
(no-such-record)
• To write to the file: assemble data in the fields of the record and
either write (if the key value ought not to be in the file already)
or rewrite (if it should be)
[RE]WRITE record-name
[INVALID KEY imperative-statement]
[NOT INVALID KEY imperative-statement]
[END-WRITE]
• Once again it would be bad practice not to code the “invalid”
branch (wrong assumption about existence of key)

11 March 2003 IT52/IS22 COBOL 168

IT52/IS22 COBOL 84
11 March 2003

Direct access to an indexed file (continued)

• We can delete: once again we move the required key-value to


the key-field before using:
DELETE internal-name
[INVALID KEY imperative-statement]
[NOT INVALID KEY imperative-statement]
[END-DELETE]
• There are also facilities to START reading sequentially from any
point in the file
• All of the above can save a huge amount of programming
• Notice that it may be advisable to occasionally rewrite an
indexed file in one sequential pass. The new index will not have
any unbalanced parts that may have been present in the old one

11 March 2003 IT52/IS22 COBOL 169

Some useful verbs: EVALUATE


• At its simplest, EVALUATE is like the C/Java switch:
DISPLAY "Please enter a character"
ACCEPT c
EVALUATE c
WHEN "Y" DISPLAY "yes"
WHEN "N" DISPLAY "no"
WHEN OTHER DISPLAY "neither Y nor N"
END-EVALUATE
• As usual, there can be multiple statements in each branch
• But this just begins to scratch the surface of the verb
• The case values can be ranges
EVALUATE age
WHEN 0 THRU 16 DISPLAY "School"
WHEN 17 THRU 65 DISPLAY "Work"
WHEN OTHER DISPLAY "Retired"
END-EVALUATE
11 March 2003 IT52/IS22 COBOL 170

IT52/IS22 COBOL 85
11 March 2003

EVALUATE (continued)

• The cases can test different conditions


EVALUATE TRUE
WHEN NOT (sex="F" OR sex="M")
DISPLAY "Sex incorrect"
WHEN sex="F" DISPLAY "Woman"
WHEN age<35 DISPLAY "Young man"
WHEN OTHER DISPLAY "Old man"
END-EVALUATE
• In fact, EVALUATE is designed to encode Decision Tables
Inputs Action
Age Sex
0-16 Any “School”
17-60 Any “Work”
61-65 Male “Work”
Other “Retired”

11 March 2003 IT52/IS22 COBOL 171

EVALUATE (continued)

• Here's that table in COBOL


* Assume sex already checked as M or F
EVALUATE age ALSO sex
WHEN 0 THRU 16 ALSO ANY
DISPLAY "School"
WHEN 17 THRU 60 ALSO ANY
DISPLAY "Work"
WHEN 61 THRU 65 ALSO "M"
DISPLAY "Work"
WHEN OTHER DISPLAY "Retired"
END-EVALUATE
• The verb tries to match each row to the column-headings: it
executes the action of the first row that matches completely
• The decision table can have as many input columns as we like
• The action part can be a sequence of statements, terminated by
the next WHEN or by END-EVALUATE

11 March 2003 IT52/IS22 COBOL 172

IT52/IS22 COBOL 86
11 March 2003

String handling

• We’ll look at four string-handling topics: Reference


modification, INSPECT, STRING and UNSTRING
• The full syntax of the verbs is too complex to be given here, so
look them up if you want to see their full power
• Reference-modification: we can refer to part of a data item
– we add (start:length) to the original reference
05 News PIC X(20)
VALUE " Here is the news ".
DISPLAY News
DISPLAY News(2:4)
– produces
Here is the news
Here
– the start and length can be variables
11 March 2003 IT52/IS22 COBOL 173

String handling: INSPECT

• The INSPECT verb deals with characters within strings.


– INSPECT ... TALLYING counts occurrences of a character
or string
– INSPECT ... REPLACING changes occurrences of a
character or string to another character or string
– INSPECT ... CONVERTING maps one set of characters into
another
(these can be BEFORE or AFTER a specified substring)
INSPECT News TALLYING N-Chars FOR ALL SPACES
MOVE ZERO TO N-Chars
INSPECT News TALLYING N-Chars FOR CHARACTERS
BEFORE "news"
INSPECT News REPLACING ALL SPACES BY "_"
INSPECT News CONVERTING "_eristhnw" TO
"*ERISTHNW"

11 March 2003 IT52/IS22 COBOL 174

IT52/IS22 COBOL 87
11 March 2003

String handling: UNSTRING


• The UNSTRING verb splits up a long string into shorter strings
01 Strings.
05 News PIC X(20)
VALUE " Here is the news ".
05 W OCCURS 5 TIMES
PIC X(5).
UNSTRING News DELIMITED BY ALL SPACE INTO
W(1), W(2), W(3), W(4), W(5)
ON OVERFLOW
DISPLAY "Too many words"
STOP RUN
END-UNSTRING
– the delimiter can be any string
– the ALL option means that consecutive delimiters count as
one delimiter
– so W(1) contains spaces, W(2) contains "Here ", etc
11 March 2003 IT52/IS22 COBOL 175

String handling: STRING

• The STRING verb concatenates shorter strings into one long


string
MOVE SPACES TO News
STRING W(2), W(3), W(4), W(5)
DELIMITED BY SPACE INTO News
ON OVERFLOW
DISPLAY "Destination string too short"
STOP RUN
END-STRING
– this gives "Hereisthenews "
• The delimiter can be any string (or SIZE)
• We can have different delimiters for different strings
STRING W(2), W(3) DELIMITED BY SPACE
W(4), W(5) DELIMITED BY SIZE
INTO News
– this gives "Hereisthe news "
11 March 2003 IT52/IS22 COBOL 176

IT52/IS22 COBOL 88

You might also like