Lesson 1 — The Decision Statement

← Module home · Lesson 2 — Conditions →

In this lesson you will learn

Everything here builds on the decision-making ideas from Problem Solving, Lesson §8; today we write them in C++.


1. A program that chooses

So far your programs have been highways: every statement runs, top to bottom, every time. A decision statement builds a fork in the road:

              ┌──────────────┐
              │  condition?  │      the question — always true or false
              └──────┬───────┘
              true   │   false
          ┌──────────┴──────────┐
          ▼                     ▼
   ┌─────────────┐       ┌─────────────┐
   │  branch A   │       │  branch B   │   exactly one runs
   └──────┬──────┘       └──────┬──────┘
          └──────────┬──────────┘
                     ▼
              code continues here          both roads rejoin

The question is a condition — an expression whose value is true or false (Lesson 2 covers building them). In C++, the fork is written with if / else.

2. if — do this if, otherwise skip

if (condition)
{
    statements;   // runs only when condition is true
}
// execution always continues here

Example — exam eligibility:

#include <iostream>
int main() {
    int marks;
    std::cout << "Enter marks (0-100): ";
    std::cin >> marks;

    if (marks >= 40)                       // condition: question about marks
    {
        std::cout << "You passed.\n";      // body: runs only for 40..100
    }

    std::cout << "Done.\n";                // NOT in the body: always runs
    return 0;
}

Practice: before running, predict the output for marks = 40. (The boundary — Lesson 2 §5 — says >= includes it.)

3. if-else — one of exactly two roads

if (condition)
{
    // A: runs when condition is true
}
else
{
    // B: runs when condition is false
}

Exactly one branch runs — never both, never neither. That guarantee is the whole point of else: it makes “the other case” explicit instead of leaving it to luck.

Example — even or odd (the % remainder trick):

if (number % 2 == 0)
{
    std::cout << "even\n";     // remainder 0 when dividing by 2
}
else
{
    std::cout << "odd\n";      // remainder 1 — any other case
}

The == (double equals) compares; the single = assigns. Writing if (number = 2) is one of the two classic mistakes — Lesson 2 §7 and D1 hunt it.

4. Dry-run a decision before you trust it

Take this tiny program and fill the table by hand — no compiler:

std::cin >> marks;
if (marks >= 40) { std::cout << "PASS\n"; }
else             { std::cout << "FAIL\n"; }
std::cout << "checked\n";
marks marks >= 40 branch taken output lines
95 true if PASS, checked
40      
39      
0      

Fill every row yourself; the the row for 40 is the one people get wrong (it’s true — >= includes 40; see boundary conditions). Checking both sides of a boundary like this is the cheapest test you will ever write.

5. else-if — a ladder of questions

When there are more than two outcomes, chain questions into a ladder. C++ runs it top to bottom and takes the first condition that is true; everything after is skipped — even if their conditions would also be true:

if (marks >= 80)
{
    grade = 'A';               // tried first
}
else if (marks >= 70)
{
    grade = 'B';               // reached only when marks < 80
}
else if (marks >= 60)
{
    grade = 'C';
}
else if (marks >= 40)
{
    grade = 'D';
}
else
{
    grade = 'F';               // every question above answered false
}

Two properties make ladders work:

Why order matters: flip the ladder (>= 40 first) and every passing mark grabs 'D' and leaves — the later questions never get a chance. Rule: from most specific/most demanding to least, or make every condition self-contained.

Gap discipline: a ladder should partition its inputs — every value falls in exactly one branch. Check your ladder with the boundary values of each band: 79, 80, 69, 70, … plus one value below the lowest band. P4 walks exactly this.

6. Nested decisions — a question inside an answer

Any branch may contain further decisions — a question you only need to ask after the first is answered:

if (age >= 18)                        // outer gate: adult?
{
    if (hasId)                        // inner question: only worth asking for adults
    {
        std::cout << "Entry allowed\n";
    }
    else
    {
        std::cout << "Adult, but bring ID\n";
    }
}
else
{
    std::cout << "Entry denied: under 18\n";
}

The inner if runs only when the outer condition is true. Structure matters more than syntax here:

Rewrite check: the same rule can also be expressed as if (age >= 18 && hasId) / else if (age >= 18) / else. All correct — pick the shape that mirrors how the requirement phrases it.

7. Braces: the silent killer

The braces are optional for a single statement — and that “feature” is a trap:

if (marks >= 40)
    std::cout << "PASS\n";
    std::cout << "Well done!\n";      // NOT guarded! always prints

The if owns only the one statement after it. The second line is unconditional. It compiles, it runs, it lies. House rule for this course: always use braces, even for one-line bodies. The compiler won’t save you here; only the habit will. Hunt D2 for the full crime scene.

Related C++ fact, so it doesn’t surprise you later: a stray semicolon gives an if an empty body — if (cond); { ... } — and the block then runs unconditionally. D3 hunts one.

# Mistake Symptom Fix
M1 = instead of == in the condition condition is the assigned value; with if (x = 0) the body never runs compare with ==; compile with -Wall so gcc warns
M2 unbraced second statement “inside” the if second line always runs brace every body
M3 ladder bands unordered high marks get low grades; some values fall through most-demanding-first, or self-contained ranges
M4 missing final else some inputs leave the outcome unset end with a catch-all, or prove every case is covered
M5 else dangling to the wrong if after nesting inner else swallows the outer case indent, brace, and dry-run both sides
M6 ; after if (…) body runs always (or never) no semicolon before the block

Every one of these appears as a full debugging hunt with hints — but try each hunt before this table spoils it.


Recap — you can now

Next: Lesson 2 — Conditions and boundaries: building the questions themselves — comparison, logical, compound, and the > vs >= trap that decides pass/fail.