C++ tutorials  /  Control Statements (if-else, switch) in C++
Chapter 4 · C++

Control Statements (if-else, switch) in C++

Control statements in C++ are constructs that alter the normal sequential flow of a program's execution based on certain conditions. Decision-making control statements — including 'if', 'if-else', 'else-if' ladders, nested 'if' statements, and the 'switch' statement — allow a program to execute different blocks of code depending on whether specified boolean conditions evaluate to true or false.

Imagine you're giving directions: 'If it's raining, take an umbrella; otherwise, wear sunglasses.' That's exactly what an if-else statement does in code — it checks a condition and decides which set of instructions to run. C++ gives you several tools for this: a simple 'if' for one condition, 'if-else' for two paths, an 'else-if' ladder for many possible paths, and 'switch' for cleanly checking one variable against several fixed values, like choosing a day of the week.

An ATM machine uses if-else logic extensively: 'if (enteredPIN == correctPIN)' grants access, otherwise it denies it. An e-commerce site uses an else-if ladder to apply shipping costs: free shipping if the cart total exceeds $50, reduced shipping if it's between $20-$50, and standard shipping otherwise. A traffic light simulation or a menu-driven console application (like a calculator choosing between +, -, *, / based on user input) is a textbook real-world use of the 'switch' statement, since it cleanly handles multiple discrete choices without a long chain of else-if comparisons. Netflix's subscription tier logic (Basic, Standard, Premium) internally relies on similar conditional branching to determine what video quality and features to unlock for a user.

Without control statements, a program would just execute every line from top to bottom with no ability to react differently to different inputs or situations, making it impossible to build anything beyond the most trivial linear scripts. Real-world software — from login systems to games to financial applications — must constantly make decisions based on user input, sensor data, or business rules, and control statements are what give programs this essential decision-making capability, forming the foundation of all algorithmic logic.

  • Simple if Statement: Executes a block of code only if a single condition evaluates to true; if the condition is false, the block is simply skipped and execution continues after it.
  • if-else Statement: Provides two distinct paths of execution — the 'if' block runs when the condition is true, and the 'else' block runs when it's false, ensuring exactly one of the two paths always executes.
  • else-if Ladder: Chains multiple conditions together to check several possibilities in sequence, executing the block for the first condition that evaluates to true and skipping the rest, with an optional final 'else' as a catch-all default.
  • Nested if Statements: An 'if' or 'if-else' statement placed inside another 'if' or 'else' block, used when a decision depends on multiple layered conditions that must be checked in sequence.
  • switch Statement: Compares a single variable or expression against multiple constant integer, character, or enum values using 'case' labels, offering a cleaner alternative to long else-if ladders when checking one variable against many fixed values, with an optional 'default' case and 'break' statements to prevent fall-through.
// if statement if (condition) { // code executes if condition is true } // if-else if (condition) { // true block } else { // false block } // else-if ladder if (condition1) { // block1 } else if (condition2) { // block2 } else { // default block } // switch statement switch (variable) { case value1: // code break; case value2: // code break; default: // code }
A developer is building a simple grading application that must convert a numeric score (0-100) into a letter grade (A, B, C, D, or F) using conditional logic, and also build a basic menu system that lets a user select an operation by entering a number, which requires choosing between an else-if ladder and a switch statement for cleaner, more maintainable code.
Grading System Using else-if Ladder
Converts a numeric score into a letter grade using a chain of else-if conditions checked in sequence.
cpp
#include <iostream> using namespace std; int main() { int score = 82; char grade; if (score >= 90) { grade = 'A'; } else if (score >= 80) { grade = 'B'; } else if (score >= 70) { grade = 'C'; } else if (score >= 60) { grade = 'D'; } else { grade = 'F'; } cout << "Score: " << score << " -> Grade: " << grade << endl; return 0; }
Score: 82 -> Grade: B
The conditions are checked top to bottom in order. Since 82 is not >= 90, the first condition fails and the second is checked: 82 >= 80 is true, so 'grade' is set to 'B' and the rest of the ladder is skipped entirely, even though 82 also satisfies later conditions like >= 70.
Simple Calculator Menu Using switch
Uses a switch statement to select between different arithmetic operations based on a user's menu choice, demonstrating a cleaner alternative to a long else-if chain.
cpp
#include <iostream> using namespace std; int main() { int choice = 2; double a = 10, b = 3, result; switch (choice) { case 1: result = a + b; cout << "Sum: " << result << endl; break; case 2: result = a - b; cout << "Difference: " << result << endl; break; case 3: result = a * b; cout << "Product: " << result << endl; break; default: cout << "Invalid choice!" << endl; } return 0; }
Difference: 7
The 'switch' evaluates 'choice' (2) and jumps directly to the matching 'case 2:' label, computing the subtraction and printing the result. The 'break;' statement is crucial — it stops execution from 'falling through' into 'case 3:' and the following cases after the matched block runs.
  • Forgetting 'break' in switch Statements: Omitting 'break;' after a case causes 'fall-through' — execution continues into the next case block regardless of whether its condition matches, silently executing unintended code. For example, without a break after 'case 1:', both case 1 and case 2's code would run even if only case 1 matched.
  • Using = Instead of == in Conditions: Writing 'if (isValid = true)' instead of 'if (isValid == true)' assigns the value rather than comparing it, and since the assigned value is truthy, the condition always evaluates to true, silently breaking the intended logic without necessarily causing a compiler error.
  • Incorrect else Binding in Nested if Statements (Dangling Else): When nested if statements aren't wrapped in braces, an 'else' automatically binds to the nearest preceding unmatched 'if', which may not be the one the programmer intended, leading to logic that executes under the wrong condition. Always use curly braces '{}' around nested blocks to make the binding explicit and unambiguous.
  • Checking Redundant or Unreachable Conditions in an else-if Ladder: Writing 'if (score >= 90) ... else if (score >= 95)' is a logic error — since scores >= 95 are already caught by the first condition, the second condition can never be reached. Conditions in an else-if ladder must be ordered correctly, typically from most specific/restrictive to least, to avoid dead code.
  • Using switch with Non-Constant or Non-Integral Case Values: C++ switch statements only support constant integral, character, or enumeration expressions in case labels — you cannot use variables, ranges (like 'case 1-5:'), floating-point values, or strings directly as case labels, which trips up beginners coming from languages that support more flexible switch/match constructs.
  • Always Use Braces {} Even for Single-Statement Blocks: Even when an if or else block contains only one line, wrap it in curly braces. This prevents the common bug where a developer later adds a second line intending it to be part of the conditional block, but it accidentally executes unconditionally because it falls outside the unbraced if's scope.
  • Always Include a default Case in switch Statements: Even if you believe all valid cases are covered, add a 'default:' case to handle unexpected values gracefully (e.g., invalid user input), which prevents silent failures and makes debugging easier by catching values that don't match any expected case.
  • Prefer switch Over Long else-if Chains When Comparing One Variable to Many Constants: When checking a single variable against many fixed values, 'switch' is generally more readable and can be more efficient than a long else-if ladder, since compilers can sometimes optimize switch statements into jump tables, giving O(1) branching instead of sequential O(n) condition checks.
  • Order else-if Conditions from Most Specific to Least Specific: When conditions overlap (like score ranges), always order them so the narrowest or most restrictive condition is checked first, ensuring the correct branch is reached and preventing broader conditions from unintentionally catching cases meant for more specific ones.
What is the difference between if-else and switch statements, and when would you choose one over the other?
An if-else ladder can evaluate any boolean expression, including ranges, multiple variables, and complex logical combinations, making it more flexible. A switch statement can only compare a single variable/expression against constant integral, character, or enum values, but it's often more readable and can be more efficient (via jump table optimization) when checking one variable against many discrete fixed values. Use switch for simple, discrete, single-variable comparisons and if-else for range checks or complex multi-variable conditions.
What is 'fall-through' behavior in a switch statement, and when might it be intentionally useful?
Fall-through occurs when a 'case' block lacks a 'break' statement, causing execution to continue into the next case regardless of whether it matches. While usually a bug, it can be intentionally useful when multiple case values should share the same code block, such as 'case 'a': case 'e': case 'i': case 'o': case 'u': isVowel = true; break;' where multiple cases fall through to execute the same shared logic.
What is the 'dangling else' problem in C++, and how do you avoid it?
The dangling else problem occurs when nested if statements without braces create ambiguity about which 'if' an 'else' belongs to; C++ resolves this by always binding 'else' to the nearest, innermost unmatched 'if', which may not match the programmer's intended logic. It's avoided by always using explicit curly braces '{}' around if and else blocks, which removes any ambiguity about which condition the else is paired with.
Can you use strings or floating-point numbers as case labels in a C++ switch statement? Why or why not?
No — C++ switch statements only support case labels that are constant expressions evaluable at compile time and of an integral, character, or enumeration type. Strings and floating-point numbers are not allowed as case labels because switch is implemented internally (often via jump tables) based on exact integral matching, which isn't well-defined for floating-point precision issues or complex string comparison; if string-based branching is needed, an if-else chain with string comparison (like '==' on std::string) must be used instead.
How does the compiler typically optimize a switch statement compared to an equivalent if-else ladder?
For switch statements with a dense range of case values, compilers often generate a jump table — an array of memory addresses indexed directly by the case value — allowing the program to jump straight to the matching code block in constant O(1) time. An equivalent if-else ladder, by contrast, must evaluate each condition sequentially in the worst case, resulting in O(n) time complexity for n conditions, making switch potentially more efficient for large numbers of discrete comparisons, though modern compilers may also optimize sparse switch statements using binary search trees instead.
Write a C++ program that checks if a given year is a leap year using nested if-else logic (a year is a leap year if divisible by 4, but not by 100 unless also divisible by 400).
#include <iostream> using namespace std; int main() { int year = 2024; bool isLeap; if (year % 4 == 0) { if (year % 100 == 0) { if (year % 400 == 0) { isLeap = true; } else { isLeap = false; } } else { isLeap = true; } } else { isLeap = false; } cout << year << (isLeap ? " is a leap year." : " is not a leap year.") << endl; return 0; }
Write a program using a switch statement that takes a number from 1-7 and prints the corresponding day of the week (1 = Monday, 7 = Sunday), including a default case for invalid input.
#include <iostream> using namespace std; int main() { int day = 4; switch (day) { case 1: cout << "Monday"; break; case 2: cout << "Tuesday"; break; case 3: cout << "Wednesday"; break; case 4: cout << "Thursday"; break; case 5: cout << "Friday"; break; case 6: cout << "Saturday"; break; case 7: cout << "Sunday"; break; default: cout << "Invalid day number"; } cout << endl; return 0; }
Predict the output of the following code and explain the bug: int x = 5; switch (x) { case 5: cout << "Five "; case 6: cout << "Six "; break; default: cout << "Other"; }
The output is 'Five Six '. This demonstrates fall-through: since 'case 5:' has no 'break' statement, execution continues into 'case 6:' and prints "Six " as well, before finally hitting the 'break;' inside case 6 and exiting the switch. To fix this bug and print only "Five ", a 'break;' statement should be added immediately after the 'case 5:' block.

Control statements — if, if-else, else-if ladders, nested if, and switch — give C++ programs the ability to make decisions and execute different code paths based on conditions, forming the backbone of all conditional logic in software. Choosing between an else-if ladder and a switch statement depends on whether you're checking a single variable against discrete constant values (switch) or evaluating more complex or ranged conditions (if-else). Avoiding classic pitfalls like missing break statements, the dangling else problem, and confusing '=' with '==' is essential for writing correct, predictable, and maintainable decision-making logic in real-world C++ applications.

© 2026 CompileX. Maintained by Aditya Kumar Sharma.