Exercises — Control flow — if - else, switch, while, do-while, for, break, continue, goto
Before we start, one reminder that every problem leans on: in C a condition is true when its value is any non-zero number and false only when it is exactly 0. Keep that in the front of your mind — half the traps below live right there.
Level 1 — Recognition
Goal: read code, predict the printed output. No writing yet.
L1.1 — First true wins
Recall Solution
WHAT we do: check each condition top to bottom. WHY: an if/else if/else chain stops at the first true branch and skips the rest.
n > 0→0 > 0→ false.n == 0→0 == 0→ true → printB, then skip theelse.
Answer: B
L1.2 — while that never runs
Recall Solution
A while tests before the body. First test: 10 < 3 → false → body runs zero times.
Answer: done
L1.3 — do-while runs at least once
Recall Solution
A do-while runs the body first, then tests. So it prints 10 once, i becomes 11, test 11 < 3 false → stop.
Answer: 10 done
L1.4 — fall-through counting
Recall Solution
switch jumps to the matching label then falls through everything below until a break — and there are no breaks here. Landing on case 2, execution runs case 2, case 3, and default in a row.
Answer: two three end
Level 2 — Application
Goal: write short, correct snippets.
L2.1 — Print 0 to 4 with a for loop
Recall Solution
WHAT: build the 4-part loop (init, condition, update) with the body doing the print. WHY for: we know exactly how many times we count, so a counting loop is the natural fit.
for (int i = 0; i < 5; i++) {
printf("%d ", i);
}Condition i < 5 (strict less-than) stops after i = 4. Output: 0 1 2 3 4.
L2.2 — Sum 1 to 100
Recall Solution
int sum = 0;
for (int i = 1; i <= 100; i++) sum += i;
printf("%d", sum);WHY i <= 100: we want to include 100, so we use less-than-or-equal. The famous closed form tells us the answer must be 5050 — a good self-check.
L2.3 — Menu with do-while
Recall Solution
WHY do-while: we must ask once before we can judge the answer — "do, then decide whether to repeat" is exactly the do-while shape.
int choice;
do {
printf("Enter 1-3: ");
scanf("%d", &choice);
} while (choice < 1 || choice > 3);The || is logical OR: the loop repeats if choice is below 1 or above 3.
Level 3 — Analysis
Goal: trace tricky flow and find bugs.
L3.1 — break vs continue trace
Recall Solution
Trace each i:
i=0: not 1, not 4 → print0.i=1:continue→ jump straight toi++(update), print nothing.i=2: print2.i=3: print3.i=4:break→ leave the loop entirely.
Answer: 0 2 3
L3.2 — the = vs == bug
Recall Solution
x = 5 is assignment, not comparison. It stores 5 into x, and the whole expression's value is 5. Since 5 is non-zero, the condition is true → prints yes — always, regardless of x's old value.
The author almost surely meant x == 5 (comparison). Answer: yes (buggy).
L3.3 — the hidden infinite loop
Recall Solution
WHAT goes wrong: at i == 2, continue jumps back to the condition test — but i++ sits after the continue, so i is never incremented. i stays 2 forever → infinite loop (prints 0 1 then hangs).
WHY the for version was safe: in a for, continue still runs the header's update i++. In while you must run the update yourself before any continue.
Fix — increment before the skip:
int i = 0;
while (i < 5) {
int cur = i;
i++; // update first
if (cur == 2) continue;
printf("%d ", cur);
} // prints 0 1 3 4Output after fix: 0 1 3 4.
Level 4 — Synthesis
Goal: combine several tools into one working program.
L4.1 — FizzBuzz (selection + iteration)
Recall Solution
WHY this order of checks: test "both" first (% 3 == 0 && % 5 == 0), because if you test 3 alone first you'd print Fizz and miss the FizzBuzz case. The % operator (see C Operators) gives the remainder; remainder 0 means "divides evenly."
for (int i = 1; i <= 15; i++) {
if (i % 3 == 0 && i % 5 == 0) printf("FizzBuzz\n");
else if (i % 3 == 0) printf("Fizz\n");
else if (i % 5 == 0) printf("Buzz\n");
else printf("%d\n", i);
}Trace of the interesting cells: 3→Fizz, 5→Buzz, 15→FizzBuzz. The count of Fizz-only outputs in 1..15 is at 3,6,9,12 → 4 of them.
L4.2 — Escape nested loops with goto
Recall Solution
WHY goto here: a plain break only exits the inner loop; we'd re-enter the outer loop and keep scanning. goto jumps clean out of both at once — the one widely-accepted use of goto.
int grid[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
int target = 7, r = -1, c = -1;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (grid[i][j] == target) { r = i; c = j; goto found; }
found:
printf("(%d,%d)", r, c);Scanning row 0 (1 2 3), row 1 (4 5 6), row 2 starts with 7 → match at i=2, j=0.
Answer: (2,0)
Level 5 — Mastery
Goal: edge cases where instinct betrays you.
L5.1 — switch on a char that isn't there
Recall Solution
'X' matches no case, and there is no default. In that situation switch simply does nothing and control continues after the block.
So only the final printf runs. Answer: |end
(If a default existed, it would have caught 'X'.)
L5.2 — signed remainder of a negative number
Recall Solution
The trap: many expect -7 % 2 to be 1. In C (since C99) the result of % takes the sign of the dividend (n), so -7 % 2 == -1, not 1. But we only test == 0, and -1 != 0, so the branch is "odd" — correct here.
Answer: odd — but be warned: if you had written if (n % 2 == 1) to detect odd, it would fail for negatives because -7 % 2 is -1, not 1. Safer parity test: if (n % 2 != 0).
L5.3 — do-while as a "run exactly once" block
Recall Solution
The condition is the constant 0 → false. But a do-while runs the body once before testing, so tries becomes 1, then while(0) stops.
Answer: 1
This do { ... } while(0) is a classic C idiom for a single-pass block you can break out of (used in macros and cleanup chains) — it guarantees exactly one execution while still allowing early break.
L5.4 — the empty for-body counting subtlety
Recall Solution
The trap: the ; right after the for(...) makes the loop body empty — the loop just runs its update until the condition fails. It increments i from 0 while i < 5. When does it stop? At the moment i becomes 5, the test 5 < 5 is false, so it stops with i == 5.
Answer: 5
The loop "did nothing" five times, but its side effect left i one past the last valid index.
Recall pass
Recall One-line self-tests
A switch lands on a matching case and does what without break? ::: Falls through into every following case's code until a break or the block end.
do { } while(0) runs the body how many times? ::: Exactly once (body runs before the false test).
In C99, -7 % 2 equals? ::: -1 (the remainder takes the sign of the dividend).
Sum of 1..100? ::: 5050.
for (i=0; i<5; i++); leaves i equal to? ::: 5.
Why does a lone break fail to exit nested loops? ::: It exits only the innermost loop; the outer loop continues.