Loops
-
A loop is a very powerful programming construct that is used when we want to do something multiple times.
-
There are three kinds of loops in C++:
-
For loops
-
While loops
-
Do while loops
Do while loops are just like while loops, except that checking the condition happens after the execution of the block of code inside the loop’s body. They are used less often than while loops and for loops, so we don’t require you to know do while loops in EECS 183.
-
While loops
-
While loops are of this form:
int i = 0; (1) while (i < 10) (2) { (3) cout << "hi" << endl; i++; (4) }
1 Initialization of the variable used to control the loop’s execution. 2 Condition that has to be true for the loop to continue executing. If the condition is fall, the body of the does not execute. 3 The body of the loop is marked by curly braces ( {}
). After the body, the condition will be again checked.4 The update of the loop variable usually takes place at the end of the body. The above example prints
hi
followed by a new line ten times. -
Let’s do a more complicated example.
Write a program that asks the user for a positive integer and keeps asking until the user cooperates. The program should behave per the sample output below, wherein red underlined text represents some user’s input:
Please give me a positive integer: 0 Try again: -42 Try again: 183 Thanks for the 183!
Solution:
positive-0.cpp#include <iostream> using namespace std; int main(int argc, const char * argv[]) { cout << "Please give me a positive integer: "; int n; cin >> n; (1) while (n < 1) (2) { cout << "Try again: "; cin >> n; (3) } cout << "Thanks for the " << n << "!" << endl; }
1 Read an integer into n
.2 Do the following so long as n
is less than1
…3 Read another integer into n
. This is the update of the loop.
For loops
-
Now let’s look at for loops. They’re similar in structure to while loops: they also have an initialization, a condition, a body and an update. However, for loops group the initialization, the condition and the update on one line.
-
This loop again prints
hi
followed by a new line ten times.for (int i = 0; i < 10; i++) (1) (2) (4) { (3) cout << "hi" << endl; }
1 First, int i = 0
initializes the variablei
that controls the loop.2 Then, the condition i < 10
is checked. It is checked each time before the body of the loop executes.3 Curly braces ( {}
) mark the start and the end of the body of the loop, which executes on each iteration.4 i++
is the update of the loop that executes each time after the body and before the condition.
For vs. While
-
What’s the difference between for loops and while loops?
-
Not much difference! In fact, you can always rewrite a for loop as a while loop and vice-versa. Let’s take a look at the earlier example again:
int i = 0; (1) while (i < 10) (2) { (3) cout << "hi" << endl; i++; (4) }
for (int i = 0; i < 10; i++) (1) (2) (4) { (3) cout << "hi" << endl; }
1 Initialization (outside of the while loop and inside the for loop). 2 Condition (always checked after the body executes). 3 The body of the loop is marked by curly braces ( {}
).4 Update (inside the body of the while loop and outside of the body of the for loop). -
The major difference between the while loop and the for loop above is that
i
is declared outside the while loop, but inside the for loop. This means thati
will still be in scope after the while loop. However,i
cannot be used after the for loop.
-
-
When should you use for loops and when should you use while loops?
-
It’s up to you! After getting comfortable with loops, you’ll most likely have a preference for one or the other.
-
In general, use while loops for event-controlled loops (i.e. if you want a block of code to execute so long as something hasn’t happened).
-
And use for loops when you want a block of code to be executed n number of times.
-
More Examples
-
Let’s write a program that counts down from 5 to 1. We can use either a while loop or a for loop. Here, I’m using a for loop.
Solution:
countdown.cpp#include <iostream> using namespace std; int main() { for (int i = 5; i > 0; i--) { cout << i << endl; } cout << "BLAST OFF!!!" << endl; }
And here’s the output of this program:
5 4 3 2 1 BLAST OFF!!!
-
This program tries to print 10 stars, but fails to do so correctly. Can you find the bug?
buggy-2.cpp#include <iostream> using namespace std; int main() { for (int i = 0; i <= 10; i++) { cout << '*'; } }
The problem is that this program prints 11 stars, not 10. This is because
i
starts at0
. After the body executes for the first time,i
is incremented and i 1. After the body executes ten times,i
is10
. The conditioni ⇐ 10
is still true and the body executes for the eleventh time. Theni
is incremented again and becomes11
, after while the conditioni ⇐ 10
is false and the loop stops.To fix the bug, change the condition from
i ⇐ 10
toi < 10
. -
And another example of a buggy program. It tries to print print 10 stars, one per line. However, it prints 10 stars on the same line. Can you figure out why?
buggy-3.cpp#include <iostream> using namespace std; int main() { for (int i = 0; i < 10; i++) cout << '*'; cout << endl; }
The problem is that the curly braces are missing and do not surround the body of the loop. And so in this case, only the first statement is considered to be the body of the loop:
cout << '*';
Remember that C++ does not care about whitespace and that indentation is only used for human readability. So even though the line
cout << endl;
is indented, it is not considered to be part of the loop’s body, since it’s not inside curly braces.
-
Loops can also be nested. Can you figure out what the following code prints?
for (int row = 0; row < 3; row++) { for (int col = 0; col < 4; col++) { cout << 'x'; } cout << endl; }
Answer:
xxxx xxxx xxxx
ASCII
-
Recall that everything inside the computer is represented in 0s and 1s (binary). That means that everything, even
char
s andstring
s are represented as integers under the hood. -
ASCII is an encoding system which represents every character with a given number. For example, an uppercase
A
is represented by the number65
and an uppercaseZ
is represented by the number90
. -
Here’s a glimpse of the ASCII table that illustrates the correspondence between characters and numbers that represent them:
-
You should try to memorize all the ASCII values. However, you should know the following:
-
There is an integer corresponding to each character in the ASCII table.
-
Uppercase letters are next to each other in the ASCII table.
-
Lowercase letters are next to each other in the ASCII table.
-
A
has a value of65
anda
has a value of97
, so uppercase letters come before lowercase letters. -
The character
0
does not have an ASCII value of0
. In other words, the character0
is not represented with the number0
.
-
-
Let’s now write a program that prints all the English letters in the alphabet (first, uppercase A–Z, and then lowercase a–z), along with their ASCII values. The program should print something like this:
A: 65 B: 66 C: 67 ... a: 97 b: 98 c: 99 ...
-
Here’s one way to do it:
ascii-0.cppint main() { // mapping for uppercase letters for (int i = 65; i < 65 + 26; i++) (1) { cout << (char) i << ": " << i << endl; (2) } cout << endl; // mapping for lowercase letters for (int i = 97; i < 97 + 26; i++) (3) { cout << (char) i << ": " << i << endl; } }
1 We start the first loop at 65 (the ASCII value of A
) and execute the loop 26 times (once per letter), so long asi
is less than 98. (97 is the ASCII value ofZ
).2 Inside the body of the first loop, we print the ASCII value after printing the corresponding character that we get by casting the integer with the ASCII value to a char
.3 Similarly, we have a for loop for lowercase letters that starts at 97 (the ASCII value of a
) and executes 26 times.However,
ascii-0.cpp
has a lot of magic numbers (65, 26, 97). And to implement it correctly, you’d have to remember, for example, thata
corresponds to 97. -
It turns out that we can also cast from
char
s toint
s, so let’s write a second version of that program, where we avoid magic numbers:ascii-1.cpp#include <iostream> using namespace std; int main() { // mapping for uppercase letters for (char c = 'A'; c <= 'Z'; c++) (1) { cout << c << ": " << (int) c << endl; (2) } cout << endl; // mapping for lowercase letters for (char c = 'a'; c <= 'z'; c++) (3) { cout << c << ": " << (int) c << endl; } }
1 We iterate over char
s, starting atA
up untilZ
. We can also incrementc
on each iteration, and we’ll get the next character in the ASCII table.2 Each time, we print the character, and then its ASCII value that we get by casting the char
to anint
.3 Similarly we iterate over char
s froma
toz
.Notice how now in
ascii-1.cpp
, we don’t have to now the exact values ofA
,Z
,a
orz
-
Being able to represent characters with numbers gives us the ability to manipulate them, which opens lots of possibilities (e.g. capitalizing strings). More on this in a week or so!
Battleship
-
Write a program that prints this Battleship board using loops. Take care to ensure that all spaces match this example:
1 2 3 4 5 6 7 8 9 10 A o o o o o o o o o o B o o o o o o o o o o C o o o o o o o o o o D o o o o o o o o o o E o o o o o o o o o o F o o o o o o o o o o G o o o o o o o o o o H o o o o o o o o o o I o o o o o o o o o o J o o o o o o o o o o
-
Since it’s a lot easier to print top to bottom, we’ll print the board row by row.
So first, let’s print the top row of numbers. All we need is a single for loop that prints numbers 1 through 10 separated by spaces:
for (int i = 1; i <= 10; i++) { cout << i << " "; }
Now we need to print ten rows of holes, with letters in the leftmost column. Let’s start by just printing a single row of 10 holes:
for (int i = 0; i < 10; i++) { cout << "o "; }
To print ten such rows, we’ll need to put the above loop inside another loop. And we’ll need to go to a new line after the inner loop executes to separate each row.
for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { cout << "o "; } cout << endl; }
Finally, we need to print the corresponding letter in each row. We can do that by printing the character that we get after adding
i
(a number from 0 to 10, corresponding to the row) to the characterA
when we print each row.// print rows of holes, with letters in leftmost column for (int i = 0; i < 10; i++) { cout << (char) ('A' + i) << " "; // print 10 holes cout << endl; }
Also, let’s define a constant to avoid magic numbers
const int BOARD_SIZE = 10;
And replace
10
withBOARD_SIZE
. -
Here’s the full solution:
battleship.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29#include <iostream> using namespace std; int main() { const int BOARD_SIZE = 10; // print top row of numbers cout << " "; for (int i = 1; i <= BOARD_SIZE; i++) { cout << i << " "; } cout << endl; // print rows of holes, with letters in leftmost column for (int i = 0; i < BOARD_SIZE; i++) { // letter cout << (char) ('A' + i) << " "; // holes for (int j = 0; j < BOARD_SIZE; j++) { cout << "o "; } cout << endl; } }
Project 2
-
Some parts of Project 2 involve working with numbers. You might have to determine if one number is divisible by another, be able to get the first 2 digits or a number and be able to get the last 2 digits of a number.
-
How to determine if
a
is divisible byb
?Remember that the modulo (%) operator gives us the remainder of dividing two numbers. So if
a
is divisible byb
, it must be the case thea % b
is 0. -
How to get the first
n
digits of a number?To get the first digit of 123, divide 123 by 100 (you’ll get 1, since 1.23 will be truncated to 1 during integer division). To get the first two digits of 123, divide 123 by 10.
To get the first digit of 1234, divide 1234 by 1000. To get the first two digits of 1234, divide 1234 by 100. To get the first three digits of 1234, divide 1234 by 1000.
See the pattern?
In general, if
a
is a number ofk
digits, you can get the firstn
digits ofa
if you dividea
by10^(k - n)
. Note that10^(k - n)
is not valid C++ syntax. -
How to get the last
n
digits of a number?To get the last digit of 123, get the remainder after dividing 123 by 10. In other words,
123 % 10
will give you the last digit (3). Similarly, to get the last two digits of 123, do123 % 100
.To get the last digit of 1234, you need
1234 % 10
. To get the last two digits of 1234, do1234 % 100
. To get the last three digits of 1234, do1234 % 1000
.And the pattern continues.
Generally, if
a
is a number ofk
digits, you can get the lastn
digits ofa
if you moda
by10^(k - n)
. Note that10^(k - n)
is not valid C++ syntax.