5. Booleans & Conditionals¶
What & why¶
Programs make decisions: if this, do that. That requires expressions that evaluate to true or false, and statements that branch on them.
Comparison operators¶
They produce a bool. std::string compares alphabetically (lexicographically):
Printing a
boolwithstd::coutshows1or0. Usestd::cout << std::boolalpha;once to gettrue/false.
Logical operators: &&, ||, !¶
&&—trueonly if both sides are true||—trueif either side is true!— flips the value
(and, or, not are valid alternative spellings, but rarely used.)
Short-circuiting¶
&& and || stop as soon as the answer is known. That makes guards safe:
if (!name.empty() && name[0] == 'A') { ... } // name[0] only runs if not empty
if (ptr != nullptr && ptr->ready) { ... } // no null dereference
No chained comparisons¶
This compiles, but it is wrong:
Write both halves:
if / else if / else¶
int temp = 22;
if (temp < 0) {
std::cout << "freezing\n";
} else if (temp < 15) {
std::cout << "cold\n";
} else if (temp < 25) {
std::cout << "comfortable\n";
} else {
std::cout << "hot\n";
}
- The condition goes in parentheses.
- Only the first matching branch runs.
- Braces are optional for a single statement — always use them anyway. Missing braces cause real bugs:
if (logged_in)
load_profile();
show_dashboard(); // ALWAYS runs — indentation means nothing to the compiler
Truthiness¶
Numbers and pointers convert to bool: zero/null is false, anything else is true.
int count = 0;
if (count) { ... } // false
std::string s;
if (s) { ... } // compile ERROR: std::string doesn't convert to bool
if (!s.empty()) { ... } // correct
Be explicit when it helps: if (count != 0) reads better than if (count) for numbers.
if with an initializer (C++17)¶
Limit a variable's scope to the if:
if (auto pos = text.find(':'); pos != std::string::npos) {
std::cout << "key: " << text.substr(0, pos) << '\n';
}
// pos doesn't exist here
Guard clauses¶
Return early to avoid deep nesting:
std::string process(int quantity, double price) {
if (quantity <= 0) {
return "invalid quantity";
}
if (price < 0) {
return "invalid price";
}
// main logic here, not indented 3 levels deep
return "processed";
}
The conditional (ternary) operator¶
Use it for simple value selection, not for side effects.
switch¶
For comparing one integer-like value (int, char, enum) against constants:
char op = '+';
int a = 6, b = 3;
switch (op) {
case '+':
std::cout << a + b << '\n';
break;
case '-':
std::cout << a - b << '\n';
break;
case '*':
case 'x': // two labels, same code
std::cout << a * b << '\n';
break;
default:
std::cout << "unknown operator\n";
}
- Forget
breakand execution "falls through" into the next case. If you mean it, mark it with[[fallthrough]];. switchdoesn't work onstd::string. Useif/else iffor strings.- Declaring a variable inside a case needs its own braces:
case 1: { int x = 5; ... break; }.
Common mistakes¶
=instead of==:if (x = 5)assigns 5 and is always true.-Wallwarns you — read warnings!0 <= x <= 100— compiles, always true. Use&&.- Missing braces on multi-line bodies.
- Missing
breakin aswitch. if (a || b == c)meansa || (b == c). You probably wanta == c || b == c.- A stray semicolon:
if (ok); { ... }— the;is the entire if-body; the block always runs. - Comparing doubles with
==(see lesson 3).
Exercises¶
- Read a year and print whether it's a leap year. (Divisible by 4, except centuries, unless divisible by 400.)
- Read a numeric grade 0–100 and print a letter: A (≥90), B (≥80), C (≥70), D (≥60), F otherwise. Reject values outside 0–100.
- Hardcode a username and password, read both from the user, and print "Access granted" only if both match.
- Read three side lengths and print whether they form a triangle, and if so whether it's equilateral, isosceles, or scalene.
- Rewrite with guard clauses:
- Build a tiny calculator: read
number op number(e.g.3 + 4) withstd::cin >> a >> op >> band use aswitchonop. Handle division by zero.
Recap¶
- Comparisons and
&&/||/!producebool;&&and||short-circuit. - No chained comparisons —
0 <= x && x <= 100. if/else if/else— always use braces.if (init; cond)keeps helper variables scoped.cond ? a : bfor simple choices;switchfor integer/char/enum constants — don't forgetbreak.
Next: Loops →