Control Flow II: Loops & Range-based for

লুপ ও range-based for

Read: ~30 min 15 practice problems

1. Three Classical Loop Forms

loops.cpp
#include <iostream>

int main() {
    // while: test before
    int i = 0;
    while (i < 3) { std::cout << "w" << i++; }
    std::cout << "\n";

    // do-while: test after (always runs once)
    int j = 0;
    do { std::cout << "d" << j++; } while (j < 3);
    std::cout << "\n";

    // for: combines init/condition/update
    for (int k = 0; k < 3; ++k) std::cout << "f" << k;
    std::cout << "\n";
}

2. Range-based for (C++11) — The Modern Way

The cleanest way to iterate over any container or array:

range_for.cpp
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {10, 20, 30, 40};

    // Read-only iteration
    for (const auto& x : v) std::cout << x << " ";
    std::cout << "\n";

    // Modify in place
    for (auto& x : v) x *= 2;

    for (int x : v) std::cout << x << " ";
    std::cout << "\n";
}
FormBehaviorWhen to use
for (auto x : v)Copy each elementSmall types (int, char)
for (const auto& x : v)Read-only referenceRead-only — default choice
for (auto& x : v)Mutable referenceModify in place

3. break, continue, and (rarely) goto

  • break — exit the innermost loop or switch.
  • continue — skip to the next iteration.
  • goto — almost never. The one valid use: jumping out of nested loops.

4. Loop Invariants — Proof of Correctness

An invariant is a statement that's true before and after each iteration. It proves the loop is correct.

Example: sum 1..n
int sum = 0;
for (int i = 1; i <= n; ++i) sum += i;
Invariant: Before iteration i, sum = 1 + 2 + ... + (i-1).
Initial: Before i=1, sum = 0 (empty sum). ✓
Maintain: If invariant holds before i, after sum += i it holds for i+1. ✓
Termination: Loop ends at i=n+1, so sum = 1+...+n. ✓

5. Nested Loops & Time Complexity

nested.cpp
#include <iostream>

int main() {
    for (int i = 1; i <= 5; ++i) {
        for (int j = 1; j <= i; ++j) {
            std::cout << "*";
        }
        std::cout << "\n";
    }
}

Two nested loops over n elements = O(n²) work. Triple nested = O(n³).

6. Practice Problems

  1. Print 1 to 100.
    ✨ Show Answer
    for (int i = 1; i <= 100; ++i) std::cout << i << " ";
  2. Compute n! for n=10 using a for loop.
    ✨ Show Answer
    fact.cpp
    #include <iostream>
    int main() {
        long long f = 1;
        for (int i = 2; i <= 10; ++i) f *= i;
        std::cout << f << "\n";
    }
  3. Sum of even numbers 1..100.
    ✨ Show Answer
    int s = 0;
    for (int i = 2; i <= 100; i += 2) s += i; // 2550
  4. Print a multiplication table for 7.
    ✨ Show Answer
    for (int i = 1; i <= 10; ++i)
        std::cout << 7 << " x " << i << " = " << 7*i << "\n";
  5. Use range-for to compute the sum of {1,2,3,4,5}.
    ✨ Show Answer
    std::vector<int> v = {1,2,3,4,5};
    int s = 0;
    for (int x : v) s += x;
  6. Print stars in a right triangle of height 5.
    ✨ Show Answer

    See section 5 above. Output:
    *
    **
    ***
    ****
    *****

  7. Find the largest divisor of 100 less than 100.
    ✨ Show Answer
    for (int d = 99; d >= 1; --d)
        if (100 % d == 0) { std::cout << d; break; } // 50
  8. Print all primes below 30.
    ✨ Show Answer
    primes.cpp
    #include <iostream>
    int main() {
        for (int n = 2; n < 30; ++n) {
            bool isp = true;
            for (int d = 2; d * d <= n; ++d)
                if (n % d == 0) { isp = false; break; }
            if (isp) std::cout << n << " ";
        }
    }
  9. Difference between ++i and i++?
    ✨ Show Answer

    Both increment i. ++i returns the new value; i++ returns the old. For loops, prefer ++i — it can be faster for non-trivial types (no temp copy). For ints, identical.

  10. Reverse a string with a loop.
    ✨ Show Answer
    std::string s = "hello";
    for (int i = 0, j = s.size()-1; i < j; ++i, --j) std::swap(s[i], s[j]);
  11. Use continue to skip multiples of 3 when printing 1..20.
    ✨ Show Answer
    for (int i = 1; i <= 20; ++i) {
        if (i % 3 == 0) continue;
        std::cout << i << " ";
    }
  12. Why prefer const auto& in range-for over auto?
    ✨ Show Answer

    Avoids unnecessary copy of each element. Plus the compiler enforces that you don't accidentally modify it. Default to const auto&; switch to auto& only when you intend to modify.

  13. Print Fibonacci numbers up to F(15) iteratively.
    ✨ Show Answer
    int a = 0, b = 1;
    for (int i = 0; i < 15; ++i) {
        std::cout << a << " ";
        int next = a + b; a = b; b = next;
    }
  14. When would you use do-while instead of while?
    ✨ Show Answer

    When you need the loop body to run at least once before the test. Common: menu-driven programs.

  15. Loop invariant for binary-counting bits in n: int c=0; while(n){ c+= n&1; n>>=1;}
    ✨ Show Answer

    Invariant: c = number of 1-bits processed so far. After the loop, n=0 (all bits processed) and c = total bit count.

Summary

while tests first, do-while tests last, for bundles init/cond/update. Range-based for is the modern default for any container. Use const auto& unless you need to modify. State your loop invariant — it is the proof of correctness.

Next Module → Functions: Overloading, Default Args, Inline.