Skip to main content

Section 7.12 Other Conditional Structures

Although the if/else structure should be your go to tool when you need to make a decision in code, there are some other ways to make decisions. This section covers two of those. Neither one is necessary - you can write any decision logic just using if/else. But there are special situations where these tricks can make code easier to read and write. You should recognize them, and should consider using them if they can make your code easier to read/write, but reaching for them should likely not be your first instinct.

Subsection 7.12.1 Switch Statements

If you need to make a series of decisions, chaining else if blocks can get long and redundant. For example, consider a program that converts integers like 1, 2, and 3 into words like "one", "two", and "three":
if (number == 1) {
    word = "one";
} else if (number == 2) {
    word = "two";
} else if (number == 3) {
    word = "three";
} else {
    word = "unknown";
}
This chain could go on and on, with many other cases for. It feels a little silly to keep writing else if (number == ___). An alternative way to evaluate many possible values of an expression is to use a switch statement:
switch (number) {
case 1:
    word = "one";
    break;
case 2:
    word = "two";
    break;
case 3:
    word = "three";
    break;
default:
    word = "unknown";
    break;
}
The body of a switch statement is organized into one or more case blocks. Each case ends with a break statement, which exits the switch body. The default block is optional and executed only if none of the cases apply.
If there is no break, execution will continue on, ignoring the caseโ€™s it encounters. This is a feature that makes switches particularly useful when multiple cases can be grouped:
// assume dayOfWeek is an int variable with a value from 0 to 6
// with 0 = Sunday, 1 = Monday, ..., 6 = Saturday
switch (dayOfWeek) {
case 1:
case 2:
case 3:
case 4:
case 5:
    cout << "Weekday!";
    break;
case 0:
case 6:
    cout << "Weekend!";
    break;
}
Any of the values 1-5 will match the appropriate case and then โ€œfall throughโ€ the others until the cout is reached. Then the break exits the switch. A similar thing happens for 0 or 6 - they โ€œfall throughโ€ to the line that prints that it is a weekend and then the break exits the switch.
There are some issues with switch statements that make them less useful than they might appear. First: switch statements in C++ can only be used to test integer values. You can not use a double or a string or any other type of data in the test. Second: there is no way to switch on a range. You canโ€™t say case < 4: or case 5-10:.

Insight 7.12.1.

Switch statements are only appropriate if there are a fixed number of discrete values you want to test for.
They will be very useful once we learn about enumerated types, but for now, they arenโ€™t usually going to be the best tool for making decisions.

Subsection 7.12.2 Ternary Conditional Operator

Consider this somewhat silly example that reads in a number of monkeys and then prints out a message. It uses a conditional to pick the right form of monkey (singular or plural):
int numMonkeys;
cin >> numMonkeys;

if (numMonkeys == 1) {
    cout << "You chose " << numMonkeys << " monkey";
} else {
    cout << "You chose " << numMonkeys << " monkeys";
}
It is awkward to write basically the same code twice just so we can change one word. An alternative is to use the ternary conditional operator. This operator is a shorthand way to write a simple if/else statement that produces one of two values.
It is called โ€œternaryโ€ (meaning three) because it has three parts:
It takes the form (TEST ? VALUE1 : VALUE2). First is the test, followed by a question mark. If the test is true, the expression produces VALUE1. If it is false, it produces VALUE2. (The parentheses are not necessary but help to show what is part of ternary operator expression.) Here is the monkeys example rewritten to use it:
int numMonkeys;
cin >> numMonkeys;

cout << "You chose " << numMonkeys 
     << (numMonkeys == 1 ? " monkey" : " monkeys");
It is hard to claim that this is a massive improvement. But it is always nice to avoid repeating code. The ternary operator can sometimes be useful for doing so by making a simple choice between two values in the middle of some other expression. But when used with complex expressions it quickly becomes much less readable and much harder to debug. So if you choose to use it, make sure to avoid doing so in statements are already complex.

Checkpoint 7.12.1.

What is the correct output of the code below?
int main() {
  int num = 2;

  switch (num) {
  case 1:
    cout << 1;
    break;
  case 2:
    cout << 4;
  case 3:
    cout << 9;
    break;
  default:
    cout << "Invalid num! Please try again.";
    break;
  }
}
  • 4
  • Incorrect! Donโ€™t forget about fall through. We will continue to the code in the next case and not stop until we encounter a break statement or the end of the switch block.
  • 49
  • Case 2 doesnโ€™t end with a break statement, so case 3 also runs!
  • 49Invalid num! Please try again.
  • Where do we encounter a break statement?
  • Invalid num! Please try again.
  • Is 2 one of the invalid numbers?
  • Code will not run.
  • There is no reason why the code wouldnโ€™t run.

Checkpoint 7.12.2.

What is the correct output this time?
int main() {
  int num = 1;

  switch (num) {
  case 1:
    cout << 1;
    break;
  case 2:
    cout << 4;
  case 3:
    cout << 9;
  default:
    cout << "Invalid num! Please try again.";
  }
}
  • 1
  • The first statement ends with a break, so only 1 will print!
  • 149
  • Where do we encounter a break statement?
  • 149Invalid num! Please try again.
  • Is 1 one of the valid numbers? Where do we encounter a break statement?
  • Invalid num! Please try again.
  • Is 1 one of the invalid numbers?
  • Code will not run.
  • There is no reason why the code wouldnโ€™t run.

Checkpoint 7.12.3.

And finally, what about this time?
int main() {
  int num = 2;

  switch (num) {
  case 1:
    cout << 1;
    break;
  case 2:
    cout << 4;
  case 3:
    cout << 9;
  default:
    cout << "Invalid num! Please try again.";
  }
}
  • 4
  • Where do we / donโ€™t we encounter a break statement?
  • 49
  • Where do we / donโ€™t we encounter a break statement?
  • 49Invalid num! Please try again.
  • Correct. We fall through into the case for 3 and then into the default case because there is no break statement.
  • Invalid num! Please try again.
  • Is 2 one of the invalid numbers?
  • Code will not run.
  • There is no reason why the code wouldnโ€™t run.
You have attempted of activities on this page.