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:
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:
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:
- Note where the semicolons are. None of the curly braces are followed by semicolons, and the conditions inside the if statements don’t get semicolons!
- Else blocks are not mandatory. You can have a single if statement or an if statement followed by a few else-if’s without an else statement at the end.
- Curly braces are not mandatory. This will cause the if statement to run the first statement (i.e., up to the first semicolon) only. It is strongly recommended that you use curly braces all the time, but unfortunately programmers can be lazy and omit them. For instance, the output of the following code is
pie
; can you see why?
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:
- Greater than (or equal to):
a > b
,a >= b
. - Less than (or eqaul to):
a < b
,a <= b
. - Equal to:
a == b
. There are two equal signs, not one. This is becausea = b
looks like you’re saying “overwrite the value ofa
with the value ofb
”. This is a very common source of error. - Not equal to:
a != b
.
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:
- And:
p && q
, bothp
andq
must be true. - Or:
p || q
, eitherp
orq
must be true.
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:
- Let the user enter three integers, \(a\), \(b\), and \(c\).
- If \(b-a=c-b\), the numbers are evenly spaced.
- 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,
- Let the user enter three integers, \(a\), \(b\), and \(c\).
- By swapping the contents of \(a\), \(b\), and/or \(c\) as necessary, put the three numbers in ascending or descending order.
- If \(b-a=c-b\), the numbers are evenly spaced.
- 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.
- If \(a \leq b \leq c\), we have nothing to do.
- If \(c \leq b \leq a\), we also have nothing to do.
- If \(a \leq c < b\), we should swap \(b\) and \(c\).
- If \(c \leq a < b\), we should swap \(a\) and \(b\).
- If \(b < a \leq c\), we should swap \(a\) and \(b\).
- 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
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:
- Explain, in pseudocode, how the solution above works. Add comments to make the code readable.
- Give two examples of user inputs that cause the program to fail in two different ways.
- Modify the solution so that it works in all cases.