Chapter 7: Conditional Logic -- Key Takeaways
Chapter Summary
Conditional logic is the foundation of any meaningful COBOL program. This chapter explored the three primary mechanisms COBOL provides for making decisions at runtime: the IF statement, the EVALUATE statement, and 88-level condition names. Together, these constructs allow programs to branch execution based on data values, user input, file status codes, and virtually any other testable condition that arises during processing.
The IF statement is the most fundamental conditional construct in COBOL, supporting simple tests, compound conditions using AND and OR, nested IF blocks, and the explicit scope terminator END-IF. While COBOL's IF statement resembles conditional constructs in other languages, its verbose English-like syntax and the legacy behavior of the period as a scope terminator introduce subtleties that demand careful attention. We examined how nested IF statements can quickly become difficult to read and how END-IF eliminates the ambiguity that plagued earlier COBOL programs relying on periods alone.
The EVALUATE statement, often compared to the switch or case statement in other languages, provides a cleaner alternative when a program must choose among multiple discrete values or ranges. Unlike a simple switch, EVALUATE supports testing multiple subjects simultaneously, matching ranges with THRU, and combining conditions in ways that make complex decision tables readable. Finally, 88-level condition names were introduced as a powerful COBOL-specific feature that attaches meaningful Boolean names to specific data values, dramatically improving code readability and maintainability throughout a program.
Key Concepts
- The IF statement tests a condition and executes one or more statements when the condition is true; the optional ELSE clause handles the false case.
- END-IF is the explicit scope terminator for IF statements and should always be used in modern COBOL instead of relying on periods to terminate scope.
- Nested IF statements place one IF inside another's THEN or ELSE branch; deep nesting beyond three levels should be avoided for readability.
- Compound conditions combine multiple tests using AND and OR; AND has higher precedence than OR, and parentheses should be used to make intent explicit.
- The NOT operator negates a condition and can be applied to simple comparisons, compound conditions, or class tests.
- Relational operators in COBOL include IS EQUAL TO (=), IS GREATER THAN (>), IS LESS THAN (<), IS NOT EQUAL TO, IS GREATER THAN OR EQUAL TO (>=), and IS LESS THAN OR EQUAL TO (<=).
- Class conditions test the nature of data: IS NUMERIC, IS ALPHABETIC, IS ALPHABETIC-LOWER, IS ALPHABETIC-UPPER, and IS DBCS.
- Sign conditions test whether a numeric item IS POSITIVE, IS NEGATIVE, or IS ZERO.
- EVALUATE acts as COBOL's multi-way branch, evaluating one or more subjects against a series of WHEN clauses, executing the first matching branch.
- EVALUATE TRUE is the most common form, allowing each WHEN clause to specify an independent condition, functioning as a cleaner alternative to nested IF.
- WHEN OTHER in an EVALUATE block serves as the default case, executing when no other WHEN clause matches.
- The 88-level condition name is defined under a data item and associates a meaningful name with one or more specific values of that item.
- An 88-level item can specify a single value, multiple values separated by spaces, or a range of values using THRU.
- SET statement can set an 88-level condition name to TRUE, which assigns the corresponding value to the parent data item.
- CONTINUE is a no-operation statement used as a placeholder in IF or EVALUATE branches where no action is required.
Common Pitfalls
- Dangling ELSE ambiguity: In legacy code without END-IF, a period terminates all open IF scopes, which can cause an ELSE to bind to the wrong IF. Always use END-IF to avoid this.
- Operator precedence errors: Writing
IF A = 1 OR 2does not test whether A equals 1 or A equals 2. It tests whether A equals 1, or whether 2 is true (nonzero). The correct form isIF A = 1 OR A = 2. - Forgetting WHEN OTHER: Omitting the default case in an EVALUATE means that if no WHEN clause matches, execution simply falls through with no action, which may silently produce incorrect results.
- Deeply nested IF blocks: Nesting IF statements more than three or four levels deep makes code nearly impossible to read and debug. Refactor using EVALUATE or PERFORM to separate paragraphs.
- Comparing incompatible data types: Comparing a numeric field to an alphanumeric field can produce unexpected results or abends. Ensure both sides of a comparison are compatible types.
- Misusing NOT with compound conditions:
NOT (A = 1 AND B = 2)is not the same asNOT A = 1 AND NOT B = 2. Apply De Morgan's laws carefully or use parentheses to be explicit. - Omitting the subject in EVALUATE: Writing
EVALUATEwithout a subject or without TRUE/FALSE leads to compilation errors. The subject expression is required. - Treating 88-levels as variables: An 88-level condition name is not a data item that holds a value. It is a Boolean alias for specific values of its parent item. You cannot MOVE a value to an 88-level.
Quick Reference
* Simple IF/ELSE/END-IF
IF WS-BALANCE IS NEGATIVE
DISPLAY "Account overdrawn"
ELSE
DISPLAY "Account in good standing"
END-IF
* Compound condition with parentheses
IF (WS-AGE >= 18 AND WS-AGE <= 65)
OR WS-EXEMPT-FLAG = "Y"
DISPLAY "Eligible"
END-IF
* EVALUATE with multiple WHEN clauses
EVALUATE WS-GRADE
WHEN "A"
MOVE "Excellent" TO WS-REMARK
WHEN "B"
MOVE "Good" TO WS-REMARK
WHEN "C" THRU "D"
MOVE "Needs Improvement" TO WS-REMARK
WHEN OTHER
MOVE "Invalid Grade" TO WS-REMARK
END-EVALUATE
* EVALUATE TRUE for independent conditions
EVALUATE TRUE
WHEN WS-TEMPERATURE > 100
DISPLAY "Overheating"
WHEN WS-TEMPERATURE < 32
DISPLAY "Freezing"
WHEN OTHER
DISPLAY "Normal range"
END-EVALUATE
* 88-level condition names
01 WS-ACCOUNT-STATUS PIC X(01).
88 ACCT-ACTIVE VALUE "A".
88 ACCT-CLOSED VALUE "C".
88 ACCT-SUSPENDED VALUE "S".
88 ACCT-VALID VALUE "A" "C" "S".
* Using SET with 88-level
SET ACCT-ACTIVE TO TRUE
* This assigns "A" to WS-ACCOUNT-STATUS
* Using 88-level in IF
IF ACCT-ACTIVE
PERFORM PROCESS-ACTIVE-ACCOUNT
END-IF
What's Next
Chapter 8 explores iteration through the PERFORM statement in all its forms. You will learn how to execute paragraphs and sections repeatedly using PERFORM TIMES, PERFORM UNTIL, and PERFORM VARYING, as well as inline PERFORM blocks. The chapter builds directly on the conditional logic covered here, since loop control conditions use the same relational and compound condition syntax introduced in this chapter. Mastering PERFORM is essential for processing files record by record, iterating through tables, and structuring COBOL programs into modular, maintainable units.