Doing things repeatedly

Real-World Analogy

Imagine a factory assembly line. Workers repeat the same task for every item that comes down the belt. A for loop is like knowing in advance exactly how many items will come — "process exactly 100 parts." A while loop is like working until a red light flashes — "keep going until the stop signal." A do-while loop is like tasting a dish before deciding whether to add more seasoning — you always do it at least once, then check whether to repeat.

In Python you used for i in range(10) or while condition. Java added a for-each syntax. In C, loops look similar to Java but have important differences: the for loop variable is not scoped to the loop in C89/C90 (though C99 and later do allow it), and C has no built-in for-each — you iterate over arrays manually with an index.

C's three loop types share one underlying rule: each loop has a condition expression. When that condition evaluates to zero (false), the loop exits. When it is non-zero (true), the body executes again. This is the same rule that governs if statements.

The three loops differ only in when the condition is checked and what happens on each cycle:

Loop Checks condition Minimum executions Best when you know...
for Before each iteration 0 (may never run) ...the exact iteration count up front
while Before each iteration 0 (may never run) ...you want to loop until a condition changes
do-while After each iteration 1 (always runs once) ...the body must run at least once (e.g. menus)
Python (what you know)
# Python for loop
for i in range(10):
    print(i)

# Python while loop
n = 10
while n > 0:
    print(n)
    n -= 1

# Python has no do-while —
# simulate with while True + break
while True:
    x = int(input("Enter > 0: "))
    if x > 0:
        break
C (what you are learning)
/* C for loop */
for (int i = 0; i < 10; i++) {
    printf("%d\n", i);
}

/* C while loop */
int n = 10;
while (n > 0) {
    printf("%d\n", n);
    n--;
}

/* C do-while — runs body first */
int x;
do {
    printf("Enter > 0: ");
    scanf("%d", &x);
} while (x <= 0);
Java (comparison)
// Java for-each (no C equivalent!)
int[] arr = {1, 2, 3};
for (int val : arr) {
    System.out.println(val);
}

// Java for — same syntax as C
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}
// Key difference: loop var always
// scoped to the loop in Java.
C array iteration
/* C has no for-each — use index */
int arr[] = {1, 2, 3};
int len = 3;
for (int i = 0; i < len; i++) {
    printf("%d\n", arr[i]);
}

/* In C89, declare i BEFORE loop: */
int i;
for (i = 0; i < len; i++) {
    printf("%d\n", arr[i]);
}
Off-by-one errors — the most common loop bug

Should the condition be i < 10 or i <= 10? For an array of 10 elements, valid indices are 0 through 9. Use i < 10 (less than, not less-than-or-equal). i <= 10 would access arr[10] — one past the end — causing undefined behavior. This off-by-one error is so common it has its own name: fencepost error.

break and continue

break exits the smallest enclosing loop immediately — execution jumps to the first statement after the loop. continue skips the rest of the current iteration and jumps to the loop's update step (for loops) or condition check (while/do-while). Neither break nor continue accept labels in C — they only affect the innermost loop.

Infinite loops

A loop whose condition is always true (or never false) runs forever. while (1) { ... } and for (;;) { ... } are both valid intentional infinite loops — used in server event loops and embedded systems. An accidental infinite loop usually means you forgot to update the loop variable, or used the wrong condition. Check: does your loop variable get modified inside the body?

Anatomy of each loop type

The for loop

for ( int i = 0 ;  i < 10 ;  i++ )  {
 ^      ^^^^^^^^^^^    ^^^^^^^^^    ^^^^^^
 |      initializer    condition    update
 |      runs once      checked      runs after
 keyword before loop   each iter    each body
    printf("%d\n", i);
}

/* All three parts are OPTIONAL: */
for (;;) { /* infinite loop — equivalent to while(1) */ }
for (i=0; i<10;) { i++; }  /* update in body instead */
Execution order: (1) initializer runs once. (2) condition checked — if false, loop exits. (3) body executes. (4) update runs. Go back to (2).

The while loop

while ( condition ) {
         ^^^^^^^^^
         evaluated BEFORE body runs
         if false on first check: body never runs
    /* body */
}

/* Example: read until valid input */
int x = 0;
while (x <= 0) {
    scanf("%d", &x);
}
Note: If x were already positive before the loop, the body would never execute — the condition is false from the start.

The do-while loop

do {
    /* body ALWAYS runs at least once */
    printf("Enter a positive number: ");
    scanf("%d", &x);
} while (x <= 0);
          ^^^^^^^^^^^^^^^
          Note the SEMICOLON after the while condition
          — this is required and easy to forget!
Key difference from while: Condition is checked after the body. The body is guaranteed to run at least once. Classic use case: input validation menus — you must show the menu at least once before checking if user wants to quit.

break and continue

/* break: exit the loop immediately */
for (int i = 0; i < 10; i++) {
    if (i == 5) break;  // exits when i reaches 5
    printf("%d ", i);     // prints: 0 1 2 3 4
}

/* continue: skip rest of THIS iteration */
for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) continue;  // skip even numbers
    printf("%d ", i);  // prints: 1 3 5 7 9
}

/* In NESTED loops: break/continue affect INNERMOST loop only */
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (j == 1) break;  // only breaks the INNER loop
        printf("(%d,%d) ", i, j);
    }
}  // prints: (0,0) (1,0) (2,0)

Complete programs you can compile and run

Example 1 — for loop: sum and search in an array Week 2 Lecture
#include <stdio.h>

int main(void) {
    int scores[] = {78, 92, 55, 88, 71, 95, 60};
    int n = 7;  /* number of elements */

    /* --- Pattern 1: Summing with a for loop --- */
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += scores[i];   /* same as: sum = sum + scores[i] */
    }
    printf("Sum:     %d\n", sum);
    printf("Average: %.1f\n", (double)sum / n);

    /* --- Pattern 2: Finding the maximum --- */
    int max = scores[0];   /* assume first is max */
    for (int i = 1; i < n; i++) {
        if (scores[i] > max) {
            max = scores[i];
        }
    }
    printf("Maximum: %d\n", max);

    /* --- Pattern 3: Linear search, using break --- */
    int target = 88;
    int found_at = -1;
    for (int i = 0; i < n; i++) {
        if (scores[i] == target) {
            found_at = i;
            break;   /* stop as soon as we find it */
        }
    }
    if (found_at != -1)
        printf("Found %d at index %d\n", target, found_at);
    else
        printf("%d not found\n", target);

    /* --- Pattern 4: Counting with continue --- */
    int above_80 = 0;
    for (int i = 0; i < n; i++) {
        if (scores[i] <= 80) continue;   /* skip scores <= 80 */
        above_80++;
    }
    printf("Scores above 80: %d\n", above_80);

    return 0;
}
Output
Sum: 539
Average: 77.0
Maximum: 95
Found 88 at index 3
Scores above 80: 3
Example 2 — while and do-while: input validation and digit counting Week 2 Lecture + Tutorial
#include <stdio.h>

int main(void) {
    /* --- do-while: keep asking until valid input --- */
    int age;
    do {
        printf("Enter your age (1-120): ");
        scanf("%d", &age);
        if (age < 1 || age > 120)
            printf("  Invalid — try again.\n");
    } while (age < 1 || age > 120);
    printf("Age accepted: %d\n\n", age);

    /* --- while: count digits in a number --- */
    int n;
    printf("Enter a positive integer: ");
    scanf("%d", &n);

    int original = n;
    int digits = 0;
    while (n > 0) {
        n /= 10;   /* remove the last digit */
        digits++;
    }
    printf("%d has %d digit(s)\n\n", original, digits);

    /* --- while with EOF: sum numbers until end of input --- */
    printf("Enter numbers (Ctrl+D to stop):\n");
    int val, total = 0, count = 0;
    while (scanf("%d", &val) == 1) {   /* returns 1 while reading succeeds */
        total += val;
        count++;
    }
    if (count > 0)
        printf("Sum of %d numbers: %d, average: %.2f\n",
               count, total, (double)total / count);

    return 0;
}
Sample run
Enter your age (1-120): -5
Invalid — try again.
Enter your age (1-120): 21
Age accepted: 21

Enter a positive integer: 12345
12345 has 5 digit(s)
Example 3 — Nested loops: multiplication table and pattern printing Week 2 Lecture
#include <stdio.h>

int main(void) {
    /* --- Nested for loops: multiplication table --- */
    int size = 5;
    printf("Multiplication table:\n");
    for (int i = 1; i <= size; i++) {
        for (int j = 1; j <= size; j++) {
            printf("%4d", i * j);   /* %4d: right-align in 4-char field */
        }
        printf("\n");   /* newline after each row */
    }

    printf("\n");

    /* --- Nested loops with break in inner: right triangle --- */
    printf("Triangle pattern:\n");
    for (int row = 1; row <= 5; row++) {
        for (int col = 1; col <= row; col++) {
            printf("* ");
        }
        printf("\n");
    }

    /* --- Nested loops with continue: skip diagonal --- */
    printf("\nOff-diagonal pairs (i != j), i,j in 1..3:\n");
    for (int i = 1; i <= 3; i++) {
        for (int j = 1; j <= 3; j++) {
            if (i == j) continue;   /* skip diagonal */
            printf("(%d,%d) ", i, j);
        }
        printf("\n");
    }

    return 0;
}
Output
Multiplication table:
   1   2   3   4   5
   2   4   6   8  10
   3   6   9  12  15
   4   8  12  16  20
   5  10  15  20  25

Triangle pattern:
*
* *
* * *
* * * *
* * * * *

Practice problems with solutions

P1 — Predict the output: tricky loop counters Week 2 Tutorial

Without running the code, predict exactly what is printed. Pay careful attention to the loop conditions and whether < or <= is used.

#include <stdio.h>
int main(void) {
    int i;

    /* Loop A */
    for (i = 0; i < 5; i++)
        printf("A%d ", i);
    printf("\n");

    /* Loop B */
    for (i = 1; i <= 5; i++)
        printf("B%d ", i);
    printf("\n");

    /* Loop C */
    for (i = 10; i > 0; i -= 3)
        printf("C%d ", i);
    printf("\n");

    /* Loop D */
    i = 0;
    while (i++ < 3)
        printf("D%d ", i);
    printf("\n");

    return 0;
}
A0 A1 A2 A3 A4
B1 B2 B3 B4 B5
C10 C7 C4 C1
D1 D2 D3 
Loop A: i starts at 0, runs while i < 5, increments. Runs for i = 0,1,2,3,4 (5 iterations).
Loop B: i starts at 1, runs while i <= 5. Runs for i = 1,2,3,4,5 (also 5 iterations but starting from 1).
Loop C: Counts down by 3 from 10. i = 10, 7, 4, 1. When i becomes -2, condition 10>0 fails, stop.
Loop D: Post-increment i++: condition checks old value, then increments. When i=0: check 0<3 (true), then i becomes 1, prints D1. When i=3: check 3<3 (false — note: was 2, incremented to 3 AFTER the check passed), so prints D3. The key: i++ returns the value BEFORE incrementing.
P2 — Spot the bug: off-by-one error Week 2 Tutorial + Exam material

The code below is supposed to print all elements of a 5-element array. It has an off-by-one error. Find the bug, explain what goes wrong, and fix it.

#include <stdio.h>
int main(void) {
    int arr[5] = {10, 20, 30, 40, 50};

    for (int i = 0; i <= 5; i++) {   /* BUG IS HERE */
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    return 0;
}
#include <stdio.h>
int main(void) {
    int arr[5] = {10, 20, 30, 40, 50};

    for (int i = 0; i < 5; i++) {   /* FIXED: < not <= */
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    return 0;
}
The bug: i <= 5 allows i to reach the value 5. But for a 5-element array, valid indices are 0 through 4. arr[5] is one past the end of the array — accessing it is undefined behavior in C. On most systems this reads garbage memory; it could crash the program, print a random value, or seem to work fine (which is even more dangerous).

The fix: Use i < 5 (strict less-than). General rule: for an array of size N, loop with i < N. The indices 0, 1, 2, ..., N-1 give you exactly N iterations.
P3 — Write a loop: FizzBuzz Classic interview / tutorial exercise

Print the integers 1 through 30. But for multiples of 3 print "Fizz" instead of the number, for multiples of 5 print "Buzz", and for multiples of both 3 and 5 print "FizzBuzz". Use a for loop and the % (modulo) operator.

#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 30; i++) {
        /* Check divisible by BOTH first — order matters! */
        if (i % 15 == 0)       /* 15 = 3*5 */
            printf("FizzBuzz\n");
        else if (i % 3 == 0)
            printf("Fizz\n");
        else if (i % 5 == 0)
            printf("Buzz\n");
        else
            printf("%d\n", i);
    }
    return 0;
}
Why check 15 first? If you check % 3 first, a number like 15 would print "Fizz" and never reach the "Buzz" check. You need to handle the "both" case before the individual cases. Alternatively, you could build the output string conditionally, or use i % 3 == 0 && i % 5 == 0 — all equivalent.
P4 — while loop: collatz sequence Tutorial

The Collatz sequence starting from a positive integer n is defined as: if n is even, divide by 2; if n is odd, multiply by 3 and add 1. Repeat until n becomes 1. Write a program that reads n from the user and prints the Collatz sequence, then prints how many steps it took.

#include <stdio.h>

int main(void) {
    int n;
    printf("Enter a positive integer: ");
    scanf("%d", &n);

    if (n <= 0) {
        printf("Error: must be positive.\n");
        return 1;
    }

    int steps = 0;
    printf("Sequence: %d", n);
    while (n != 1) {
        if (n % 2 == 0)
            n = n / 2;
        else
            n = 3 * n + 1;
        printf(" -> %d", n);
        steps++;
    }
    printf("\nSteps: %d\n", steps);
    return 0;
}
Why while and not for? We don't know in advance how many steps the sequence will take — it depends on n in a way that mathematicians still don't fully understand (the Collatz conjecture is unsolved). When the number of iterations is unknown, while is more natural than for. The loop terminates when n == 1.
P5 — Nested loops: print a diamond pattern Exam material

Write a program that reads an odd number n from the user and prints a diamond of asterisks of "width" n. For n=5 the output should be:
*
***
*****
***
*

#include <stdio.h>

int main(void) {
    int n;
    printf("Enter an odd number: ");
    scanf("%d", &n);
    int half = n / 2;

    /* Top half (including middle row) */
    for (int row = 0; row <= half; row++) {
        /* Print leading spaces */
        for (int s = 0; s < half - row; s++) printf(" ");
        /* Print stars */
        for (int s = 0; s < 2*row + 1; s++) printf("*");
        printf("\n");
    }
    /* Bottom half */
    for (int row = half - 1; row >= 0; row--) {
        for (int s = 0; s < half - row; s++) printf(" ");
        for (int s = 0; s < 2*row + 1; s++) printf("*");
        printf("\n");
    }
    return 0;
}
Pattern logic: Row row from the top has half - row leading spaces and 2*row + 1 stars. The top half counts row from 0 to half (inclusive). The bottom half mirrors by counting row from half-1 back down to 0. This uses three nested loops per half — a common exam pattern for 2D output.
P6 — do-while menu: user keeps choosing until quit Week 2 Tutorial

Write a simple menu-driven program. Show three options: (1) Print hello, (2) Print the current count, (3) Quit. Keep asking until the user picks 3. The program must always show the menu at least once. Use a do-while loop.

#include <stdio.h>

int main(void) {
    int choice = 0;
    int count  = 0;

    do {
        printf("\n--- Menu ---\n");
        printf("1. Say hello\n");
        printf("2. Show count (%d)\n", count);
        printf("3. Quit\n");
        printf("Choice: ");
        scanf("%d", &choice);

        if (choice == 1) {
            printf("Hello!\n");
            count++;
        } else if (choice == 2) {
            printf("You have chosen an option %d time(s).\n", count);
        } else if (choice != 3) {
            printf("Invalid choice — please enter 1, 2, or 3.\n");
        }
    } while (choice != 3);

    printf("Goodbye!\n");
    return 0;
}
Why do-while is perfect here: The menu must always appear at least once. With a regular while loop you would need to show the menu before the loop and again inside it (code duplication), or set a dummy initial value. do-while naturally expresses "execute body then check whether to repeat."

Key concepts to memorize

Card 1 of 10
Question — click to flip
Answer
Click card to flip • Use buttons to navigate

Test your understanding

Topic 05 Quiz — Loops Score: 0 / 6
1
How many times does this loop execute its body?
for (int i = 0; i < 10; i++)
LO1
multiple choice
2
True or False: A do-while loop is guaranteed to execute its body at least once, even if the condition is false.LO1
true / false
3
What does the continue statement do inside a for loop?LO1
multiple choice
4
Fill in the blank: the C syntax for an intentional infinite loop using only for is for ( ___ ) — write the three semicolon-separated parts inside the parentheses (just two semicolons, no spaces).LO1
fill in the blank
5
Spot the bug: this code tries to print elements 0 through 4 of a 5-element array. What is wrong?LO1
int arr[5] = {1,2,3,4,5};
for (int i = 0; i <= 5; i++) {
    printf("%d\n", arr[i]);
}
spot the bug — multiple choice
6
In nested loops, if a break statement is reached in the inner loop, what happens?LO1
multiple choice
0/6
Quiz complete!