class: center, middle # CMPE 30: Lecture 5 Decisions and `while` --- # What does this print? .lc[ ```cpp int a = 10; int b = a++; int c = ++a; std::cout << a << " " << b << " " << c << "\n"; ``` ] .rc[ 1. `10 10 11` 1. `11 10 11` 1. `12 10 12` 1. `12 11 12` 1. Ben got this wrong ] --- # Learning Objectives - Write `if`, `if/else`, `if/else if/else` chains - Avoid the `=` vs `==` trap - Trace a nested `if` and flatten it with guard clauses - Scope a tested variable with `if` with initializer - Write a `while` loop that terminates - Use `while` for input validation loops --- # if Statements .lc[ ```cpp int score = 85; if (score >= 90) { std::cout << "Excelente!\n"; } ``` ] .rc[ - Condition is converted to a boolean --- nonzero counts as true - True --> body runs; false --> body is skipped - **Always** use `{}` --- saves you from the dangling-if trap ] --- # else and else if .lc[ ```cpp if (score >= 90) { std::cout << "A\n"; } else if (score >= 80) { std::cout << "B\n"; } else if (score >= 70) { std::cout << "C\n"; } else { std::cout << "Try again\n"; } ``` ] .rc[ - Tested **top to bottom** - First match wins; the rest are skipped - Final `else` catches anything that did not match **Trap:** `if (x = 5)` **assigns** 5, does not compare. ] --- # Nested if .lc[ ```cpp if (age >= 18) { if (has_ticket) { std::cout << "Welcome\n"; } else { std::cout << "Ticket?\n"; } } else { std::cout << "18+\n"; } ``` ] .rc[ - Legal, but deep nesting is hard to read - Flatten by combining with `&&` / `||` - Or with guard clauses --- next slide ] --- # Guard Clauses --- the Problem .lc[ ```cpp if (age >= 18) { if (has_ticket) { if (seats_left > 0) { std::cout << "Welcome\n"; return true; } else { std::cout << "Sold out\n"; return false; } } else { std::cout << "Ticket?\n"; return false; } } else { std::cout << "18+ only\n"; return false; } ``` ] .rc[ - Success case buried four levels deep - Each failure message far from the condition that rejected it - Tracing = counting open braces ] --- # Guard Clauses --- the Fix .lc[ ```cpp if (age < 18) { std::cout << "18+ only\n"; return false; } if (!has_ticket) { std::cout << "Ticket?\n"; return false; } if (seats_left <= 0) { std::cout << "Sold out\n"; return false; } std::cout << "Welcome\n"; return true; ``` ] .rc[ - **Guard clause** = early `return` that rejects a bad case immediately - Failure sits right next to its condition - Happy path unindented at the bottom - Functions are chapter 6 --- read `return` as "stop here" ] --- # if with Initializer (C++17) .lc[ ```cpp // before: rank outlives the if int rank = find_rank("Black Hole Sun"); if (rank > 0) { std::cout << "found at " << rank << "\n"; } // after: rank scoped to the if if (int rank = find_rank("Black Hole Sun"); rank > 0) { std::cout << "found at " << rank << "\n"; } ``` ] .rc[ - Before the `;`: init, runs once - After the `;`: the actual condition - `rank` lives only inside the `if` (and its `else`) ] --- # if with Initializer --- npos .lc[ ```cpp if (auto pos = name.find("99"); pos != std::string::npos) { std::cout << "the 90s start at " << pos << "\n"; } else { std::cout << "no 99\n"; } ``` ] .rc[ - Shines when a call returns "did it work?" plus a value - `pos` is visible in both branches - Gone when the statement ends **Tip:** Use this form when the tested value only matters *inside* the `if`. ] --- # while Loops .lc[ ```cpp int countdown = 5; while (countdown > 0) { std::cout << countdown << "... "; countdown--; } std::cout << "Vamos!\n"; ``` ] .rc[ - Condition tested **before** each iteration - If false from the start, the body **never** runs - Make sure the loop variable changes **Trap:** Forgetting to update the loop variable gives an infinite loop. Ctrl+C is your friend. ] --- # Input Validation .lc[ ```cpp int n; std::cout << "Positive number: "; std::cin >> n; while (n <= 0) { std::cout << "Try again: "; std::cin >> n; } ``` ] .rc[ - Classic pattern: ask, test, ask again - `do-while` will make this cleaner next lecture ] --- # Try It --- Guessing Game .lc[ ```cpp int target = 42, guess; std::cin >> guess; while (guess != target) { if (guess < target) std::cout << "Higher! "; else std::cout << "Lower! "; std::cin >> guess; } std::cout << "Got it!\n"; ``` ] .rc[ - One-word changes can make the loop infinite - Non-numeric input is a preview of chapter 9 - Ask the class: what is the smallest bug? ] --- # What does this print? .lc[ ```cpp int x = 5; if (x = 10) { std::cout << "A "; } std::cout << x << "\n"; ``` ] .rc[ 1. `A 5` 1. `A 10` 1. `5` 1. `10` 1. Ben got this wrong ] --- # How many times does this run? .lc[ ```cpp int i = 10; while (i > 10) { std::cout << "hi\n"; i++; } ``` ] .rc[ 1. 0 1. 1 1. 10 1. infinite 1. Ben got this wrong ] --- # Key Points - `if` / `else if` / `else` chains are top-to-bottom, first match wins - Guard clauses reject bad cases early; happy path stays unindented - `if (init; cond)` scopes the tested variable to the `if`/`else` - `while` tests the condition **before** each iteration - Make sure the loop variable changes - `==` compares, `=` assigns **Read:** chapter 5 of *Gorgo Starting C++*, `do-while`, `for`, `switch`, and `break`/`continue`. **Do:** exercises 2, 3, 4, 6, 8.