Chapter 8 Exercises: Iteration -- The PERFORM Statement
Tier 1: Recall and Recognition (Exercises 1-8)
These exercises test your understanding of PERFORM syntax and basic concepts.
Exercise 1: Identify the PERFORM Form
For each of the following code fragments, identify which form of PERFORM is being used (Basic, THRU, TIMES, UNTIL with TEST BEFORE, UNTIL with TEST AFTER, VARYING, or Inline):
* Fragment A:
PERFORM CALCULATE-TAX
* Fragment B:
PERFORM 10 TIMES
ADD 1 TO WS-COUNTER
END-PERFORM
* Fragment C:
PERFORM WITH TEST AFTER
UNTIL WS-RESPONSE = 'Q'
PERFORM DISPLAY-MENU
ACCEPT WS-RESPONSE
END-PERFORM
* Fragment D:
PERFORM VALIDATE-START THRU VALIDATE-EXIT
* Fragment E:
PERFORM VARYING WS-I FROM 1 BY 1
UNTIL WS-I > 50
DISPLAY WS-TABLE-ENTRY(WS-I)
END-PERFORM
* Fragment F:
PERFORM UNTIL WS-BALANCE < 0
SUBTRACT WS-PAYMENT FROM WS-BALANCE
END-PERFORM
* Fragment G:
PERFORM PRINT-HEADER 1 TIMES
Exercise 2: Predict the Output
What does the following code display? Trace the execution carefully.
01 WS-X PIC 9(2) VALUE 1.
PROCEDURE DIVISION.
MAIN-PARA.
DISPLAY "Start"
PERFORM PARA-A
DISPLAY "Middle"
PERFORM PARA-B
DISPLAY "End"
STOP RUN.
PARA-A.
DISPLAY "A-begin"
PERFORM PARA-C
DISPLAY "A-end".
PARA-B.
DISPLAY "B-begin"
DISPLAY "B-end".
PARA-C.
DISPLAY "C-begin"
DISPLAY "C-end".
Exercise 3: Sum of First N Numbers
Write a COBOL program that uses PERFORM VARYING to compute the sum of the first 100 natural numbers (1 + 2 + 3 + ... + 100). Display the result. Verify that the answer is 5050 (using the formula n(n+1)/2 = 100101/2 = 5050).
Exercise 4: PERFORM TIMES vs. PERFORM VARYING
Explain the difference between these two loops. Do they produce the same output? Why or why not?
* Loop A:
MOVE 0 TO WS-COUNTER
PERFORM 5 TIMES
ADD 1 TO WS-COUNTER
DISPLAY WS-COUNTER
END-PERFORM
* Loop B:
PERFORM VARYING WS-COUNTER FROM 1 BY 1
UNTIL WS-COUNTER > 5
DISPLAY WS-COUNTER
END-PERFORM
Exercise 5: Multiplication Table
Write a COBOL program that prints a 10x10 multiplication table. Use nested PERFORM VARYING loops (either with AFTER or nested inline). The output should be a neatly formatted grid showing products from 1x1 to 10x10.
Exercise 6: TEST BEFORE vs. TEST AFTER
For each scenario below, state whether you would use WITH TEST BEFORE or WITH TEST AFTER, and explain why:
a) Reading records from a file until end-of-file b) Displaying a menu and processing user choices until they select "Quit" c) Computing Fibonacci numbers until one exceeds 1,000,000 d) Prompting for a password with a maximum of 3 attempts e) Processing all elements of an array
Exercise 7: Condition Names in Loops
Rewrite the following loop to use 88-level condition names instead of the relational condition:
01 WS-STATUS PIC X(1) VALUE SPACES.
MOVE 'N' TO WS-STATUS
PERFORM UNTIL WS-STATUS = 'Y'
PERFORM PROCESS-RECORD
PERFORM CHECK-FOR-COMPLETION
END-PERFORM
Exercise 8: Find the Bugs
Each of the following code fragments contains a bug related to PERFORM. Identify and explain each bug:
* Bug A: Infinite loop
PERFORM UNTIL WS-COUNTER > 10
DISPLAY WS-COUNTER
END-PERFORM
* Bug B: Unexpected behavior
MOVE 5 TO WS-LIMIT
PERFORM WS-LIMIT TIMES
SUBTRACT 1 FROM WS-LIMIT
DISPLAY "Iteration"
END-PERFORM
* Bug C: Missing priming read
SET NOT-END-OF-FILE TO TRUE
PERFORM UNTIL END-OF-FILE
PERFORM PROCESS-RECORD
PERFORM READ-RECORD
END-PERFORM
* Bug D: Off-by-one
PERFORM VARYING WS-I FROM 1 BY 1
UNTIL WS-I = 10
DISPLAY WS-TABLE(WS-I)
END-PERFORM
Tier 2: Understanding and Application (Exercises 9-16)
These exercises require you to write working code and demonstrate understanding of PERFORM patterns.
Exercise 9: Factorial Calculator
Write a COBOL program that calculates and displays the factorials of 1 through 15. Use PERFORM VARYING with an accumulator. Display each factorial on a separate line (e.g., "5! = 120").
Exercise 10: Temperature Conversion Table
Write a COBOL program that produces a Fahrenheit-to-Celsius conversion table for temperatures from -40 to 212 degrees Fahrenheit in steps of 10. Use PERFORM VARYING with a step value of 10. Format the output in two neat columns with headers.
The formula is: C = (F - 32) * 5 / 9
Exercise 11: Array Reversal
Write a COBOL program that:
1. Initializes a 10-element numeric array with the values 10, 20, 30, ..., 100.
2. Displays the array.
3. Reverses the array in-place using a PERFORM UNTIL loop with two converging index variables (left and right).
4. Displays the reversed array.
Exercise 12: Convert PERFORM TIMES to PERFORM VARYING
Rewrite the following code using PERFORM VARYING instead of PERFORM TIMES:
MOVE ZEROS TO WS-SUM
MOVE ZEROS TO WS-COUNTER
PERFORM 20 TIMES
ADD 1 TO WS-COUNTER
COMPUTE WS-SQUARE = WS-COUNTER * WS-COUNTER
ADD WS-SQUARE TO WS-SUM
DISPLAY WS-COUNTER " squared = " WS-SQUARE
END-PERFORM
DISPLAY "Sum of squares: " WS-SUM
Exercise 13: Convert PERFORM VARYING to PERFORM UNTIL
Rewrite the following code using PERFORM UNTIL instead of PERFORM VARYING:
PERFORM VARYING WS-I FROM 100 BY -5
UNTIL WS-I < 0
DISPLAY WS-I
END-PERFORM
Exercise 14: Binary Search
Write a COBOL program that implements a binary search on a sorted array of 20 numbers. The program should:
1. Initialize a sorted array with values 5, 10, 15, 20, ..., 100.
2. Search for a target value (e.g., 65).
3. Use PERFORM UNTIL with a found-flag and converging low/high pointers.
4. Display each guess and whether it was too high, too low, or correct.
5. Display the number of comparisons made.
Exercise 15: Structured Program Skeleton
Design and write the PROCEDURE DIVISION skeleton (paragraph names and PERFORM statements only, no detailed logic) for a COBOL program that processes a customer order file and produces an invoice report. Your skeleton should include:
- Main program paragraph (IPT pattern)
- Initialization (open files, print headers)
- Processing loop with priming read
- Record validation
- Order total calculation
- Invoice line printing
- Summary totals printing
- File closing
Use descriptive paragraph names following the verb-noun naming convention.
Exercise 16: Inline vs. Out-of-Line Decision
For each scenario below, state whether you would use inline PERFORM or out-of-line PERFORM, and explain your reasoning:
a) Summing elements of a small 5-element array b) Validating 15 different fields of an input record c) A loop that reads and processes records until end-of-file d) Initializing 50 working storage variables to their default values e) A nested loop that fills a 100x100 matrix f) A loop body that is called from three different places in the program
Tier 3: Analysis and Problem Solving (Exercises 17-24)
These exercises require analyzing problems and designing complete solutions.
Exercise 17: Simple Control Break
Write a COBOL program that processes the following department expense data (already sorted by department) and produces a report with department subtotals and a grand total:
| Department | Amount |
|---|---|
| ACCT | 1,500.00 |
| ACCT | 2,300.00 |
| ACCT | 1,800.00 |
| ACCT | 2,100.00 |
| MGMT | 4,500.00 |
| MGMT | 5,200.00 |
| MGMT | 4,800.00 |
| SALE | 3,200.00 |
| SALE | 2,800.00 |
| SALE | 3,500.00 |
| SALE | 3,100.00 |
| SALE | 2,900.00 |
Use the standard control break pattern with PERFORM UNTIL and a previous-key variable.
Exercise 18: Nested Loop Pattern -- Pyramid
Write a COBOL program that produces the following output using nested PERFORM VARYING loops:
*
***
*****
*******
*********
The program should work for any height specified in a variable (e.g., WS-HEIGHT = 5). This requires computing the correct number of leading spaces and stars for each row.
Exercise 19: String Processing Loop
Write a COBOL program that accepts a string (up to 50 characters) and uses PERFORM VARYING to:
1. Count the number of vowels, consonants, digits, and other characters.
2. Convert all lowercase letters to uppercase.
3. Display the original string and the converted string.
4. Display the character counts.
Exercise 20: Powers of 2
Write a COBOL program that displays the powers of 2 from 2^0 through 2^20 using a PERFORM VARYING loop. Each line should show the exponent and the result. Verify that 2^10 = 1024 and 2^20 = 1048576.
Exercise 21: Sorting with PERFORM
Implement the selection sort algorithm using nested PERFORM VARYING loops. The program should:
1. Initialize an array with unsorted values: 64, 25, 12, 22, 11, 90, 34, 45.
2. Display the array before sorting.
3. Sort using selection sort (find minimum in remaining portion, swap with current position).
4. Display the array after each pass.
5. Display the final sorted array.
Exercise 22: Euclid's GCD Algorithm
Write a COBOL program that computes the Greatest Common Divisor (GCD) of two numbers using Euclid's algorithm with PERFORM UNTIL. The algorithm is:
1. Given two numbers A and B (A > B).
2. Replace A with B, and B with A mod B.
3. Repeat until B is zero.
4. A is the GCD.
Test with the pairs: (252, 105), (1071, 462), (100, 75).
Exercise 23: PERFORM VARYING with AFTER
Write a COBOL program that uses PERFORM VARYING ... AFTER to fill and display a 3x4 matrix where each element is the sum of its row index and column index (e.g., element [2,3] = 5). Display the matrix in a neat grid format.
Then use another PERFORM VARYING ... AFTER to compute the sum of each row and each column, displaying the results.
Exercise 24: Convert GO TO to PERFORM
Rewrite the following GO TO-based code using structured PERFORM statements (no GO TO):
PROCESS-RECORDS.
READ INPUT-FILE INTO WS-RECORD
AT END GO TO PROCESS-END.
PROCESS-LOOP.
IF WS-RECORD-TYPE = 'H'
GO TO PROCESS-NEXT.
IF WS-AMOUNT < 0
ADD 1 TO WS-ERROR-COUNT
GO TO PROCESS-NEXT.
ADD WS-AMOUNT TO WS-TOTAL
ADD 1 TO WS-RECORD-COUNT
WRITE OUTPUT-RECORD FROM WS-RECORD.
PROCESS-NEXT.
READ INPUT-FILE INTO WS-RECORD
AT END GO TO PROCESS-END.
GO TO PROCESS-LOOP.
PROCESS-END.
DISPLAY "Records: " WS-RECORD-COUNT.
DISPLAY "Errors: " WS-ERROR-COUNT.
Tier 4: Design and Synthesis (Exercises 25-32)
These exercises require designing complete programs with proper structured design.
Exercise 25: Complete Payroll Program
Design and implement a complete payroll program following the IPT pattern. The program should:
- Initialize: Set up employee data in a table (5 employees with name, hours, and hourly rate).
- Process: For each employee, calculate: - Regular pay (up to 40 hours) - Overtime pay (hours over 40 at 1.5x rate) - Gross pay (regular + overtime) - Tax (22% of gross) - Net pay (gross - tax)
- Terminate: Print a summary showing total gross pay and total net pay for all employees.
Use at least three levels of paragraph hierarchy. Include a paragraph for each calculation step.
Exercise 26: Grade Distribution Report
Write a COBOL program that processes an array of 50 student test scores (values between 0 and 100) and produces a grade distribution report:
- A: 90-100
- B: 80-89
- C: 70-79
- D: 60-69
- F: below 60
Use PERFORM VARYING to iterate through scores, EVALUATE for grade assignment, and accumulator variables for each grade category. Display the count and percentage for each grade, plus the class average, highest score, and lowest score.
Exercise 27: Calendar Generator
Write a COBOL program that displays a calendar for a given month and year. The program should: 1. Accept month and year as data items. 2. Calculate the day of the week for the 1st of the month (Zeller's formula or similar). 3. Calculate the number of days in the month (handle leap years). 4. Display the calendar in a standard 7-column grid format with day-of-week headers.
Use PERFORM VARYING for the day loop and PERFORM UNTIL for the week loop.
Exercise 28: Multi-Level Report
Design and implement a sales report program that processes sales data organized by: - Region (3 regions: North, South, West) - Quarter (4 quarters) - Month (3 months per quarter)
Use a three-dimensional array and nested PERFORM VARYING loops to:
1. Calculate quarterly subtotals by region.
2. Calculate annual totals by region.
3. Calculate monthly totals across all regions.
4. Display a formatted report with all subtotals and grand totals.
Exercise 29: Menu-Driven Calculator
Write a COBOL program that implements a simple calculator using a menu-driven PERFORM WITH TEST AFTER loop:
- Display a menu: Add, Subtract, Multiply, Divide, Clear, Quit
- Accept the user's choice (simulate with a predefined sequence of operations).
- For arithmetic operations, accept two operands and display the result.
- For Clear, reset the accumulator.
- For Quit, display session summary (number of operations performed) and exit.
Structure the program using a clear paragraph hierarchy.
Exercise 30: Data Validation Framework
Write a COBOL program that validates customer records using a structured validation framework:
- Define a customer record with: customer ID, name, address, city, state, zip, phone, email indicator.
- Create a validation paragraph for each field.
- Use a master validation paragraph that PERFORMs each field validation.
- Track errors using an error counter and error message table.
- Process 5 sample records (some valid, some with various errors).
- Display a validation report showing which records passed and which failed, with specific error messages.
Exercise 31: Statistical Analysis
Write a COBOL program that performs statistical analysis on a dataset of 20 numbers using various PERFORM patterns:
- Mean: Use PERFORM VARYING to sum and divide.
- Median: Sort the array (using a sorting PERFORM loop), then find the middle value.
- Mode: Use nested PERFORM VARYING to count occurrences of each value.
- Standard deviation: Use PERFORM VARYING to compute the sum of squared differences from the mean.
- Range: Use PERFORM VARYING to find min and max.
Display all results with appropriate labels and formatting.
Exercise 32: Text Report Formatter
Write a COBOL program that takes a paragraph of text (stored as multiple 80-character lines) and reformats it to a specified line width (e.g., 60 characters). The program should:
- Read words from the input text using character-by-character scanning with PERFORM VARYING.
- Accumulate words into output lines, wrapping to the next line when a word would exceed the line width.
- Right-justify each completed line by distributing extra spaces between words.
- Display the formatted output.
This exercise combines string processing with multiple PERFORM patterns.
Tier 5: Critical Thinking and Evaluation (Exercises 33-40)
These exercises require critical analysis, comparison, and evaluation of different approaches.
Exercise 33: PERFORM THRU Analysis
A legacy COBOL program uses the following structure:
PERFORM PROCESS-ORDER THRU PROCESS-ORDER-EXIT.
PROCESS-ORDER.
PERFORM VALIDATE-ORDER
IF ORDER-VALID
PERFORM CALCULATE-TOTAL
PERFORM APPLY-DISCOUNT
END-IF.
GENERATE-INVOICE.
PERFORM PRINT-INVOICE-HEADER
PERFORM PRINT-INVOICE-LINES
PERFORM PRINT-INVOICE-FOOTER.
PROCESS-ORDER-EXIT.
EXIT.
A maintenance programmer needs to add invoice generation for valid orders. They insert a PERFORM GENERATE-INVOICE into the PROCESS-ORDER paragraph. However, they notice that GENERATE-INVOICE is physically located between PROCESS-ORDER and PROCESS-ORDER-EXIT.
a) What happens when this code executes? Is GENERATE-INVOICE executed once or twice for valid orders? b) How would you restructure this code to avoid the THRU problem? c) What coding standards would prevent this issue?
Exercise 34: Performance Comparison
Consider these three implementations of the same logic -- summing all elements in a 10,000-element array:
* Version A: Out-of-line PERFORM VARYING
PERFORM SUM-ONE-ELEMENT
VARYING WS-I FROM 1 BY 1
UNTIL WS-I > 10000.
SUM-ONE-ELEMENT.
ADD WS-ARRAY(WS-I) TO WS-TOTAL.
* Version B: Inline PERFORM VARYING
PERFORM VARYING WS-I FROM 1 BY 1
UNTIL WS-I > 10000
ADD WS-ARRAY(WS-I) TO WS-TOTAL
END-PERFORM
* Version C: PERFORM UNTIL with manual counter
MOVE 1 TO WS-I
PERFORM UNTIL WS-I > 10000
ADD WS-ARRAY(WS-I) TO WS-TOTAL
ADD 1 TO WS-I
END-PERFORM
a) Rank these three versions by likely performance (fastest to slowest) and explain why. b) Which version would you choose for production code and why? c) Under what circumstances (if any) would the performance difference matter?
Exercise 35: Loop Equivalence
Prove that the following two loops are NOT equivalent by finding input values where they produce different results:
* Loop A: TEST BEFORE
MOVE 1 TO WS-X
PERFORM UNTIL WS-X > WS-N
ADD WS-X TO WS-TOTAL
ADD 1 TO WS-X
END-PERFORM
* Loop B: TEST AFTER
MOVE 1 TO WS-X
PERFORM WITH TEST AFTER
UNTIL WS-X > WS-N
ADD WS-X TO WS-TOTAL
ADD 1 TO WS-X
END-PERFORM
For what value(s) of WS-N do these produce different results? What are the different results?
Exercise 36: Structured Programming Debate
A colleague argues that the following GO TO pattern is clearer than the structured alternative for a paragraph with multiple validation checks:
* GO TO version:
VALIDATE-RECORD.
IF WS-CUST-ID = SPACES
MOVE "Missing customer ID" TO WS-ERROR
GO TO VALIDATE-RECORD-EXIT.
IF WS-AMOUNT NOT NUMERIC
MOVE "Non-numeric amount" TO WS-ERROR
GO TO VALIDATE-RECORD-EXIT.
IF WS-DATE-FIELD NOT NUMERIC
MOVE "Invalid date" TO WS-ERROR
GO TO VALIDATE-RECORD-EXIT.
SET RECORD-VALID TO TRUE.
VALIDATE-RECORD-EXIT.
EXIT.
a) Write the purely structured equivalent (no GO TO, no EXIT PARAGRAPH). b) Write the COBOL 2002+ equivalent using EXIT PARAGRAPH. c) Compare all three versions for readability, maintainability, and correctness. d) Which would you recommend for new code? For maintaining legacy code?
Exercise 37: PERFORM Stack Analysis
Trace the PERFORM stack for the following program. At each numbered comment, show the contents of the PERFORM stack (which return addresses are on it):
MAIN. *> (1) Stack: ?
PERFORM PARA-A
STOP RUN. *> (6) Stack: ?
PARA-A. *> (2) Stack: ?
PERFORM PARA-B
DISPLAY "Back in A". *> (5) Stack: ?
PARA-B. *> (3) Stack: ?
PERFORM PARA-C
DISPLAY "Back in B". *> (4) Stack: ?
PARA-C.
DISPLAY "In C".
Exercise 38: Design Critique
Critique the following program structure. Identify at least five problems with the PERFORM organization:
MAIN-PARA.
PERFORM PARA-1
PERFORM PARA-2 THRU PARA-5
PERFORM PARA-6 100 TIMES
PERFORM PARA-2
STOP RUN.
PARA-1.
PERFORM PARA-3.
PARA-2.
MOVE 'A' TO WS-FLAG.
PARA-3.
PERFORM PARA-4.
PARA-4.
DISPLAY "Hello".
PARA-5.
EXIT.
PARA-6.
PERFORM PARA-6.
Exercise 39: Real-World Pattern Design
A bank processes daily transactions against customer accounts. Transactions are sorted by account number and then by transaction date. There are three transaction types:
- D (Deposit): Add to balance
- W (Withdrawal): Subtract from balance (reject if insufficient funds)
- I (Interest): Calculate and add daily interest
Design the PROCEDURE DIVISION structure (paragraph names, PERFORM statements, and brief comments) for this program. Include: - IPT pattern at the top level - Control break on account number - Running balance tracking - Error handling for insufficient funds - Daily interest calculation - Account summary at each control break - Grand summary at end-of-file
Do not write the full implementation -- just the structural skeleton with PERFORM statements.
Exercise 40: Comprehensive Iteration Challenge
Write a COBOL program that demonstrates ALL forms of PERFORM in a single, cohesive application. The program should implement a simple student grade book that:
- Uses PERFORM paragraph to call initialization and cleanup routines.
- Uses PERFORM THRU (with EXIT paragraph) for a multi-step report generation process.
- Uses PERFORM TIMES to print a decorative border.
- Uses PERFORM UNTIL (TEST BEFORE) for the main processing loop.
- Uses PERFORM WITH TEST AFTER for input validation retry.
- Uses PERFORM VARYING to iterate through student records.
- Uses PERFORM VARYING with AFTER to process a 2D grade matrix (students x assignments).
- Uses Inline PERFORM for short calculations.
- Uses Nested out-of-line PERFORM for the report hierarchy.
The program should follow the IPT pattern with at least a three-level paragraph hierarchy. Include clear comments identifying which PERFORM form is being demonstrated in each section.
Solution Notes
Selected solutions are provided in code/exercise-solutions.cob. The solutions demonstrate best practices including:
- Proper fixed-format column alignment
- Meaningful data names following naming conventions
- 88-level condition names for loop control
- The IPT pattern for overall program structure
- Comments explaining the approach
For exercises that ask for analysis or design (rather than code), sample answers are provided in the solution file comments and in-class discussion materials.