Notifications

No notifications

/Phase 1

Control Flow — if, switch, loops

Decisions & Loops 🔀

Control flow lets your program choose and repeat. C++ inherits all of C's control-flow keywords and adds two modern conveniences: range-based for and if with init.

if / else

int score = 73;
if (score >= 90)        cout << "A";
else if (score >= 75)   cout << "B";
else if (score >= 60)   cout << "C";
else                    cout << "F";

Modern: if With Init (C++17)

if (auto it = m.find(key); it != m.end()) {
    cout << it->second;          // it lives only in this if/else
}

switch

switch (grade) {
    case 'A': cout << "Excellent"; break;
    case 'B':
    case 'C': cout << "OK";        break;   // fall-through
    default:  cout << "Try again"; break;
}

> ⚠️ Don't forget break! Without it, execution falls through to the next case (sometimes intentional, often a bug).

Loops

for (int i = 0; i < 5; i++)        cout << i;     // classic
while (n > 0)                      n /= 2;        // condition first
do { cout << "once"; } while (false);              // runs at least once

Range-Based for (C++11+)

vector<int> nums = {1, 2, 3};
for (int x : nums)        cout << x;       // copy each element
for (int& x : nums)       x *= 2;          // modify in place
for (const int& x : nums) cout << x;       // read-only, no copy

Jump Statements

KeywordEffect
breakExit the innermost loop / switch
continueSkip to next iteration
returnExit the current function
goto(Avoid in modern C++)

On this page

Detailed Theory

Every algorithm boils down to choose and repeat. C++ gives you a full toolkit and modern C++ keeps adding small, sharp upgrades.

Boolean Conditions

Conditions are anything convertible to bool. Numbers: 0 = false, anything else = true. Pointers: nullptr = false.

if (count)        cout << "non-zero";
if (!ptr)         cout << "null";
if (s.empty())    cout << "empty string";

Logical Operators

OpMeaningShort-circuits?
&&ANDyes — stops on first false
\\ORyes — stops on first true
!NOT

if (p != nullptr && p->valid())   // safe — if p is null, p->valid() never runs

Comparison

== != < <= > >= — and <=> (C++20 *spaceship operator*) for three-way comparisons.

> ⚠️ = vs ==if (x = 5) assigns 5 to x and is always true. Most compilers warn about this. Always == in conditions.

if, else, else if

if (cond) {
    // ...
} else if (other) {
    // ...
} else {
    // ...
}

Use braces { } even for one-line bodies — saves you from the famous "Apple goto-fail" bug:

if (cond)
    doA();
    doB();      // ALWAYS runs — not what you might have meant

if With Init (C++17)

Limit a variable's scope to the if:

if (auto it = map.find(key); it != map.end()) {
    use(it->second);
}                        // 'it' destroyed here

C++20 added the same for switch and for.

Conditional Operator

int abs = (x < 0) ? -x : x;

Great for short choices. Don't nest more than one level — readability dies fast.

switch

For exact-value matches on integers, enums, or characters.

switch (cmd) {
    case 'q': quit(); break;
    case 'h':
    case '?': showHelp(); break;       // intentional fall-through
    default:  cout << "unknown"; break;
}

Fall-Through

By default, control flows from one matching case into the next until a break. C++17 lets you mark intentional fall-through:

switch (x) {
    case 1:
        a();
        [[fallthrough]];   // tells the compiler "yes, on purpose"
    case 2:
        b();
        break;
}

Classic for Loop

for (init; condition; step) {
    // body
}

for (int i = 0; i < n; ++i) cout << i;
for (int i = n - 1; i >= 0; --i) cout << i;     // backwards
for (int i = 0, j = n - 1; i < j; ++i, --j) ;   // two cursors

++i is conventional in C++. For ints it's identical to i++, but for iterators ++i is sometimes faster (no temporary).

while & do…while

while (n > 1) {
    if (n % 2 == 0) n /= 2;
    else            n = 3*n + 1;     // Collatz!
}

do { cout << "Try again> "; cin >> guess; } while (guess != answer);

Use while when you might do zero iterations; do…while when you need at least one.

Range-Based for (C++11)

The cleanest way to iterate over containers, arrays, strings, anything with begin()/end().

vector<int> v = {1, 2, 3};
for (int x : v) cout << x;            // copy each element

for (int& x : v) x += 10; // modify in place

for (const auto& s : names) cout << s; // big elements: const ref to avoid copies

Pattern: auto& to modify, const auto& to read.

Loop Control: break & continue

for (int x : nums) {
    if (x < 0) continue;       // skip negatives
    if (x == 0) break;          // stop at first zero
    cout << x << ' ';
}

Breaking Out of Nested Loops

C++ has no labelled break. Common idioms:

bool done = false;
for (int i = 0; i < n && !done; ++i)
    for (int j = 0; j < n; ++j)
        if (grid[i][j] == target) { done = true; break; }

Or just put it in a function and use return. Cleaner.

goto?

C++ has goto. Don't use it for normal flow. The one defensible use is jumping to a single cleanup label in deeply nested C-style code — and even then, RAII is better.

Common Bugs

BugCause
Off-by-one (<= instead of <)Loop runs one extra time
Forgot break in switchUnintended fall-through
if (x = 5)Assignment instead of comparison
Modifying a container while iteratingIterator invalidation

Cheat-Sheet

NeedIdiom
Pick one of manyif/else if/else
Match exact valueswitch
Run N timesfor (int i = 0; i < N; ++i)
Until conditionwhile (cond)
At least oncedo { ... } while (cond);
Iterate containerfor (const auto& x : v)
Modify in placefor (auto& x : v)
Skip iterationcontinue
Stop loopbreak
Exit functionreturn

Master these and you can express any algorithm. The next phase introduces functions — a way to package the control flow you write here.