Lecture 3: Loops
Prerequisites: Lecture 2 (Conditions —
if/else, relational and logical operators,switch)
1. Overview
- Programmes frequently need to perform the same action many times; this chapter introduces the repetition structure (loops) that eliminates redundant code and enables data-driven iteration.
- After studying this chapter you will be able to choose among
while,do-while, andforloops, control iteration withbreakandcontinue, nest loops for multi-dimensional tasks, and distinguish counter-controlled from event-controlled repetition.
2. Learning Outcomes
Upon completing this chapter, students will be able to:
- Explain the difference between entry-controlled loops (
while,for) and the exit-controlled loop (do-while), and select the appropriate construct for a given problem. - Use compound assignment operators (
+=,-=,*=,/=,%=) and the increment/decrement operators (++,--) correctly, distinguishing prefix from postfix behaviour. - Design counter-controlled loops (known iteration count) and event-controlled (sentinel) loops (unknown iteration count).
- Apply the
forloop idiom for counting tasks and understand how its three clauses map onto initialisation, condition, and modification. - Construct nested loops to solve two-dimensional problems such as pattern printing and multiplication tables.
- Use
breakto exit a loop early andcontinueto skip to the next iteration, including the deliberate use of infinite loops withbreak. - Apply the principle of parameterisation to replace hard-coded limits with variables, making programmes more general and reusable.
3. Key Terms
| Term (EN) | 中文 | Notes |
|---|---|---|
| repetition structure / loop | 循环结构 | The third fundamental control structure; repeats a block while a condition holds. |
| entry-controlled loop | 入口控制循环 | Condition tested before the body executes (while, for). Body may execute zero times. |
| exit-controlled loop | 出口控制循环 | Condition tested after the body executes (do-while). Body always executes at least once. |
while loop | while 循环 | Entry-controlled; most general form of loop. |
do-while loop | do-while 循环 | Exit-controlled; guarantees at least one execution of the body. |
for loop | for 循环 | Entry-controlled; bundles initialisation, condition, and modification into one header. |
| counter-controlled loop | 计数器控制循环 | Iteration count is known in advance (e.g., "repeat 10 times"). |
| event-controlled / sentinel loop | 事件/哨兵控制循环 | Iteration ends when a special sentinel value is encountered; count is unknown in advance. |
| sentinel value | 哨兵值 | A marker value distinct from valid data that signals the end of input (e.g., −1). |
| compound assignment operator | 复合赋值运算符 | +=, -=, *=, /=, %= — shorthand for var = var op expr. |
| increment / decrement operator | 自增/自减运算符 | ++ / --. Prefix form modifies before use; postfix form modifies after use. |
| nested loop | 嵌套循环 | A loop placed inside the body of another loop; the inner loop completes all iterations per outer iteration. |
break | break 语句 | Immediately exits the innermost enclosing loop (or switch). |
continue | continue 语句 | Skips the remainder of the current iteration and jumps to the next condition check (or modification step in for). |
| infinite loop | 无限循环 | A loop whose condition never becomes false (e.g., while (1)); must contain a break or external termination. |
| parameterisation | 参数化 | Replacing hard-coded constants with variables so that a programme adapts to different inputs without rewriting. |
4. Core Concepts
4.1 The Need for Repetition
Consider printing the integers 1 to 5. Without a loop the programme requires five separate printf calls:
printf("1\n");
printf("2\n");
printf("3\n");
printf("4\n");
printf("5\n");
If the requirement changes to printing 1 to 10 000, this approach is clearly unworkable. A loop lets us write the action once and execute it as many times as needed, driven by a condition that eventually becomes false.
All programmes can be written using three control structures: sequence (Lecture 0–1), selection (Lecture 2), and repetition (this lecture). Mastering loops completes the structural foundation upon which all subsequent topics build.
Takeaway: Loops eliminate code duplication and make programmes adaptable to varying data sizes.
4.2 The while Loop
The while loop is an entry-controlled (pre-test) loop. It evaluates the condition before each iteration; if the condition is false on the very first test, the body never executes at all.
while (condition)
{
statement;
}
The general pattern involves three components, though they appear in separate locations:
- Initialisation — set the loop variable before the
while. - Condition — tested at the top of each iteration.
- Modification — update the loop variable inside the body to ensure eventual termination.
Forgetting the modification step is the most common cause of infinite loops.
Minimal example
File: p03_while.c
Build: gcc p03_while.c -o p03_while
Run: ./p03_while
#include <stdio.h>
int main(void)
{
int i = 1; /* 1. Initialisation */
while (i <= 5) { /* 2. Condition */
printf("%d\n", i);
i = i + 1; /* 3. Modification */
}
return 0;
}
What you should see: The integers 1 through 5, each on its own line.
Takeaway: The while loop is the most general loop construct; when you are unsure which loop to use, while is always a safe choice.
4.3 Compound Assignment Operators
C provides shorthand operators that combine an arithmetic operation with assignment. They reduce verbosity and are especially convenient inside loop bodies.
| Operator | Example | Equivalent |
|---|---|---|
= | a = b | a = b |
+= | a += b | a = a + b |
-= | a -= b | a = a - b |
*= | a *= b | a = a * b |
/= | a /= b | a = a / b |
%= | a %= b | a = a % b |
Using the while example from §4.2, the modification i = i + 1 may equivalently be written i += 1.
Takeaway: Compound assignment operators are syntactic sugar; use them for clarity, but ensure you understand the equivalent longhand form.
4.4 Increment and Decrement Operators
The increment (++) and decrement (--) operators add or subtract 1 from a variable. Each has two forms:
- Prefix (
++i/--i): the variable is modified before its value is used in the surrounding expression. - Postfix (
i++/i--): the current value is used first, and the variable is modified afterwards.
When the operator appears as a standalone statement (e.g., i++; on its own line), the two forms are functionally identical. The distinction matters only when the expression's value is consumed in the same statement, such as printf("%d", count++) versus printf("%d", ++count).
Minimal example
File: p03_incdec.c
Build: gcc p03_incdec.c -o p03_incdec
Run: ./p03_incdec
#include <stdio.h>
int main(void)
{
int count = 0;
printf("Postfix increment loop:\n");
while (count < 5) {
printf("Count: %d\n", count++); /* prints 0,1,2,3,4 */
}
count = 0;
printf("\nPrefix increment loop:\n");
while (count < 5) {
printf("Count: %d\n", ++count); /* prints 1,2,3,4,5 */
}
return 0;
}
What you should see: The postfix loop prints 0 through 4; the prefix loop prints 1 through 5.
Takeaway: Prefer using i++ or ++i as a standalone statement for the loop update; embedding it inside a complex expression is error-prone and hurts readability.
4.5 Counter-Controlled vs Event-Controlled Loops
Loops fall into two broad categories based on how termination is determined:
Counter-controlled loops iterate a known number of times. A counter variable is initialised, tested, and incremented on each pass. The class-average programme below illustrates this: we know there are exactly num_students grades to read.
Event-controlled (sentinel) loops iterate an unknown number of times. Termination is triggered by a special sentinel value — a value chosen to be outside the range of valid data. For example, using −1 as a sentinel when all legitimate grades are in [0, 100].
The sentinel approach has a standard pattern: read the first value before the loop, then test for the sentinel in the while condition, and read the next value at the end of the loop body.
Counter-controlled example (average of a fixed class size):
File: p03_counter.c
Build: gcc p03_counter.c -o p03_counter
Run: ./p03_counter
#include <stdio.h>
int main(void)
{
int num_students;
printf("Enter the number of students: ");
scanf("%d", &num_students);
float grade, total = 0.0f;
int i = 1;
while (i <= num_students) {
printf("Enter the grade of student %d (0-100): ", i);
scanf("%f", &grade);
total += grade;
i++;
}
float avg = total / num_students;
printf("The average of grades is %.1f\n", avg);
return 0;
}
Sentinel-controlled example (average of an unknown class size):
File: p03_sentinel.c
Build: gcc p03_sentinel.c -o p03_sentinel
Run: ./p03_sentinel
#include <stdio.h>
int main(void)
{
int i = 1;
float grade, total = 0.0f;
printf("Enter grades (0-100). Enter -1 to stop.\n");
printf("Enter the grade of student %d: ", i);
scanf("%f", &grade); /* priming read */
while (grade >= 0) {
total += grade;
i++;
printf("Enter the grade of student %d: ", i);
scanf("%f", &grade); /* update read */
}
float avg = total / (i - 1);
printf("The average of grades is %.1f\n", avg);
return 0;
}
Takeaway: Use a counter-controlled loop when the iteration count is known before the loop starts; use a sentinel loop when the count depends on run-time input.
4.6 Parameterisation and Abstraction
The first version of the class-average programme hard-coded the class size as 5. If the class size changes, the source code must be edited and recompiled. By replacing the literal 5 with a variable num_students read from the user, the programme becomes general-purpose — this is parameterisation.
Parameterisation is a manifestation of abstraction, a fundamental principle in software engineering. Abstracted code can be reused across different contexts without modification. Whenever you find yourself writing a magic number in a loop bound or a calculation, ask: "Could this be a variable instead?"
Takeaway: Always parameterise loop bounds and other constants so that programmes adapt to different inputs without source-code changes.
4.7 The do-while Loop
The do-while loop is an exit-controlled (post-test) loop. The body executes first, and the condition is tested afterwards. This guarantees that the body runs at least once, regardless of the condition's initial value.
do
{
statement;
}
while (condition);
Note the semicolon after the closing parenthesis — a frequent source of syntax errors.
The do-while is most naturally used when the first iteration must happen unconditionally — for example, displaying a menu and reading a choice before it is meaningful to test whether the choice is valid.
Minimal example
File: p03_dowhile.c
Build: gcc p03_dowhile.c -o p03_dowhile
Run: ./p03_dowhile
#include <stdio.h>
int main(void)
{
int i = 1;
do {
printf("%d\n", i);
i++;
} while (i <= 5);
return 0;
}
What you should see: The integers 1 through 5.
Sentinel version using do-while — the sentinel-controlled average can also be written with do-while, though the post-processing is slightly more involved because the sentinel value is added to the total before the test:
do {
printf("Enter the grade of student %d: ", i);
scanf("%f", &grade);
total += grade;
i++;
} while (grade >= 0);
/* Correct for the sentinel that was added: */
float avg = (total - grade) / (i - 2);
This works, but the need to subtract the sentinel afterwards makes the while-with-priming-read pattern generally cleaner for sentinel loops.
Takeaway: Use do-while when the body must execute at least once; otherwise prefer while or for.
4.8 The for Loop
The for loop bundles all three loop-control components — initialisation, condition, and modification — into a single header:
for (initialisation; condition; modification)
{
statement;
}
Execution proceeds as follows:
- The initialisation executes exactly once.
- The condition is evaluated. If false, the loop terminates immediately.
- If true, the body executes.
- The modification executes.
- Control returns to step 2.
The for loop is the idiomatic choice for counter-controlled repetition. It keeps the loop variable's lifecycle compact and visible in one place, reducing the risk of forgetting the modification step.
Minimal example
File: p03_for.c
Build: gcc p03_for.c -o p03_for
Run: ./p03_for
#include <stdio.h>
int main(void)
{
for (int i = 1; i <= 5; i++) {
printf("%d\n", i);
}
return 0;
}
What you should see: The integers 1 through 5.
The modification clause is not limited to i++. Any expression is valid; for example, i += 2 produces even numbers:
for (int i = 0; i <= 10; i += 2) {
printf("%d\n", i); /* prints 0, 2, 4, 6, 8, 10 */
}
Equivalence with while: Any for loop can be rewritten as a while loop (and vice versa). If the initialisation and modification clauses are omitted, the for degenerates into a while:
int i = 1;
for (; i <= 5; ) { /* equivalent to while (i <= 5) */
printf("%d\n", i);
i++;
}
Takeaway: Use for when the iteration count is determined by a simple counter; use while when termination depends on a more complex or event-driven condition.
4.9 Nested Loops
A nested loop is a loop placed inside the body of another loop. For each single iteration of the outer loop, the inner loop runs through all of its iterations from start to finish. If the outer loop iterates m times and the inner loop iterates n times, the body of the inner loop executes m × n times in total.
Nested loops are essential for problems involving two-dimensional structures: printing patterns, processing matrices, generating multiplication tables, and comparing elements pairwise.
Minimal example — number triangle
File: p03_nested.c
Build: gcc p03_nested.c -o p03_nested
Run: ./p03_nested
#include <stdio.h>
int main(void)
{
int n;
printf("Enter the number of rows: ");
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
printf("%d", j);
}
printf("\n");
}
return 0;
}
What you should see (for n = 4):
1
12
123
1234
Combining different loop types — the following fragment uses a for as the outer loop, a while as the inner loop, and a do-while to print a separator. This demonstrates that any loop type may be nested within any other:
int num, multiplier, max_num = 25;
for (num = 1; num <= max_num; num++) {
printf("Multiplication Table for %d:\n", num);
multiplier = 1;
while (multiplier <= max_num) {
printf("%d * %d = %2d\n", num, multiplier, num * multiplier);
multiplier++;
}
int count = 0;
do {
printf("-");
count++;
} while (count < 16);
printf("\n");
}
Takeaway: Keep nesting shallow (ideally two levels) and use meaningful variable names for each level to maintain readability.
4.10 break and continue
Two statements modify the normal flow of a loop:
break— immediately exits the innermost enclosing loop. Execution continues with the first statement after the loop. (We metbreakinswitchstatements in Lecture 2; it works identically in loops.)continue— skips the remaining statements in the current iteration and jumps directly to the next condition evaluation (forwhileanddo-while) or to the modification step (forfor).
Minimal example
File: p03_breakcont.c
Build: gcc p03_breakcont.c -o p03_breakcont
Run: ./p03_breakcont
#include <stdio.h>
int main(void)
{
printf("break example:\n");
for (int i = 1; i <= 5; i++) {
if (i == 3) {
break; /* exits the loop entirely */
}
printf("%d\n", i);
}
/* Output: 1, 2 */
printf("\ncontinue example:\n");
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue; /* skips to i++ */
}
printf("%d\n", i);
}
/* Output: 1, 2, 4, 5 */
return 0;
}
What you should see: The break section prints 1 and 2 only. The continue section prints 1, 2, 4, 5 (skipping 3).
Takeaway: Use break sparingly to handle early-exit conditions; use continue to skip unwanted iterations without increasing indentation depth.
4.11 Infinite Loops and Deliberate Use of break
An infinite loop is a loop whose condition never becomes false. In C the canonical form is while (1) (or equivalently for (;;)). On its own an infinite loop hangs the programme, but combined with an internal break it provides an elegant pattern for event-driven input processing:
while (1) {
/* prompt and read */
if (exit_condition) {
break;
}
/* process */
}
This pattern is often cleaner than a sentinel while loop because it avoids the priming read and the duplicated scanf call.
Minimal example
File: p03_infinite.c
Build: gcc p03_infinite.c -o p03_infinite
Run: ./p03_infinite
#include <stdio.h>
int main(void)
{
int num;
while (1) {
printf("Enter a positive number [0 to stop]: ");
scanf("%d", &num);
if (num == 0) {
printf("Exiting loop...\n");
break;
}
printf("You entered: %d\n", num);
}
return 0;
}
What you should see: The programme repeatedly prompts for input, echoing each value, until the user enters 0.
Takeaway: Infinite loops with break are a legitimate and often preferred idiom for interactive programmes; the key is ensuring that the break condition is always reachable.
5. Worked Examples
Example 1: Factorial Calculation
Problem: Read a non-negative integer N from the user and compute N! (N factorial). Recall that N! = 1 × 2 × 3 × … × N, with 0! = 1 by convention.
Steps:
- Read N.
- Initialise
result = 1. - Use a
forloop from 1 to N, multiplyingresultby the loop counter on each iteration. - Print the result.
Reference code
File: p03_ex1.c
Build: gcc p03_ex1.c -o p03_ex1
Run: ./p03_ex1
#include <stdio.h>
int main(void)
{
int n;
printf("Enter a number: ");
scanf("%d", &n);
long result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
printf("Factorial of %d is %ld\n", n, result);
return 0;
}
Output:
Enter a number: 5
Factorial of 5 is 120
Why it works: The for loop is a natural fit because we know exactly how many multiplications are required (N). The variable result acts as an accumulator, a common loop pattern in which a running total (or product) is built up across iterations. We use long to accommodate the rapid growth of factorial values.
Example 2: Reverse a Number
Problem: Read an integer and print its digits in reverse order.
Steps:
- Read the number.
- In each iteration: extract the last digit with
num % 10, print (or accumulate) it, then remove the last digit withnum /= 10. - Repeat while
numis non-zero.
Reference code
File: p03_ex2.c
Build: gcc p03_ex2.c -o p03_ex2
Run: ./p03_ex2
#include <stdio.h>
int main(void)
{
int num;
printf("Enter a number: ");
scanf("%d", &num);
int reversed = 0;
while (num != 0) {
int digit = num % 10;
reversed = reversed * 10 + digit;
num /= 10;
}
printf("Reversed number: %d\n", reversed);
return 0;
}
Output:
Enter a number: 1234
Reversed number: 4321
Why it works: The modulus operator % 10 isolates the units digit, and integer division / 10 shifts all remaining digits one place to the right. The while loop terminates naturally when all digits have been consumed (i.e., num becomes 0). This is an event-controlled loop — we do not know in advance how many digits the number contains.
Example 3: First N Prime Numbers
Problem: Read an integer N and print the first N prime numbers. A prime number is greater than 1 and divisible only by 1 and itself.
Steps:
- Read N.
- Start testing candidates from 2. For each candidate, check divisibility by all integers from 2 up to its square root (trial division).
- If no divisor is found, the candidate is prime — print it and increment a counter.
- Continue until the counter reaches N.
Reference code
File: p03_ex3.c
Build: gcc p03_ex3.c -o p03_ex3
Run: ./p03_ex3
#include <stdio.h>
int main(void)
{
int n;
printf("Enter the number of prime numbers to display: ");
scanf("%d", &n);
int count = 0;
int candidate = 2;
printf("First %d prime numbers:", n);
while (count < n) {
int is_prime = 1;
for (int d = 2; d * d <= candidate; d++) {
if (candidate % d == 0) {
is_prime = 0;
break; /* no need to test further */
}
}
if (is_prime) {
printf(" %d", candidate);
count++;
}
candidate++;
}
printf("\n");
return 0;
}
Output:
Enter the number of prime numbers to display: 5
First 5 prime numbers: 2 3 5 7 11
Why it works: The outer while loop is event-controlled — it runs until we have found N primes. The inner for loop is counter-controlled — it tests divisors from 2 up to √candidate. The break inside the inner loop provides an early exit as soon as a factor is discovered, avoiding unnecessary computation. The condition d * d <= candidate is equivalent to d <= √candidate but avoids floating-point arithmetic.
6. Common Mistakes
-
Forgetting the modification step in a
whileloop: If the loop variable is never updated, the condition never becomes false and the programme hangs in an infinite loop. Always verify that eachwhilebody modifies a variable that appears in the condition. -
Off-by-one errors in loop bounds: Using
<instead of<=(or vice versa) causes the loop to execute one too few or one too many times. Trace through the first and last iterations on paper to verify correctness. -
Confusing prefix and postfix
++/--inside expressions:printf("%d", count++)prints the old value, whereasprintf("%d", ++count)prints the new value. When the distinction matters, prefer separating the increment from the expression: increment on its own line, then use the variable. -
Missing the semicolon after
do-while: The constructdo { ... } while (condition)requires a trailing semicolon. Omitting it is a syntax error that may produce a confusing diagnostic. -
Placing a semicolon directly after
for (...)orwhile (...): Writingfor (i = 0; i < 5; i++);creates an empty loop body (the semicolon is the body), so the block{...}that follows executes only once. This is a silent bug — the compiler may not warn. -
Modifying the loop counter inside a
forbody: Although legal, changing the counter variable inside the body (in addition to the modification clause) leads to confusing and error-prone code. Let theforheader be the sole authority on the counter's evolution. -
Using
breakorcontinuewithout understanding scope: Both statements affect only the innermost enclosing loop. In nested loops, abreakexits only the inner loop; the outer loop continues normally. If you need to exit multiple levels, consider a flag variable or restructuring the logic.
7. Practice
7.1 Basic
-
P1 — Print Numbers with
while: Write a programme that prints the integers from 1 to 10 using awhileloop. Output:1 2 3 4 5 6 7 8 9 10Acceptance: All ten numbers appear on one line, separated by spaces. -
P2 — Sum of N Natural Numbers: Ask the user for a positive integer N and compute the sum 1 + 2 + … + N using a
whileloop. Input/Output:Enter a number: 5→Sum of first 5 natural numbers is 15Acceptance: Correct for any positive N. -
P3 — Print Even Numbers: Print all even numbers between 1 and 20 (inclusive). Output:
2 4 6 8 10 12 14 16 18 20Acceptance: Correct list; implemented with a loop (not 10printfcalls).
7.2 Required
-
P4 — Multiplication Table: Ask the user for a number N and print its multiplication table from 1 to 9 using a
do-whileloop. Input/Output:Enter a number: 4→4 x 1 = 4,4 x 2 = 8, …,4 x 9 = 36. Acceptance: Correct table; usesdo-while. -
P5 — Factorial Calculation: Compute the factorial of a given non-negative integer N using a
forloop. Input/Output:Enter a number: 5→Factorial of 5 is 120Acceptance: Handles N = 0 (result is 1) through at least N = 12 without overflow. -
P6 — Reverse a Number: Read an integer and print its digits in reverse order. Input/Output:
Enter a number: 1234→Reversed number: 4321Hint: Use% 10to extract the last digit and/ 10to remove it. Acceptance: Correct for any positive integer. -
P7 — Using
breakto Exit an Infinite Loop: Write a programme that runs an infinite loop, reading integers from the user. If the user enters −1, break out of the loop and printLoop terminated.Input/Output: User enters1,2,4,-1→ programme echoes each value, then printsLoop terminated.Acceptance: Loop exits only on −1; other negative numbers are echoed normally. -
P8 — Skipping Even Numbers with
continue: Print the integers from 1 to 10, but usecontinueto skip even numbers. Output:1 3 5 7 9Acceptance: Only odd numbers appear; implemented usingcontinue.
7.3 Optional
-
P9 — First N Prime Numbers: Ask the user for N and print the first N prime numbers using nested loops and the trial-division method. Input/Output:
Enter the number of prime numbers to display: 5→First 5 prime numbers: 2 3 5 7 11Hint: A number is prime if it has no divisor between 2 and its square root. Acceptance: Correct for N up to at least 50. -
P10 — Right-Angled Triangle Pattern: Read the number of rows N and print a right-angled triangle of
*characters using nestedforloops. Input/Output:Enter the number of rows: 5→** ** * ** * * ** * * * *Acceptance: Correct pattern for any N ≥ 1.
8. Mini Task
Goal: Build a number-guessing game. The programme selects a secret number (hard-code it, or use rand() if you wish to experiment) in the range 1–100. The user repeatedly guesses; after each guess the programme reports "Too high", "Too low", or "Correct!". Track the number of attempts and print it when the user succeeds. Use an infinite loop with break.
Deliverables:
README.md: Compilation and run instructions; a sample session showing 4–5 guesses.src/guess.c: The source file.report.md: A brief summary (200–300 words) describing which loop construct you chose, why, and how you handled invalid input.
9. Further Reading
- Deitel & Deitel, C How to Program (9th ed.): Chapter 4 — C Program Control.
- King, C Programming: A Modern Approach (2nd ed.): Chapter 6 — Loops.
- ISO/IEC 9899:2018 (C18 Standard): §6.8.5 — Iteration statements (
while,do,for); §6.8.6.3 — Thebreakstatement; §6.8.6.2 — Thecontinuestatement.
10. Appendix
A. Loop Selection Guide
| Situation | Recommended loop | Reason |
|---|---|---|
| Iteration count known before the loop starts | for | All three control clauses in one header; intent is clear. |
| Iteration count unknown; body may not need to execute | while | Pre-test ensures zero iterations are possible. |
| Iteration count unknown; body must run at least once (e.g., menu, input validation) | do-while | Post-test guarantees first execution. |
| Event-driven exit from the middle of the body | while (1) + break | Avoids duplicated priming reads; clean separation of exit logic. |
B. Tracing Pre/Postfix in a Loop Condition
Consider:
int count = 0;
while (count++ < 5) {
printf("Count: %d\n", count);
}
At each evaluation of the condition, count is compared before the increment (postfix), but the printf inside the body sees the already-incremented value:
| Iteration | Condition test (count before ++) | count inside body |
|---|---|---|
| 1 | 0 < 5 → true | 1 |
| 2 | 1 < 5 → true | 2 |
| 3 | 2 < 5 → true | 3 |
| 4 | 3 < 5 → true | 4 |
| 5 | 4 < 5 → true | 5 |
| 6 | 5 < 5 → false | (body not entered) |
The loop body executes 5 times, printing 1 through 5. Although this pattern works, it sacrifices clarity; separating the increment from the condition is generally preferable.