Hunter Liu's Website

7. Week 4 Tuesday: Practise with If Statements

≪ 6. Week 3 Thursday: Review and Practise | Table of Contents | 8. Week 4 Thursday: While Loops and For Loops ≫

Our very first example of control flow is the if statement. This allows us to tell C++ to run certain lines of code and avoid running other lines of code, perhaps depending on the user’s input or on the status of our computer.

The general syntax is as follows:

1if( [condition] ) {
2    // code 
3}

The [condition] is an expression that is true or false, and the code within the curly braces runs if the condition is true. Typically, it will be a comparison of numbers, such as x <= 15, y > 0, etc. More on conditional expressions below!

You can add an else block at the end:

1if( [condition] ) {
2    // code 
3} else {
4    // more code 
5}

This time, if the condition is true, the first block of code will run; otherwise, the second block will run. Finally, you can chain multiple conditions together:

1if( [condition 1] ) {
2    // code block 1 
3} else if( [condition 2] ) {
4    // code block 2
5} else if( [condition 3] ) {
6    // code block 3 
7} // etc. 

It will go through the conditions in order, one by one, until it finds a true statement. Then, it will run the corresponding code block before exiting. Here is an example:

 1int x = 73; 
 2if(x >= 90) {
 3    cout << "You got an A" << endl; 
 4} else if(x >= 80) {
 5    cout << "You got a B" << endl; 
 6} else if(x >= 70) {
 7    cout << "You got a C" << endl; 
 8} else if(x >= 60) {
 9    cout << "You got a D" << endl; 
10} else {
11    cout << "See me after class." << endl; 
12}

This snippet of code will output You got a C. It will check the condition x >= 90, which is false. Then, it checks x >= 80, which is also false. It finally checks x >= 70, which is true, and so it runs the following code block. It then skips the rest of the else if/else blocks!

There are several things to remark:

1int x = 50; 
2if(x < 0) 
3    cout << "I love "; 
4    cout << "pie" << endl; 

Conditionals

We have to put conditionals inside the if statements, and these will generally take the form of comparisons between numbers. You can compare integers, chars, and doubles with each other. If a and b are numbers, you can perform the following comparisons:

These should hopefully be self-explanatory.

Sometimes, however, we may have more than one condition that we want to be true, or several conditions of which we want at least one to be true. If p and q are two boolean expressions (i.e., true or false, such as the comparisons above), you can combine them in the following two ways:

Of course, one can string together any number of conditions using a mix of && and ||; however, you should be careful with the order in which they are combined together. This StackOverflow answer provides a great explanation; in short, && is evaluated first in absence of parentheses.

Problem 1. Soggy Sandwiches

What is the output of the following code?

 1#include <iostream>
 2
 3using namespace std;
 4
 5int main() {
 6    int a = 15;
 7    double b = 4.6;
 8    double c = -9.7;
 9    int d = 100;
10    double e = 2.718;
11    double f = 4.178e18;    // scientific notation - 4.178 * 10^18
12
13    if(a == 10 || b > 3 && c < 0 || d * e < f && f < 0 && e > 0) {
14        cout << "I love C++ so much, I want to marry C++." << endl;
15    } else {
16        cout << "C++ is as pleasant as a soggy sandwich." << endl;
17    }
18
19    return 0;
20}
Solution

This amounts to checking what the condition on line 13 is, i.e. if it’s true or false. We can work out the individual conditions without any problem: a == 10 is false, b > 3 is true, c < 0 is true, d * e < f is false, f < 0 is false, and e > 0 is true. So, the expression becomes:

false || true && true || false && false && true

Remember that && is always computed before || (unless parentheses are present). true && true is true, while false && false && true is false. Thus, this becomes false || true || false Since at least one of these is true, the full expression is true. Thus, the code on line 14 will be run, and the output will be I love C++ so much, I want to marry C++.

Problem 2. Evenly Spaced

Write a program that asks the user for three integers, then prints “Evenly spaced” if the three numbers are evenly spaced, and “Unevenly spaced” otherwise. For instance, the numbers 2, 4, and 6 are evenly spaced, regardless of which order they are input, but 7, 10, and 14 are not.

Let’s analyse this particular problem together. A naïve but entirely plausible solution in pseudocode may look as follows:

  1. Let the user enter three integers, \(a\), \(b\), and \(c\).
  2. If \(b-a=c-b\), the numbers are evenly spaced.
  3. Otherwise, the numbers are not evenly spaced.

This works perfectly well when the numbers are in increasing or decreasing order — we’re checking if the differences between consecutive numbers are the same.

However, this algorithm falls apart entirely when the three numbers are out of order: the user inputting 4 2 6 would cause a = 4, b = 2, c = 6 to be read in, and b - a = -2 while c - b = 4.

One immediate way to remedy this is to first put the numbers in order, then perform the above algorithm. In pseudocode,

  1. Let the user enter three integers, \(a\), \(b\), and \(c\).
  2. By swapping the contents of \(a\), \(b\), and/or \(c\) as necessary, put the three numbers in ascending or descending order.
  3. If \(b-a=c-b\), the numbers are evenly spaced.
  4. Otherwise, they are not evenly spaced.

Try to implement these steps algorithmically before peeking at the solution!

Solution

This is not the only way to solve this problem; there are may different ways to place numbers in increasing or decreasing order. We will handle this by breaking up all the possible scenarios into distinct cases.

Suppose the user has entered the integers \(a, b, c\); our job is to place them in either ascending or descending order.

  1. If \(a \leq b \leq c\), we have nothing to do.
  2. If \(c \leq b \leq a\), we also have nothing to do.
  3. If \(a \leq c < b\), we should swap \(b\) and \(c\).
  4. If \(c \leq a < b\), we should swap \(a\) and \(b\).
  5. If \(b < a \leq c\), we should swap \(a\) and \(b\).
  6. If \(b < c \leq a\), we should swap \(b\) and \(c\).

The above analysis represents every possible ordering of the three inputs; we are describing how to handle each case.

We could write four if/else-if branches for scenarios 3-6, but this would result in some redundancies: the actions we need to perform for cases 4 and 5 are the same. Thus, we may write this in another way, grouping by the actions we are performing rather than the scenario:

  • We should swap \(a\) and \(b\) when…
    • \(b < a \leq c\) (case 5)
    • \(b > a \geq c\) (case 4)
  • We should swap \(b\) and \(c\) when…
    • \(b < c \leq a\) (case 6)
    • \(b > c \geq a\) (case 3)

Converting this into actual code yields:

 1#include <iostream> 
 2
 3using namespace std; 
 4
 5int main() {
 6    // 1. read user input into 3 integers, a, b, and c 
 7    int a, b, c; 
 8    cout << "Please enter 3 integers: "; 
 9    cin >> a >> b >> c; 
10
11    // 2. rearrange the three integers so they're "in order". 
12    // cases 4 and 5, swapping a and b
13    if((b < a && a >= c) || (b > a && a >= c)) { 
14        int temp = b; 
15        b = a; 
16        a = temp; 
17    } 
18
19    // cases 3 and 6, swapping b and c
20    else if((b < c && c <= a) || (b > c && c >= a)) {
21        int temp = b; 
22        b = c; 
23        c = temp; 
24    } 
25
26    // 3. if b - a and c - b are equal, we are evenly spaced 
27    if( b - a == c - b ) {
28        cout << "Evenly spaced" << endl; 
29    } 
30
31    // 4. otherwise, they aren't evenly spaced. 
32    else {
33        cout << "Unevenly spaced" << endl; 
34    } 
35
36    return 0; 
37} 
Challenge
There is a solution to this problem that does not involve rearranging the user’s three inputs. Can you think of a way to do this?

Problem 3. Quadratic Formula

Write a C++ program that asks the user for three real numbers \(a, b, c\), then prints out the real solutions to the equation \(ax^2+bx+c=0\). Recall that the quadratic formula is \(x=\frac{-b\pm\sqrt{b^2-4ac}}{2a}\).

Sample runs:
INPUT    1 -1 -1         (x^2 - x - 1 = 0)
OUTPUT   Solutions: 1.61803, -0.618034

INPUT    1 2 1           (x^2 + 2x + 1 = 0)
OUTPUT   Solution: -1

Student Solution:

 1#include <iostream>
 2#include <cmath>
 3
 4using namespace std;
 5
 6int main() {
 7    double a, b, c, d;
 8    cin >> a >> b >> c;
 9    d = sqrt(b * b - 4 * a * c);
10
11    cout << "Solutions: "
12         << (-1 * b + d) / (2 * a)
13         << ", " << (-1 * b - d) / (2 * a) << endl;
14
15    return 0;
16}

Your job is threefold:

  1. Explain, in pseudocode, how the solution above works. Add comments to make the code readable.
  2. Give two examples of user inputs that cause the program to fail in two different ways.
  3. Modify the solution so that it works in all cases.