Many of the commands described in this section have already been used in earlier sections but here their description will be shown alongside related commands, clauses and verbs. It should be noted that a command probably is a verb, while a clause is a collection of COBOL words without a verb.
=======================
# ACCEPT and DISPLAY
=======================
To enter data via the console during a program run, use the ACCEPT verb, e.g:
ACCEPT W-DATA-IN
To display data on the console during a run use the DISPLAY verb, i.e:
DISPLAY W-DATA-OUT
To place text with the outputed data you would code:
DISPLAY 'Inputed data is ' W-DATA-OUT
=========
# Move
=========
The format is:
MOVE [literal-1 or identifier-1] TO [identifier-2] ...
The MOVE statement has already been extensively used in the examples in the Defining Data section. A couple of features have not been described yet: CORRESPONDING (abreviation CORR) and the qualification OF or IN. The elipsis (...) means more of the same, i.e. above [identifier-2] [identifier-3] [identifier-4]...and so on.
To move a group of items from one field description to another:
03 DATE-IN.
05 W-DAY PIC 99.
05 W-MONTH PIC 99.
05 W-YEAR PIC 99.
03 DATE-OUT.
05 W-DAY PIC 99.
05 PIC X VALUE '/'.
05 W-MONTH PIC 99.
05 PIC X VALUE '/'.
05 W-YEAR PIC 99.
If you were to code: MOVE DATE-IN TO DATE-OUT you would end up with the 6 characters of DATE-IN appearing in the first 6 positions of DATE-OUT, including over-written fillers. To get the contents of W-DAY of DATE-IN into W-DAY of DATE-OUT (and the same for the other two items) you could either move them individually, or you could simply code: MOVE CORRESPONDING DATE-IN TO DATE-OUT. To do this the items must have the same name spelling and must be of the same level (here they are both level 03). They don't have to be in the same level 01 group.
Of course, this does present the programmer with a potential problem, this being that if elsewhere in the program you were to code, say, ADD 12 to W-MONTH, the compiler would report a syntax error since it W-MONTH appears twice in the data division and doesn't know which one you mean. To remedy this, you have to qualify the item, i.e. state which group W-MONTH you mean, i.e. :
MOVE 12 TO W-MONTH IN DATE-OUT.
You could use the word OF instead of IN here to the same effect.
Reference modification
-----------------------------------
To access specific characters within a string you can use a reference modifier.
STRING-ITEM (startPosition:Length)
The start position is the nth character of the STRING-ITEM. For MicroFocus compilers at least, the length can be omitted if you want all characters to the end of the string.
e.g.
WORKING-STORAGE SECTION.
01 STRING-1 PIC X(10) VALUE 'ABCDEFGHIJ'.
01 STRING-2 PIC X(10) VALUE SPACES.
01 STRING-3 PIC X(10) VALUE SPACES.
01 STRING-4 PIC X(10) VALUE SPACES.
01 STRING-5 PIC X(10) VALUE SPACES.
01 STRING-6 PIC X(10) VALUE SPACES.
: : in procedure division:
MOVE STRING-1(2:6) TO STRING-2
MOVE STRING-1(1:9) TO STRING-3
MOVE STRING-1(6) TO STRING-4
MOVE STRING-1(5:1) TO STRING-5
MOVE STRING-1(3:3) TO STRING-6
Then:
STRING-2 will contain characters 2 to 6, i.e. : "BCDEFG "
STRING-3 will contain characters 1 to 9, i.e. : "ABCDEFGHI "
STRING-4 will contain characters 6 to the end of STRING-1, i.e. : "FGHIJ "
STRING-5 will contain character 5 only, i.e. : "E "
STRING-6 will contain characters 3 to 5, i.e. : "CDE "
===============
# Perform
===============
The PERFORM verb is one of the most important in COBOL (alongside MOVE).
PERFORM has already been encountered in the Four Divisions section, where it was used to call paragraphs from within a control paragraph. Of course, it doesn't have to be a control (or main) paragraph.
000290 PROCEDURE DIVISION.
000300 XYZ-PARAGRAPH.
000310 PERFORM FIRST-PROCESS
000320 PERFORM SECOND-PARAGRAPH
000330 STOP RUN.
002000 FIRST-PROCESS.
002010 [statements]
[last statement].
In the above code, the paragraph FIRST-PROCESS is executed. When the full stop at the end of this paragraph is encountered the logic will return to XYZ-PARAGRAPH at the next line, i.e. line 320. This is called an Out-of-Line PERFORM.
The PERFORM verb can form the bases of a repetitive loop (or sub-routine) until a certin condition has been met.
For Example:
000290 PROCEDURE DIVISION.
000300 XYZ-PARAGRAPH.
000310 PERFORM COUNT-PROCESS UNTIL W-COUNTER > 10
000320 STOP RUN.
001000
002000 COUNT-PROCESS.
002010 COMPUTE W-COUNTER = W-COUNTER + 1
002020 DISPLAY 'Number of loops is ' W-COUNTER.
In the above code, COUNT-PROCESS is executed until the value of W-COUNT has reached 11.
The format for an Out-of-Line PERFORM is:
PERFORM [paragraph-name] UNTIL [condition]
An In-Line PERFORM, rather than execute a paragraph (aka procedure), allows for the repeated execution of a series of commands. The format for an In-Line PERFORM is:
PERFORM UNTIL
{action}...
END-PERFORM
Example:
000290 PROCEDURE DIVISION.
000300 XYZ-PARAGRAPH.
000305 MOVE ZERO TO W-COUNTER
000310 PERFORM UNTIL W-COUNTER > 10
000320 COMPUTE W-COUNTER = W-COUNTER + 1
000330 DISPLAY 'This is loop number: ' W-COUNTER
000340 END-PERFORM
000350 DISPLAY 'Counter is now equal to: ' W-COUNTER
000360 STOP RUN.
END-PERFORM defines the scope of the PERFORM loop, and is a Scope terminator. Other such scope terminators exist for other commands that will be described further on. The code above will loop 11 times (showning numbers 1 to 11). This is because when W-COUNTER is equal to 10, the condition (W-COUNTER) is still false. 1 is then added, and W-COUNTER is displayed as 11, and now when W-COUNTER is tested the condition will be true and the logic will then jump to the statement that immediately follows END-PERFORM.
This type of PEFORM tests the condition before the following statements are allowed to proceed. Using WITH TEST can be used to define when the test is done:
000290 PROCEDURE DIVISION.
000300 XYZ-PARAGRAPH.
000305 MOVE ZERO TO W-COUNTER
000310 PERFORM WITH TEST AFTER UNTIL W-COUNTER > 10
000320 COMPUTE W-COUNTER = W-COUNTER + 1
000330 DISPLAY 'This is loop number: ' W-COUNTER
000340 END-PERFORM
000350 DISPLAY 'Counter is now equal to: ' W-COUNTER
000360 STOP RUN.
Now the condition is tested after the commands within the PERFORM..END-PERFORM loop has be executed once. (WITH TEST BEFORE has same effect as initial example).
If you wanted to loop a desired number of times you could use TIMES
PERFORM 5 TIMES
COMPUTE W-NUMBER = XYZ * 3
END-PERFORM
The format is:
PERFORM {identifier or literal} TIMES
{action}...
END-PERFORM
To have a loop using an increment (such as a 'for..do' loop in Pascal or FOR in BASIC), the PERFORM VARYING statement is used.
The Format is:
PERFORM {paragraph-name if out-of-line} VARYING {identifier-1}
FROM {identifier-2 or literal} BY {identifier-3 or literal}
UNTIL {condition}
END-PERFORM
Look at the example given below:
000290 PROCEDURE DIVISION.
000300 XYZ-PARAGRAPH.
000310 PERFORM VARYING W-COUNTER FROM 1 BY 2
000320 UNTIL W-COUNTER > 10
000330 DISPLAY 'This is loop number: ' W-COUNTER
000340 END-PERFORM
000350 DISPLAY 'Counter is now equal to: ' W-COUNTER
000360 STOP RUN.
This code will display:
This is loop number: 1
This is loop number: 3
This is loop number: 5
This is loop number: 7
This is loop number: 9
Counter is now equal to: 11
This because with each loop, W-COUNTER has increased from 1 by increments of 2. When W-COUNT was equal to 11 then the condition W-COUNTER > 10 is now true and so the loop is exited. If you wanted to count downwards you could code:
PERFORM VARYING W-COUNTER FROM 20 BY -1
UNTIL W-COUNTER < ZERO.
The last thing to mention is PERFORM..THRU. If a program had a series of paragraphs, just for the sake of argument, called PROCESS-1, PROCESS-2, PROCESS-3 and PROCESS-4, then if you wished to execute these paragraphs in the order that they are written you could code: PERFORM PROCESS-1 THRU PROCESS-4 with any out-of-line loops and conditions you might want. Seemingly, this is not good programming practise so is generally avoided.
===============
# If..Then..Else
===============
Another fundamental part of programming logic is the ability to offer a choice of what to do that depends on the conditions asked of.
The format is:
IF {identifier-1} {condition} {identifier-2 or literal} ...
THEN {statements}
[ELSE {statements}]
END-IF
example:
IF X = Y THEN
MOVE 1 TO Y-COUNTER
ELSE
MOVE 1 TO X-COUNTER
END-IF
ELSE is used if an alternative statement is to be executed if the first condition is false. If there was only to be action if X = Y then the ELSE would be ommitted.
The END-IF terminates the IF statement. All that lies between IF and END-IF will depend on the conditions being tested.
Multiple conditions can be tested, i.e. IF (X = Y) AND (Y < 100) THEN ..
-----------------------------------------------------------------------------------------
===========
# Conditions
===========
There are four types of conditions that could be tested either in a PERFORM, IF..THEN, or EVALUATE (see next section), these being:
1. Class conditions
2. Relational conditions
3. Sign conditions
4. Condition-name conditions
Class conditions test where an item is NUMERIC, ALPHABETIC, ALPHABETIC-LOWER, or ALPHABETIC-HIGHER (as in lower or upper case).
Relational conditions allow comparisons, i.e: GREATER THAN, LESS THAN, EQUAL TO or their sign equivalent: " > ", " < ", " = ", respectively.
Sign conditions test whether an item IS POSITIVE, IS NEGATIVE, or IS NOT ZERO. (note 'IS' is optional)
Condition-name conditions are as described in the section, where a named condition is defined in the data division using a level 88 description.
Conditions can be combined using AND, OR, AND NOT, OR NOT, and brackets. The most common combinations would probably be GREATER THAN OR EQUAL TO and LESS THAN OR EQUAL TO, which can simply be written >= and <= respectively. Also, NOT EQUAL TO would be <> although I find the Fujitsu compiler rejects '<>' so I just use 'NOT = ' instead.
More complex combination's can be achieved with the use of brackets. eg.
IF ( X > Y ) AND ( ( Y + 10 < Z ) OR ( X - 10 > Z ) ) THEN ...
Remember:
[true] AND [false] = FALSE
[true] AND [true] = TRUE
[true] OR [false] = TRUE
[true] OR [true] = TRUE
NOT [true] = FALSE
NOT [false] = TRUE
Alpha-numeric comparisons can also be made that relate to their ASCII character value, so 'A' < 'Z' etc...
------------------------------------------------------------------------------------------------------------------------------
=========
# Evaluate
=========
If there are a large number of conditional alternatives, then using a large number of nested IF statements can be messy:
IF A = 1 THEN PERFORM PARA-1
ELSE
IF A = 2 THEN PERFORM PARA-2
ELSE
IF A = 3 THEN PERFORM PARA-3
ELSE
IF A = 4 THEN PERFORM PARA-4
END-IF
END-IF
END-IF
END-IF
The above example only tested four possible values for 'A'. Suppose there were ten or twenty? This is where the EVALUATE statement is of great use. The format is: