Change Theme
# Control Flow ### Lecture 4: Conditionals Making Decisions in Your Code
## Why Do We Need Conditionals? Programs need to make **decisions** and execute different code based on input or state. **Key Points:** - Execute different paths based on conditions - Make programs interactive and intelligent - Handle different scenarios gracefully
## C++ Conditional Tools **Primary constructs:** - `if` statements - `else if` chains - `else` clauses - `switch` statements **Decision drivers:** - Boolean expressions (`true`/`false`) - In C++: non-zero = `true`, zero = `false`
## Example: Piecewise Function Consider this mathematical function: $$f(x) = \begin{cases} x^2 & \text{if } x < 0 \\\\ \sin(x) & \text{if } 0 \leq x < 2 \\\\ \ln(1+x) & \text{if } x \geq 2 \end{cases}$$ How do we implement this in C++?
## Piecewise Function: Implementation ```cpp #include
#include
int main() { double x; std::cout << "Enter x: "; std::cin >> x; if (x < 0) { std::cout << "f(x) = " << x * x << std::endl; } else if (x < 2) { std::cout << "f(x) = " << sin(x) << std::endl; } else { std::cout << "f(x) = " << log1p(x) << std::endl; } return 0; } ```
## EE Example: Overcurrent Protection **Problem:** Circuit breaker protection system **Physics:** By Ohm's Law, $I = \frac{V}{R}$ **Safety Logic:** - **Trip:** $I > 1.2 \times I_{rated}$ - **Warning:** $I_{rated} < I \leq 1.2 \times I_{rated}$ - **Safe:** $I \leq I_{rated}$
## Overcurrent Protection: Code ```cpp #include
int main() { double V, R, I_rated; std::cout << "Enter voltage (V), resistance (R), rated current: "; std::cin >> V >> R >> I_rated; double I = V / R; // Calculate actual current if (I > 1.2 * I_rated) { std::cout << "TRIP: Overcurrent detected!" << std::endl; } else if (I > I_rated) { std::cout << "WARNING: Above rated current" << std::endl; } else { std::cout << "SAFE: Within operating limits" << std::endl; } return 0; } ```
## Aerospace: Velocity Classification **Problem:** Classify trajectory based on velocity **Physics:** Earth's gravitational influence **Classifications:** - **Sub-orbital:** $v < 7.8 \text{ km/s}$ - **Bound Orbit:** $7.8 \leq v < 11.2 \text{ km/s}$ - **Escape:** $v \geq 11.2 \text{ km/s}$
## Velocity Classification: Code ```cpp #include
int main() { double velocity; // in km/s std::cout << "Enter velocity (km/s): "; std::cin >> velocity; if (velocity < 7.8) { std::cout << "Sub-orbital trajectory" << std::endl; } else if (velocity < 11.2) { std::cout << "Bound orbital trajectory" << std::endl; } else { std::cout << "Escape velocity achieved!" << std::endl; } return 0; } ```
## Civil Engineering: Stress Analysis **Problem:** Material stress safety check **Applied stress** $\sigma$ vs **Allowable stress** $\sigma_{allow}$ **Design Rules:** - **Safe:** $\sigma \leq \sigma_{allow}$ - **Reinforce:** $\sigma_{allow} < \sigma \leq 1.1 \times \sigma_{allow}$ - **Redesign:** $\sigma > 1.1 \times \sigma_{allow}$
## Stress Analysis: Code ```cpp #include
int main() { double sigma, sigma_allow; std::cout << "Enter applied stress and allowable stress: "; std::cin >> sigma >> sigma_allow; if (sigma <= sigma_allow) { std::cout << "SAFE: Stress within limits" << std::endl; } else if (sigma <= 1.1 * sigma_allow) { std::cout << "ACTION: Reinforce element" << std::endl; } else { std::cout << "CRITICAL: Redesign required" << std::endl; } return 0; } ```
## The `switch` Statement **When to use:** - Multiple discrete integer or character values - Cleaner than long `if-else if` chains - Better performance for many conditions **Key feature:** - Tests one variable against many constant values
## Switch Statement: Example ```cpp #include
int main() { int material_code; std::cout << "Enter material code (1-3): "; std::cin >> material_code; switch (material_code) { case 1: std::cout << "Material: Concrete" << std::endl; break; // Don't forget break! case 2: std::cout << "Material: Steel" << std::endl; break; case 3: std::cout << "Material: Timber" << std::endl; break; default: std::cout << "Unknown material code" << std::endl; } return 0; } ```
## Best Practices: Braces & Structure **Always use braces `{}`:** ```cpp // Good practice if (condition) { doSomething(); } // Avoid this (even for single statements) if (condition) doSomething(); ``` **Why?** Prevents errors when adding more statements later.
## Best Practices: Floating-Point Comparison **Problem:** Don't use `==` with floating-point numbers! ```cpp // Wrong way if (a == b) { /* unreliable! */ } // Right way const double EPSILON = 1e-9; if (fabs(a - b) < EPSILON) { // a and b are approximately equal } ``` **Reason:** Floating-point precision errors make exact equality unreliable.
## Best Practices: Short-Circuiting **Logical operators stop early:** ```cpp // Safe pointer checking if (ptr != nullptr && ptr->is_valid()) { // Use ptr safely } // Efficient range checking if (x > 0 && x < max_value && expensive_check(x)) { // expensive_check() only runs if x is in range } ``` **`&&`** stops at first `false` **`||`** stops at first `true`
## Common Pitfall: Assignment vs Comparison **The Classic Mistake:** ```cpp int x = 10; // Wrong: assignment (always true!) if (x = 5) { std::cout << "This always executes!"; } // Right: comparison if (x == 5) { std::cout << "This checks equality"; } ``` **Result:** `x` becomes 5, condition is always true!
## Common Pitfall: Dangling Else **Confusing code:** ```cpp if (condition1) if (condition2) action1(); else // Which if does this belong to? action2(); ``` **Clear code:** ```cpp if (condition1) { if (condition2) { action1(); } } else { action2(); } ```
## Common Pitfall: Missing Break **Dangerous fall-through:** ```cpp switch (grade) { case 'A': std::cout << "Excellent!"; // Missing break - falls through! case 'B': std::cout << "Good job!"; break; case 'C': std::cout << "Average"; break; } ``` **Input 'A' outputs:** "Excellent!Good job!"
## Historical Perspective: Early Days **FORTRAN (1957):** - "Arithmetic IF" statement - Branched to labels based on negative/zero/positive - Example: `IF (X) 10, 20, 30` **Problems:** - Unstructured jumps everywhere - "Spaghetti code" - hard to follow - Difficult to debug and maintain
## Historical Perspective: The Revolution **ALGOL 60 (1960):** - Introduced structured `if-then-else` - Block structure with `begin`/`end` - **Massive leap** for structured programming **Impact:** - Code became more readable - Logic flow was clearer - Foundation for modern programming
## Historical Perspective: C and Beyond **C (1972):** - Inherited `if-else` from ALGOL - Added `switch` with fall-through behavior - Became the template for modern languages **C++17 Additions:** - `if` with initializers: `if (auto v = f(); v.ok())` - `[[fallthrough]]` attribute for explicit fall-through
When you forget `break` in a `switch` statement...
One case triggers a chain reaction through all the others!
## Summary **Key Concepts:** - Conditionals make programs intelligent and interactive - `if-else` for ranges and complex logic - `switch` for discrete values - Boolean expressions drive all decisions **Remember:** - Always use braces `{}` - Use `EPSILON` for floating-point comparisons - Don't forget `break` in switch statements - Watch out for `=` vs `==`
## Questions? **Next time:** Loops and Iteration --- *Practice writing conditionals with the examples from today!*