CodeRigor

LESSON

Make decisions with if and else

Compare values, read true/false conditions, choose between blocks of code with if, else if and else, and combine conditions with &&, || and !.

Every program so far ran the same statements in the same order, whatever the user typed. A program becomes useful when it can do different things in different situations: let an adult in and turn a child away, or say whether a guess was too high. That takes a way to ask a question and a way to act on the answer.

Conditions are true or false

A condition is a question whose answer is either true or false. You write one by comparing two values with a comparison operator:

Operator Meaning Example Answer
== is equal to 7 == 7 true
!= is not equal to 7 != 7 false
< is less than 3 < 5 true
> is greater than 3 > 5 false
<= is less than or equal to 5 <= 5 true
>= is greater than or equal to 4 >= 5 false

"Is equal to" is written with two equals signs. A single = stores a value in a variable, as you saw in lesson 2. Mixing the two up is the most common mistake in this lesson, and it is covered at the end.

The answers true and false are values with a type of their own, bool. A bool variable holds either true or false.

C++
#include <iostream>

int main() {
    int age = 15;
    bool is_adult = age >= 18;
    std::cout << is_adult << '\n';
    std::cout << (age < 16) << '\n';
}

This prints 0 and then 1. std::cout shows false as 0 and true as 1. When you send a comparison straight to std::cout, put it in round brackets as on line 7, so that the comparison is worked out before << sends it.

Comparing also works for strings: name == "Ada" is true when name holds exactly that text, with the same capital letters.

if runs a block only when its condition is true

An if statement has a condition in round brackets, then a pair of braces. The statements between the braces are called a block. The block runs when the condition is true and is skipped when it is false.

C++
#include <iostream>

int main() {
    int age = 20;
    if (age >= 18) {
        std::cout << "You may vote.\n";
    }
    std::cout << "Thank you.\n";
}

This prints You may vote. and then Thank you.. Change 20 to 15 and run it again: only Thank you. is printed, because the block is skipped. The last statement is after the closing brace of the block, so it runs either way.

The statements inside the block are indented four more spaces. As before, the compiler does not need the indenting, but it shows the reader which statements depend on the condition.

else gives the other path

Add else and a second block to say what should happen when the condition is false. Exactly one of the two blocks runs.

C++
#include <iostream>

int main() {
    int age = 15;
    if (age >= 18) {
        std::cout << "You may vote.\n";
    } else {
        std::cout << "You are too young to vote.\n";
    }
}

This prints You are too young to vote..

else if chooses between several paths

else if adds another condition, which is checked only when the ones above it were false. You can have as many else if parts as you need, and an optional else at the end for "none of the above".

C++
#include <iostream>

int main() {
    int age = 9;
    if (age < 5) {
        std::cout << "Free\n";
    } else if (age < 16) {
        std::cout << "Child ticket\n";
    } else {
        std::cout << "Adult ticket\n";
    }
    std::cout << "Enjoy your visit.\n";
}

This prints Child ticket and then Enjoy your visit.. Step through the diagram to see which lines run and which are skipped.

Following one value through if, else if and else
start / 5 ⇄ code
With age holding 9 the first condition is false, the second is true, and its block runs. The rest of the chain is skipped and the program carries on below it.
Following one value through if, else if and else
With age holding 9 the first condition is false, the second is true, and its block runs. The rest of the chain is skipped and the program carries on below it.

The conditions are checked from the top, and the block of the first one that is true runs. At most one block in a chain runs, so the order of the conditions matters. A nine-year-old is also "less than 100", but a condition age < 100 written below age < 16 would never be reached for them.

A chain picks exactly one path
start / 4
Each condition is asked only if every condition above it was false. else catches everything that is left.
A chain picks exactly one path
Each condition is asked only if every condition above it was false. else catches everything that is left.

Combining conditions

Three operators build a bigger condition out of smaller ones:

  • && means and. a && b is true when both sides are true.
  • || means or. a || b is true when at least one side is true.
  • ! means not. !a is true when a is false.
C++
#include <iostream>

int main() {
    int age = 30;
    bool has_ticket = false;

    if (age >= 18 && has_ticket) {
        std::cout << "Come in.\n";
    } else {
        std::cout << "Sorry, not today.\n";
    }

    if (age < 5 || age >= 65) {
        std::cout << "Free travel\n";
    }

    if (!has_ticket) {
        std::cout << "Tickets are sold at the desk.\n";
    }
}

This prints Sorry, not today. and then Tickets are sold at the desk.. The first condition needs both parts to be true, and has_ticket is false. The second needs at least one part to be true, and a 30-year-old is neither under 5 nor 65 or over, so nothing is printed. The third is true because has_ticket is false.

To ask whether a value lies between two limits, compare it twice and join the comparisons with &&: age >= 13 && age <= 19.

Three mistakes the compiler helps with

One = where you meant ==. This program is meant to greet only 18-year-olds:

C++
#include <iostream>

int main() {
    int age = 20;
    if (age = 18) {
        std::cout << "Exactly eighteen\n";
    }
}

It compiles, runs and prints Exactly eighteen, although age was 20. The single = stores 18 in age, and C++ then treats the stored number as the condition: any number other than 0 counts as true. The compiler suspects a mistake and says so:

Text
main.cpp: In function 'int main()':
main.cpp:5:13: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
    5 |     if (age = 18) {
      |         ~~~~^~~~

This is a warning, not an error. A warning means "this is allowed, but it is probably not what you meant", and the program is still compiled. Read warnings as carefully as errors: "assignment used as truth value" is the compiler's way of saying that an = is being used where a true-or-false answer is expected. ("Parentheses" is another word for round brackets; ignore that suggestion.) The fix is if (age == 18).

A semicolon that cuts an if from its else.

C++
#include <iostream>

int main() {
    int age = 20;
    if (age >= 18) {
        std::cout << "Adult\n";
    };
    else {
        std::cout << "Child\n";
    }
}
Text
main.cpp: In function 'int main()':
main.cpp:8:5: error: 'else' without a previous 'if'
    8 |     else {
      |     ^~~~

The message points at line 8, but the cause is at the end of line 7. A semicolon after the closing brace ends the whole if statement, so the else that follows has nothing to belong to. Blocks do not take a semicolon after their closing brace. When the marked line looks correct, look at the line above it.

Two comparisons written as in maths. To test for a teenager it is tempting to write 13 <= age <= 19:

C++
#include <iostream>

int main() {
    int age = 30;
    if (13 <= age <= 19) {
        std::cout << "Teenager\n";
    }
}

This compiles and prints Teenager for a 30-year-old. C++ works out 13 <= age first, which gives true, and then compares that answer, counted as the number 1, with 19. The compiler warns:

Text
main.cpp: In function 'int main()':
main.cpp:5:19: warning: comparison of constant '19' with boolean expression is always true [-Wbool-compare]
    5 |     if (13 <= age <= 19) {
      |         ~~~~~~~~~~^~~~~
main.cpp:5:12: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
    5 |     if (13 <= age <= 19) {
      |         ~~~^~~~~~

The second warning says it plainly. (In the first one, "boolean" is the adjective for true-or-false values; it is where bool gets its name.) Write two comparisons joined with &&: if (age >= 13 && age <= 19).

What you can do now

You can compare values, store a true-or-false answer, run a block only when a condition holds, choose between several paths with a chain, and combine conditions. In the exercises you will predict which path small programs take, then write a program that decides who may go on a ride.

Next: repeat steps with loops, so that a program can do something many times without you writing it many times.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →