Michael Coughlan

Home > Other > Michael Coughlan > Page 13


  79

  Chapter 5 ■ Control StruCtureS: SeleCtion

  To apply bracketing, you note that NOT takes precedence, so you write (NOT Num1 < 25). AND is next according to the precedence rules, so you bracket the ANDed conditions to give (Num2 = 80 AND Num3 > 264). Finally, the OR

  is evaluated to give the full condition as

  IF (NOT Num1 < 25) OR (Num2 = 80 AND Num3 > 264)THEN

  DISPLAY "Done"

  END-IF

  Of course, you can use bracketing to change the order of evaluation. For instance, you can change the previous condition to

  IF NOT (Num1 < 25 OR Num2 = 80) AND Num3 > 264 THEN

  DISPLAY "Done"

  END-IF

  In the original condition, the order of evaluation was NOT..AND..OR, but the new bracketing changes that order to OR..NOT..AND. This change has a practical effect on the result of the condition.

  Suppose all the simple conditions in the original expression are true. The truth table for that expression yields Table 5-4.

  Table 5-4. IF Statement Evaluation When All the Simple Conditions Are True

  Condition

  IF(NOT Num1 < 25)

  OR

  (Num2 = 80

  AND

  Num3 > 264)

  Expressed as

  (NOT T)

  OR

  ( T

  AND

  T )

  Evaluates to

  (F)

  OR

  ( T

  AND

  T )

  Evaluates to

  (F)

  OR

  (T)

  Evaluates to

  True

  The re-bracketed expression yields Table 5-5.

  Table 5-5. The Rebracketed Truth Table

  Condition

  IF NOT

  (Num1 < 25

  OR

  Num2 = 80)

  AND

  Num3 > 264

  Expressed as

  NOT

  ( T

  OR

  T )

  AND

  T

  Evaluates to

  NOT

  (T)

  AND

  T

  Evaluates to

  (F)

  AND

  T

  False

  Implied Subjects

  Although COBOL is often verbose, it does occasionally provide constructs that enable quite succinct statements to be written. The implied subject is one of those constructs.

  80

  Chapter 5 ■ Control StruCtureS: SeleCtion

  When, in a complex condition, a number of comparisons have to be made against a single data item, it can be tedious to have to repeat the data item for each comparison. For instance, the example code fragment you saw earlier could be rewritten using implied subjects as

  IF (ScrRow > 0 AND < 25) AND (ScrCol > 0 AND < 81) THEN

  DISPLAY "On Screen"

  END-IF

  In this case, the implied subjects are ScrRow and ScrCol.

  Similarly, using Grade = as the implied subject, you can rewrite

  IF Grade = "A" OR Grade = "B" OR Grade = "C" THEN DISPLAY "Passed"

  as

  IF Grade = "A" OR "B" OR "C" THEN DISPLAY "Passed"

  Finally, you can use the implied subject Num1 > to rewrite the expression

  IF Num1 > Num2 AND Num1 > Num3 AND Num1 > Num4 THEN

  DISPLAY "Num1 is the largest"

  END-IF

  as

  IF Num1 > Num2 AND Num3 AND Num4

  DISPLAY "Num1 is the largest"

  END-IF

  Nested IFs

  COBOL allows nested IF statements (see Example 5-5). But be aware that although nested IF statements may be easy to write, they are somewhat difficult to understand when you return to them after an interval of time. Complex, and nested IF, statements are often used as a substitute for clear thinking. When you first attempt to solve a problem, you often don’t have a full understanding of it. As a result, your solution may be convoluted and unwieldy. It is often only after you have attempted to solve the problem that you gain sufficient insight to allow you to generate a simpler solution. When you have a better understanding of the problem, you may find that a mere reorganization of your code will greatly reduce both the number and complexity of the IF statements required. Simplicity is difficult to achieve but is a highly desirable objective. It is a principle of good program design that your solution should be only as complex as the problem demands.

  Example 5-5. Nested IF..ELSE Statements

  *> This example uses nested IF statements including IF..THEN..ELSE statements

  *> This is quite a straight forward example of nested IFs but nested If & IF.. ELSE statements

  *> can get a lot more convoluted and difficult to understand. It is especially difficult if

  *> some nested IF statements do not have ELSE branches and others do. It can take some time

  *> to untangle which ELSE belongs with which IF

  81

  Chapter 5 ■ Control StruCtureS: SeleCtion

  IF InputVal IS NUMERIC

  MOVE InputVal to Num1

  IF Num1 > 5 AND < 25

  IF Num1 < Num2

  MOVE Num2 TO Num1

  ELSE

  MOVE Num1 TO Num2

  END-IF

  DISPLAY "Num1 & Num2 = " Num1 SPACE Num2

  ELSE

  DISPLAY "Num 1 not in range"

  END-IF

  ELSE

  DISPLAY "Input was not numeric"

  END-IF

  Delimiting Scope: END-IF vs. Period

  The scope of an IF statement may be delimited by either an END-IF or a period (full stop). For a variety of reasons, the explicit END-IF delimiter should always be used instead of a period. The period is so problematic that one of the most useful renovations you can perform on legacy COBOL code is to replace the periods with explicit scope delimiters.

  There are two main problems with using a period as a scope delimiter. The first is that periods are hard to see, which makes it more difficult to understand the code. The second problem is that a period delimits all open scopes.

  This is a source of many programming errors.

  The code fragments in Example 5-6 illustrate the readability problem. Both IF statements are supposed to

  perform the same task. But the scope of the IF statement on the left is delimited by an END-IF, whereas the statement on the right is delimited by a period.

  Example 5-6. Comparing END-IF and Period-Delimited IF Statements

  Statement1

  Statement1

  Statement2

  Statement2

  IF Num1 > Num2 THEN

  IF Num1 > Num2 THEN

  Statement3

  Statement3

  Statement4

  Statement4

  END-IF

  Statement5

  Statement5

  Statement6.

  Statement6.

  Unfortunately, on the right, the programmer has forgotten to follow Statement4 with a delimiting period.

  This means Statement5 and Statement6 will be included in the scope of the IF. They will be executed only if the condition is true. When periods are used to delimit the scope of an IF statement, this is an easy mistake to make; and, once made, it is difficult to spot. A period is small and unobtrusive compared to an END-IF.

  The problem caused by unexpectedly delimiting scope is illustrated by the following code fragment:

  IF Num1 < 10

  ADD 10 TO Num1

  MULTIPLY Num1 BY 1000 GIVING NUM2

  ON SIZE ERROR DISPLAY "Error: Num2 too small".

  DISPLAY "When is this shown?".

  82

  Chapter 5 ■ Control StruCtureS: SeleCtion

  In this fragment, it looks as if the DISPLAY on the final line is executed only when Num1 is less than 10. However, a period has been used to delimit the scope of the ON SIZE ERROR (instead of an END-MULTIPLY delimiter)
, and that period also delimits the scope of the IF (all open scopes). This means the DISPLAY lies outside the scope of the IF and so is always executed.

  If you replace the periods with explicit scope delimiters, you can see more clearly what is happening:

  IF Num1 < 10

  ADD 10 TO Num1

  MULTIPLY Num1 BY 1000 GIVING NUM2

  ON SIZE ERROR DISPLAY "Error: Num2 too small"

  END-MULTIPLY

  END-IF

  DISPLAY "When is this shown?".

  Even though the indentation used in this version is just as misleading as the period-based version, you are not misled. The explicit scope delimiters used for the IF and the MULTIPLY make the scope of these statements clear.

  The use of delimiting periods in the PROCEDURE DIVISION is such a source of programming errors that a

  minimum period style of programming has been advocated by Howard Tompkins1 and Robert Baldwin2. In the

  examples in this book, I use a variation of the style suggested by Tompkins. Tompkins was writing before the 1985

  standard was produced and so was not able to incorporate END delimiters into his scheme. Nowadays, you can adopt a style that uses only a single period per paragraph. Although Tompkins has persuasive arguments for placing that period alone on the line in column 12, for aesthetic reasons I use it to terminate the last statement in the paragraph.

  Whether you prefer the Tompkins lonely period style or my variation, I strongly suggest that you adopt the minimum period style. That way you will save yourself a world of hurt.

  Condition Names

  Wherever a condition tests a variable for equality to a value, a set of values, or a range of values, that condition can be replaced by a kind of abstract condition called a condition name. Wherever it is legal to have a condition, it is legal have a condition name. Just like a condition, a condition name is either true or false.

  Condition names allow you to give a meaningful name to a condition while hiding the implementation details of how the condition is detected. For instance,

  IF CountryCode = 3 OR 7 OR 10 OR 15 THEN

  MOVE 14 TO CurrencyCode

  END-IF

  may be replaced with

  IF BritishCountry THEN

  SET CurrencyIsPound TO TRUE

  END-IF

  This example illustrates the readability benefits of using condition names. When you encounter code such as IF CountryCode = 3 OR 7 OR 10 OR 15

  the meaning of what the IF statement is testing is not obvious. You can see that CountryCode is being tested for particular values, but why? What is the significance of the values 3,7,10, and 15? What is the significance of moving 14

  to the CurrencyCode? To discover this information, a maintenance programmer has to read external documentation or in-code comments. Now consider the condition name version of the IF statement. It is obvious what you are testing 83

  Chapter 5 ■ Control StruCtureS: SeleCtion

  because the test has been given a meaningful name. Similarly, the action taken when BritishCountry is true is also obvious. No documentation and no comments are required.

  Ease of maintenance is also improved. If the coding system changed and the countries of the British Isles were now represented by the codes 4, 12, 18, and 25, only the definition of the condition name would have to be changed.

  In the version that did not use the condition name, you would have to change the code values in all the places in the program where the condition was tested.

  Defining Condition Names

  Condition names are sometimes called level 88s because they are created in the DATA DIVISION using the special level number 88. The metalanguage for defining condition names is given in Figure 5-6.

  Figure 5-6. Metalanguage for defining condition names

  Rules

  Condition names are always associated with a particular data item and are defined immediately after the definition of that data item. A condition name may be associated with a group data item and elementary data, or even the element of a table. The condition name is automatically set to true or false the moment the value of its associated data item changes.

  When the VALUE clause is used with condition names, it does not assign a value. Instead, it identifies the value(s) which, if found in the associated data item, make the condition name true.

  When identifying the condition values, a single value, a list of values, a range of values, or any combination of these may be specified. To specify a list of values, the entries are listed after the keyword VALUE. The list entries may be separated by commas or spaces but must terminate with a period.

  Single Condition Name, Single Value

  In Example 5-7, the condition name CityIsLimerick has been associated with CityCode so that if CityCode contains the value 2 (listed in the CityIsLimerick VALUE clause), the condition name will be automatically set to true.

  Example 5-7. Defining and Using a Condition Name

  DATA DIVISION.

  WORKING-STORAGE SECTION.

  01 CityCode PIC 9 VALUE ZERO.

  88 CityIsLimerick VALUE 2.

  PROCEDURE DIVISION.

  Begin.

  : : : : : : : :

  DISPLAY "Enter a city code (1-6) - " WITH NO ADVANCING

  ACCEPT CityCode

  84

  Chapter 5 ■ Control StruCtureS: SeleCtion

  IF CityIsLimerick

  DISPLAY "Hey, we're home."

  END-IF

  : : : : : : : :

  In the program fragment, DISPLAY and ACCEPT get a city code from the user. The instant the value in CityCode changes, the CityIsLimerick condition name will be set to true or false, depending on the value in CityCode.

  Multiple Condition Names

  Several condition names may be associated with a single data item. In Example 5-8, a number of condition names have been associated with CityCode. Each condition name is set to true when CityCode contains the value listed in the condition name VALUE clause. Condition names, like Booleans, can only take the value true or false. If a condition name is not set to true, it is set to false. Table 5-6 shows the Boolean value of each condition name for each value of CityCode.

  Example 5-8. Associating Many Condition Names with a Data Item

  DATA DIVISION.

  WORKING-STORAGE SECTION.

  01 CityCode PIC 9 VALUE ZERO.

  88 CityIsDublin VALUE 1.

  88 CityIsLimerick VALUE 2.

  88 CityIsCork VALUE 3.

  88 CityIsGalway VALUE 4.

  88 CityIsSligo VALUE 5.

  88 CityIsWaterford VALUE 6.

  PROCEDURE DIVISION.

  Begin.

  : : : : : : : :

  DISPLAY "Enter a city code (1-6) - " WITH NO ADVANCING

  ACCEPT CityCode

  IF CityIsLimerick

  DISPLAY "Hey, we're home."

  END-IF

  IF CityIsDublin

  DISPLAY "Hey, we're in the capital."

  END-IF

  : : : : : : : :

  Table 5-6. Results for Each Value of CityCode

  Data Item / Condition Name

  Data Value / Condition Name Result

  CityCode

  0

  1

  2

  3

  4

  5

  6

  7–9

  CityIsDublin

  False

  TRUE

  False

  False

  False

  False

  False

  False

  CityIsLimerick

  False

  False

  TRUE

  False

  False

  False

  False

  False

  CityIsCork

  False

  False

  False

  TRUE

  False

  False

  False

  False

  CityIsGalway
r />   False

  False

  False

  False

  TRUE

  False

  False

  False

  CityIsSligo

  False

  False

  False

  False

  False

  TRUE

  False

  False

  CityIsWaterford

  False

  False

  False

  False

  False

  False

  TRUE

  False

  85

  Chapter 5 ■ Control StruCtureS: SeleCtion

  Overlapping and Multiple-Value Condition Names

  When multiple condition names are associated with a single data item, more than one condition name can be

  true at the same time. In Listing 5-2, UniversityCity is true if CityCode contains any value between 1 and 4.

  These values overlap the values of the first four condition names, so if UniversityCity is true, then one of those four must also be true.

  Listing 5-2. Multiple Condition Names with Overlapping Values

  IDENTIFICATION DIVISION.

  PROGRAM-ID. Listing5-2.

  AUTHOR. Michael Coughlan.

  DATA DIVISION.

  WORKING-STORAGE SECTION.

  01 CityCode PIC 9 VALUE ZERO.

  88 CityIsDublin VALUE 1.

  88 CityIsLimerick VALUE 2.

  88 CityIsCork VALUE 3.

  88 CityIsGalway VALUE 4.

  88 CityIsSligo VALUE 5.

  88 CityIsWaterford VALUE 6.

  88 UniversityCity VALUE 1 THRU 4.

  88 CityCodeNotValid VALUE 0, 7, 8, 9.

  PROCEDURE DIVISION.

  Begin.

  DISPLAY "Enter a city code (1-6) - " WITH NO ADVANCING

  ACCEPT CityCode

  IF CityCodeNotValid

  DISPLAY "Invalid city code entered"

  ELSE

  IF CityIsLimerick

  DISPLAY "Hey, we're home."

  END-IF

  IF CityIsDublin

  DISPLAY "Hey, we're in the capital."

  END-IF

  IF UniversityCity

  DISPLAY "Apply the rent surcharge!"

  END-IF

  END-IF

  STOP RUN.

  The list of values that follows a condition name may be a single value, a number of values, or a range of values, or any mixture of these. When a range is specified, the word THROUGH or THRU is used to separate the minimum and maximum values in the range. In Listing 5-2, UniversityCity is true if CityCode contains any value between 1 and 4, whereas CityCodeNotValid is true if CityCode contains a value of 0 or 7 or 8 or 9. In Listing 5-2 I have chosen to list the individual values for CityCodeNotValid, but the value list could have been written as:

 

‹ Prev