Chapter 8 Quiz: Iteration -- The PERFORM Statement
Instructions: Answer each question, then expand the hidden answer to check your work. Each question is worth one point unless otherwise noted.
Question 1
What is the default test behavior for PERFORM UNTIL? That is, when is the UNTIL condition evaluated if you do not specify WITH TEST BEFORE or WITH TEST AFTER?
Show Answer
The default is **WITH TEST BEFORE**. The UNTIL condition is evaluated **before** each iteration. If the condition is true initially, the loop body is never executed. This makes the default PERFORM UNTIL equivalent to a `while` loop in other languages.Question 2
What is the COBOL equivalent of a do-while loop (a loop that always executes at least once)?
Show Answer
`PERFORM WITH TEST AFTER UNTIL condition`. The TEST AFTER option causes the condition to be checked **after** each iteration, guaranteeing that the loop body executes at least once, even if the condition is already true.Question 3
True or False: PERFORM 0 TIMES will execute the loop body once.
Show Answer
**False.** If the TIMES value is zero (or negative), the loop body is **never** executed. The count is tested before the first execution.Question 4
In the statement PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 10, what is the value of WS-I after the loop completes?
Show Answer
**WS-I = 11.** The loop executes for WS-I values 1 through 10. After the iteration where WS-I is 10, the BY value (1) is added, making WS-I = 11. The UNTIL condition (WS-I > 10) is then true, so the loop exits. The VARYING variable always ends up one step past the termination point.Question 5
What is the scope terminator that marks the end of an inline PERFORM?
Show Answer
**`END-PERFORM`**. It was introduced in the COBOL-85 standard. Without END-PERFORM, you cannot use inline PERFORM -- you must name a paragraph for out-of-line PERFORM.Question 6
Name two reasons why PERFORM THRU is considered controversial and is discouraged by many COBOL coding standards.
Show Answer
1. **The insertion problem:** If a new paragraph is added between the THRU range endpoints, it becomes part of the execution range unintentionally, potentially introducing bugs. 2. **The ordering dependency:** PERFORM THRU depends on the physical order of paragraphs in the source code. Rearranging paragraphs can silently break the program. Other valid answers include: it makes programs harder to understand, it creates implicit coupling between paragraph positions, and it complicates maintenance.Question 7
What is the "priming read" pattern, and why is it needed?
Show Answer
The **priming read** is the practice of reading the first record from a file **before** entering the PERFORM UNTIL END-OF-FILE loop. It is needed because PERFORM UNTIL with TEST BEFORE (the default) evaluates the condition before executing the body. Without the priming read, the program would either: - Try to process an uninitialized record area, or - Need to use TEST AFTER with an additional IF check inside the loop. The pattern is:PERFORM READ-RECORD (priming read)
PERFORM UNTIL END-OF-FILE
PERFORM PROCESS-RECORD
PERFORM READ-RECORD (subsequent reads)
END-PERFORM
Question 8
In the PERFORM VARYING ... AFTER construct, which variable changes fastest -- the VARYING variable or the AFTER variable?
Show Answer
The **AFTER** variable changes fastest. The AFTER variable is the inner loop. It cycles through its entire range for each single step of the VARYING (outer) variable. If there are multiple AFTER clauses, the rightmost one changes fastest.Question 9
What does the following code display?
01 WS-X PIC 9(2) VALUE 15.
PERFORM WITH TEST AFTER
UNTIL WS-X > 10
DISPLAY WS-X
ADD 1 TO WS-X
END-PERFORM
Show Answer
It displays: **15** Even though WS-X (15) is already greater than 10, `WITH TEST AFTER` means the body executes once before the condition is checked. After the body executes (displaying 15 and incrementing to 16), the UNTIL condition (WS-X > 10, which is 16 > 10 = true) is evaluated, and the loop exits. So the output is a single line: `15`Question 10
True or False: PERFORM TIMES provides an automatic iteration counter variable.
Show Answer
**False.** Unlike `for` loops in most other languages, `PERFORM TIMES` does **not** provide an automatic counter. If you need to know which iteration you are on, you must declare and manage your own counter variable. This is a common source of confusion for programmers coming from other languages.Question 11
What is the difference between these two statements?
* Statement A:
PERFORM CALCULATE-TAX
* Statement B:
PERFORM
COMPUTE WS-TAX = WS-INCOME * WS-RATE
END-PERFORM
Show Answer
**Statement A** is an **out-of-line PERFORM**. It transfers control to the paragraph named `CALCULATE-TAX`, executes its statements, and returns. The code is in a separate paragraph that can be PERFORMed from multiple places. **Statement B** is an **inline PERFORM**. The code between PERFORM and END-PERFORM is executed in place. No separate paragraph is needed or referenced. This code can only be executed from this one location. Functionally, both execute code once, but Statement A references a reusable paragraph while Statement B contains the code inline.Question 12
What happens if you PERFORM a paragraph that itself PERFORMs the calling paragraph (direct recursion)?
Show Answer
This causes **undefined behavior** in standard COBOL. The PERFORM stack becomes corrupted because the same paragraph has multiple active PERFORM invocations. Most compilers will either enter an infinite loop, produce incorrect results, or terminate with a runtime error. COBOL (through the 2002 standard) does not support recursive PERFORM. Recursive CALL is supported in COBOL 2002+ with the RECURSIVE attribute, but recursive PERFORM is not.Question 13
What is the IPT pattern in COBOL structured programming?
Show Answer
The **IPT (Init-Process-Terminate)** pattern is the fundamental structure of nearly every batch COBOL program:MAIN-PROCESS.
PERFORM INITIALIZATION (Init)
PERFORM PROCESS-RECORDS (Process)
PERFORM WRAP-UP (Terminate)
STOP RUN.
- **Initialization:** Opens files, initializes working storage, prints report headers.
- **Process:** Contains the main processing loop (read, process, write).
- **Terminate:** Prints summary totals, closes files, performs cleanup.
This pattern provides a clear, predictable program structure.
Question 14
Which COBOL 2002+ statement is equivalent to break in C/Java?
Show Answer
**`EXIT PERFORM`**. It immediately terminates the innermost enclosing inline PERFORM loop and transfers control to the statement following END-PERFORM. It can only be used within an inline PERFORM (one that uses END-PERFORM), not with out-of-line PERFORM.Question 15
Which COBOL 2002+ statement is equivalent to continue in C/Java?
Show Answer
**`EXIT PERFORM CYCLE`**. It skips the remaining statements in the current iteration and proceeds to the next iteration of the innermost enclosing inline PERFORM loop. For PERFORM VARYING, the loop variable is incremented before the next iteration begins. Like EXIT PERFORM, it only works within inline PERFORM blocks.Question 16
How many times does the following loop body execute?
PERFORM VARYING WS-I FROM 1 BY 2
UNTIL WS-I > 10
DISPLAY WS-I
END-PERFORM
Show Answer
**5 times.** The values of WS-I are: 1, 3, 5, 7, 9. After WS-I = 9, the BY value (2) is added, making WS-I = 11, which satisfies the UNTIL condition (11 > 10), so the loop exits.Question 17
Explain the term "PERFORM stack" and why it matters for nested PERFORM statements.
Show Answer
The **PERFORM stack** is an internal data structure that COBOL uses to track return addresses for PERFORM statements. When a PERFORM executes: 1. The return address (the address of the statement following the PERFORM) is pushed onto the stack. 2. Control transfers to the target paragraph. 3. When the paragraph completes, the return address is popped from the stack and control resumes there. For nested PERFORMs (a PERFORMed paragraph that itself PERFORMs another paragraph), multiple return addresses are on the stack simultaneously. This is analogous to the function call stack in other languages. Understanding the PERFORM stack is important because: - It explains why paragraphs should only be reached via PERFORM, not by "falling through" from the previous paragraph. - It explains why recursive PERFORM is dangerous (the stack gets corrupted). - It explains the execution flow in complex programs with deeply nested PERFORM calls.Question 18
What is wrong with the following code?
PERFORM VARYING WS-I FROM 1 BY 1
UNTIL WS-I > 10
IF WS-ARRAY(WS-I) = WS-KEY
EXIT PERFORM
END-IF
END-PERFORM
a) Nothing -- this code is correct b) EXIT PERFORM cannot be used with PERFORM VARYING c) EXIT PERFORM requires END-PERFORM, which is present d) WS-I will have an undefined value after EXIT PERFORM
Show Answer
**a) Nothing -- this code is correct.** EXIT PERFORM can be used with any form of inline PERFORM (any PERFORM that has END-PERFORM). When the EXIT PERFORM executes, the loop terminates immediately, and WS-I retains the value it had when the match was found. This is a valid and common pattern for early exit from a search loop.Question 19
In what order are the identifiers set when executing this statement?
PERFORM VARYING WS-A FROM 1 BY 1
UNTIL WS-A > 3
AFTER WS-B FROM 1 BY 1
UNTIL WS-B > 2
DISPLAY WS-A " " WS-B
END-PERFORM
Show Answer
The output is:1 1
1 2
2 1
2 2
3 1
3 2
WS-A is the outer loop (VARYING), and WS-B is the inner loop (AFTER). For each value of WS-A, WS-B cycles through its entire range (1, 2). When WS-B exceeds its limit, WS-A is incremented and WS-B resets to its FROM value. The VARYING variable changes slowest; the AFTER variable changes fastest. This produces 3 x 2 = 6 iterations.
Question 20
True or False: Changing the TIMES variable inside a PERFORM TIMES loop changes the number of iterations.
Show Answer
**False.** The TIMES value is captured (evaluated) once at the beginning of the loop. Modifying the variable that specifies the count during loop execution does **not** change the number of iterations. The loop will still execute the originally specified number of times. This is explicitly stated in the COBOL standard.Question 21
What is the EXIT statement (without PARAGRAPH, SECTION, or PERFORM), and when is it typically used?
Show Answer
The plain `EXIT` statement is a **no-operation** -- it does nothing. It provides a paragraph that contains no executable code. It is typically used as the endpoint paragraph in a `PERFORM THRU` range:PERFORM PROCESS-RECORD THRU PROCESS-RECORD-EXIT.
PROCESS-RECORD.
... (processing logic) ...
PROCESS-RECORD-EXIT.
EXIT.
The EXIT paragraph serves as a clean, unambiguous endpoint for the THRU range. In COBOL-74 and COBOL-85, the EXIT statement was required to be the only statement in its paragraph.
Question 22
A programmer writes:
PERFORM UNTIL END-OF-FILE
PERFORM READ-RECORD
PERFORM PROCESS-RECORD
END-PERFORM
without a priming read. If the input file is empty, what happens with the default TEST BEFORE behavior?
Show Answer
If the `READ-RECORD` paragraph has not been called before the loop, the END-OF-FILE condition has not been set. The initial value of the EOF flag (typically 'N' or FALSE) means the loop **enters** and executes `READ-RECORD`. If the file is empty, `READ-RECORD` sets END-OF-FILE to TRUE, but then `PROCESS-RECORD` still executes for this iteration -- processing an empty or uninitialized record, which is a bug. With a proper priming read:PERFORM READ-RECORD
PERFORM UNTIL END-OF-FILE
PERFORM PROCESS-RECORD
PERFORM READ-RECORD
END-PERFORM
If the file is empty, the priming read sets END-OF-FILE, and the loop body never executes.
Question 23
Which COBOL standard introduced inline PERFORM with END-PERFORM?
a) COBOL-68 b) COBOL-74 c) COBOL-85 d) COBOL 2002
Show Answer
**c) COBOL-85** (also known as ANS85 or the 1985 ANSI standard). COBOL-85 introduced scope terminators including END-PERFORM, END-IF, END-EVALUATE, END-READ, and others. This was one of the most significant enhancements to the COBOL language, enabling inline structured constructs.Question 24
Why are index names (INDEXED BY) generally more efficient than numeric subscripts for table access?
Show Answer
Index names store table element positions as **byte displacement values** (the number of bytes from the start of the table to the desired element). Accessing an element using an index requires only a single addition (base address + displacement). Numeric subscripts store the **occurrence number** (1, 2, 3, ...). Accessing an element using a subscript requires a **multiplication** (subscript value x element size) plus an addition. The multiplication adds overhead, especially on older hardware or in tight loops. Modern optimizing compilers can sometimes eliminate this difference, but index-based access is still generally preferred for performance-critical table operations, particularly on IBM mainframes.Question 25
What is the output of the following code?
01 WS-COUNT PIC 9(2) VALUE 0.
PERFORM ADD-ONE 3 TIMES
DISPLAY WS-COUNT
PERFORM ADD-ONE 2 TIMES
DISPLAY WS-COUNT
STOP RUN.
ADD-ONE.
ADD 1 TO WS-COUNT.
Show Answer
The output is:03
05
The first `PERFORM ADD-ONE 3 TIMES` executes ADD-ONE three times, incrementing WS-COUNT from 0 to 3. The DISPLAY shows `03`.
The second `PERFORM ADD-ONE 2 TIMES` executes ADD-ONE two more times, incrementing WS-COUNT from 3 to 5. The DISPLAY shows `05`.
WS-COUNT retains its value between PERFORM calls because it is a WORKING-STORAGE variable with persistent scope.
Question 26 (2 points)
Write a PERFORM VARYING statement that iterates through a two-dimensional array WS-MATRIX with 5 rows and 8 columns, setting each element to the product of its row and column indices. Use a single PERFORM VARYING with an AFTER clause.
Show Answer
PERFORM VARYING WS-ROW FROM 1 BY 1
UNTIL WS-ROW > 5
AFTER WS-COL FROM 1 BY 1
UNTIL WS-COL > 8
COMPUTE WS-MATRIX(WS-ROW, WS-COL) =
WS-ROW * WS-COL
END-PERFORM
This iterates through all 40 elements (5 rows x 8 columns). WS-ROW is the outer loop (VARYING) and WS-COL is the inner loop (AFTER). For each row, all 8 columns are processed before moving to the next row.
Question 27
What does EXIT PARAGRAPH do, and in what COBOL standard was it introduced?
Show Answer
`EXIT PARAGRAPH` immediately transfers control to the **end of the current paragraph**, as if the paragraph's terminating period had been reached. It is the COBOL equivalent of an early `return` from a function. It was introduced in **COBOL 2002**. It is useful for implementing guard-clause validation patterns, where early exit is taken for error conditions, and the "happy path" logic follows at the end of the paragraph without deep nesting.Question 28
A programmer needs to process elements 5 through 15 of a 20-element table in reverse order (15, 14, 13, ..., 5). Write the PERFORM VARYING statement.
Show Answer
PERFORM VARYING WS-I FROM 15 BY -1
UNTIL WS-I < 5
DISPLAY WS-TABLE(WS-I)
END-PERFORM
This starts at element 15 and counts down by 1 until WS-I goes below 5. The values processed are: 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5 (11 elements).
Question 29
Explain the difference between the UNTIL condition in COBOL's PERFORM UNTIL and the condition in C's while loop. Why is this distinction important?
Show Answer
In C's `while (condition)`, the condition specifies when to **continue** the loop. The loop body executes as long as the condition is true. In COBOL's `PERFORM UNTIL condition`, the condition specifies when to **stop** the loop. The loop body executes as long as the condition is false and stops when it becomes true. These are logical inverses of each other: - C: `while (count <= 10)` continues while count is 10 or less - COBOL: `PERFORM UNTIL count > 10` stops when count exceeds 10 Both produce the same behavior, but the logical sense is reversed. This distinction is important because: 1. Programmers coming from C/Java/Python often write the wrong condition initially. 2. The UNTIL condition is the **termination** condition, which can be counter-intuitive. 3. When converting between languages, the condition must be negated.Question 30
True or False: You can use EXIT PERFORM to exit an out-of-line PERFORM (a PERFORM that names a paragraph rather than using END-PERFORM).
Show Answer
**False.** `EXIT PERFORM` and `EXIT PERFORM CYCLE` can only be used within an **inline** PERFORM -- that is, a PERFORM that has a matching END-PERFORM scope terminator. They cannot be used to exit from an out-of-line PERFORM of a named paragraph. To achieve early exit from an out-of-line PERFORM, you must use either: - `EXIT PARAGRAPH` (COBOL 2002+) - `GO TO` the EXIT paragraph at the end of a PERFORM THRU range - Restructured IF/ELSE logicScoring Guide
| Score | Rating |
|---|---|
| 28-31 | Excellent -- You have a thorough understanding of PERFORM |
| 23-27 | Good -- Strong knowledge with minor gaps |
| 18-22 | Satisfactory -- Review the sections you missed |
| 13-17 | Needs Improvement -- Re-read the chapter carefully |
| 0-12 | Insufficient -- Start from the beginning and work through examples |
Total possible points: 31 (Questions 1-25 and 27-30 are 1 point each; Question 26 is 2 points)