13.1 What are Nested Loops?
A nested loop is a loop whose body contains another loop. The outer loop controls how many times the inner loop runs to completion. Together they let a program iterate over two dimensions — for example the rows and columns of a table.
Key idea: The total number of times the innermost body runs is the product of the iteration counts of all the loops — not the sum. A 3-iteration outer loop wrapped around a 4-iteration inner loop runs the body 3 × 4 = 12 times.
Visualising Nested Loops
FOR I <- 1 TO 2 // outer loop (rows)
FOR J <- 1 TO 3 // inner loop (columns)
OUTPUT I, J
NEXT J
NEXT IReading the output order: the outer counter I stays fixed while the inner counter J cycles through all its values. So the output is:
1, 1
1, 2
1, 3
2, 1
2, 2
2, 3Notice how I changes slowly (only twice) while J changes rapidly (six times). This pattern is the signature of nested-loop execution.
13.2 Nested FOR Loops
The most common form of nesting is two FOR loops, one inside the other. Each FOR must have its own matching NEXT statement, and the inner NEXT must appear before the outer NEXT.
Syntax
FOR <outer> <- <start> TO <end> DO
FOR <inner> <- <start> TO <end> DO
<body — runs (outer × inner) times>
NEXT <inner>
NEXT <outer>Note the "last opened, first closed" rule: the inner FOR opens last, so its NEXT comes first. Getting this order wrong is the #1 nesting bug.
Worked Example: A 3×3 Multiplication Table
DECLARE I : INTEGER
DECLARE J : INTEGER
FOR I <- 1 TO 3
FOR J <- 1 TO 3
OUTPUT I, " x ", J, " = ", I * J
NEXT J
NEXT IThe output runs through all 9 combinations of (I, J): 1×1=1, 1×2=2, 1×3=3, 2×1=2, 2×2=4, 2×3=6, 3×1=3, 3×2=6, 3×3=9. The outer loop fixes the row (the multiplier), the inner loop fixes the column (the multiplicand).
Common bug: Swapping the order of NEXT statements. If you write NEXT I before NEXT J, the inner loop is closed by the wrong NEXT and the structure is invalid. Always close the innermost loop first.
13.3 How Nested Loops Work (Tracing)
To understand nested loops you must learn to trace them — that is, write down the values of all loop counters at every step. The rule is simple: the outer counter changes slowly; the inner counter changes rapidly.
Worked Trace
FOR I <- 1 TO 2
FOR J <- 1 TO 2
OUTPUT I, J
NEXT J
NEXT I| Step | I (outer) | J (inner) | OUTPUT |
|---|---|---|---|
| 1 | 1 | 1 | 1 1 |
| 2 | 1 | 2 | 1 2 |
| 3 | 2 | 1 | 2 1 |
| 4 | 2 | 2 | 2 2 |
Notice how I stays at 1 while J goes 1 → 2. Only when the inner loop has finished does I move to 2, and then J starts over from 1 again.
Exam tip: When you encounter a nested loop in an exam question, draw a small trace table with one column per counter BEFORE you read the rest of the question. Filling it in step by step will almost always reveal the answer.
13.4 Nesting Different Loop Types
You are not restricted to nesting FOR inside FOR. CIE pseudocode allows any loop type (FOR, WHILE, REPEAT...UNTIL) to be nested inside any other. Mixing loop types is useful when the outer and inner loops have different termination requirements.
Example: FOR Inside WHILE
Keep processing batches of 5 items while the user has not typed "QUIT".
DECLARE Done : BOOLEAN
DECLARE I : INTEGER
DECLARE Command : STRING
Done <- FALSE
WHILE NOT Done DO
FOR I <- 1 TO 5
OUTPUT "Processing item ", I
// ... process item I of this batch ...
NEXT I
OUTPUT "Type QUIT to stop, anything else to continue."
INPUT Command
IF Command = "QUIT" THEN
Done <- TRUE
ENDIF
ENDWHILEThe outer WHILE keeps the program running until the user quits; the inner FOR processes exactly 5 items per batch. Without nesting you would need to write the "process 5 items" block many times.
Example: WHILE Inside FOR
For each of 3 students, keep prompting until they enter a valid mark.
DECLARE Student : INTEGER
DECLARE Mark : INTEGER
DECLARE Valid : BOOLEAN
FOR Student <- 1 TO 3
Valid <- FALSE
WHILE NOT Valid DO
OUTPUT "Student ", Student, " — enter mark (0..100): "
INPUT Mark
IF Mark >= 0 AND Mark <= 100 THEN
Valid <- TRUE
ELSE
OUTPUT "Invalid, try again."
ENDIF
ENDWHILE
OUTPUT "Recorded mark ", Mark, " for student ", Student
NEXT StudentThe outer FOR fixes the student (a counted iteration); the inner WHILE retries until valid (an unknown number of iterations). Notice that the Valid flag is reset to FALSE at the start of each student — otherwise the WHILE would skip for students 2 and 3.
Rule of thumb: Use the loop type that matches each dimension’s nature. Known count → FOR. Unknown count, may run zero times → WHILE. Unknown count, must run at least once → REPEAT...UNTIL. Mix and match as the problem requires.
13.5 Practical Examples
Here are three worked examples that show nested loops solving real exam-style problems.
Example 1 — Print a 3×3 Grid of Stars
DECLARE Row : INTEGER
DECLARE Col : INTEGER
FOR Row <- 1 TO 3
FOR Col <- 1 TO 3
OUTPUT "*", " " // print star + space, no newline
NEXT Col
OUTPUT "" // move to next line after each row
NEXT RowThe inner loop prints one row of 3 stars; the OUTPUT "" after the inner loop forces a newline. The outer loop repeats this for 3 rows. Result: a 3×3 grid.
Example 2 — Sum All Cells of a 2D Array
DECLARE Grid : ARRAY[1:3, 1:4] OF INTEGER
DECLARE Row : INTEGER
DECLARE Col : INTEGER
DECLARE Total : INTEGER
Total <- 0
// ... assume Grid is filled with values ...
FOR Row <- 1 TO 3
FOR Col <- 1 TO 4
Total <- Total + Grid[Row, Col]
NEXT Col
NEXT Row
OUTPUT "The total is ", TotalThe outer loop iterates over 3 rows; the inner loop iterates over 4 columns in the current row. Every cell is visited exactly once and added to the running total.
Example 3 — Find the Largest Value in a 2D Array
DECLARE Grid : ARRAY[1:3, 1:4] OF INTEGER
DECLARE Row : INTEGER
DECLARE Col : INTEGER
DECLARE Largest : INTEGER
// ... assume Grid is filled with values ...
Largest <- Grid[1, 1]
FOR Row <- 1 TO 3
FOR Col <- 1 TO 4
IF Grid[Row, Col] > Largest THEN
Largest <- Grid[Row, Col]
ENDIF
NEXT Col
NEXT Row
OUTPUT "Largest value is ", LargestInitialise Largest to the first cell, then visit every cell. Whenever a larger value is found, update Largest. By the end of the nested loops, Largest holds the maximum value in the entire 2D array.
13.6 Key Points Summary
Recap the most important ideas about nested loops before you tackle the Question Bank.
Exam tip: Always draw a trace table with one column per loop counter. The moment you see the inner counter resetting while the outer counter stays the same, you know you are tracing correctly.