Video Coming Soon...
17: Classic for-loops
You are now going to learn about using for-loops in C++ to process lists of items. You should have the documentation for vector
open while you do this exercise for reference.
Problems With while-loops
The while-loop
has a problem because you can get it wrong very easily. You can forget the initializer, forget to increment, or maybe you make the incrementer too complex. You can also get the test wrong. Because of this it's difficult to reason about when a while-loop
will end. This becomes even more of a problem when the while-loop
gets more complicated over time.
Classic for-loop
as Solution
To solve the problems with while-loops
there's three general solutions:
- The topic of this exercise which I'm calling "classic
for-loops
" that take the elements necessary for awhile-loop
and make them obvious and explicit. - The topic of the next exercise called "range
for-loops
" where you allow thevector
to control the looping, effectively ensuring it will always end. - A future topic called "functional programming" to run code over your data and/or tell your data to run functions for you.
The Code
This code is exactly the same as the previous code but it uses a for-loop
instead of a while-loop
to iterate through the age
vector:
View Source file ex17a.cpp Only
#include <fmt/core.h>
#include <vector>
using namespace fmt;
using std::vector;
int main() {
vector<int> ages = {10,34,25,19,87,5};
println("I have {} cousins of different ages:", ages.size());
for(size_t i = 0; i < ages.size(); i++) {
int cousin_age = ages.at(i);
println("cousin #{} is {} years old.", i, cousin_age);
}
}
Code Walkthrough
I'll skip the usual starting code you have to write, as it's similar to the previous exercise and will only focus on the part with the for-loop
. You should open both ex16.cpp
and this ex17a.cpp
file to compare them side-by-side:
- 12
- This starts the
for-loop
and consists of three parts separated by;
(semi-colon) characters. First is the initializer which issize_t i = 0
; then there's the test which isi < ages.size()
; and finally the incrementer which isi++
. This matches my comments fromex16.cpp
for thewhile-loop
but all on one line. - 13
- This line gets a cousin's age from
ages
usingages.at(i)
just like in thewhile-loop
version. - 14
- Then just print it out like normal using
println()
.
The way to think about a for-loop
's initialization is it's like three lines of code every while-loop
needs smashed onto a single line with ;
characters. You can actually do this with any C++ code. Imagine I want to create an integer, add a number to it, and print it:
int i = 0;
i += 10;
println("i={}", i);
I could simply put all those on one line like this:
int i = 0; i += 10; println("i={}", i);
That's because C++ doesn't care as long as you have ;
separating things. That's effectively what a for-loop
does. It just takes those three lines you'd normally have to write for a while-loop
and pulls them up to the top on one line (separated by ;
).
Challenge Mode
Here's another example that's more complicated and shows a ffew more features of both for-loops
and vector
:
View Source file ex17.cpp Only
#include <fmt/core.h>
#include <vector>
using std::string, std::vector;
using namespace fmt;
int main() {
vector<string> fruit = {
"Apple", "Orange", "Pear",
"Grape", "Durian", "Mango"
};
// loop through fruit
for(size_t i = 0; i < fruit.size(); i++) {
println("Fruit #{} is {}", i, fruit[i]);
}
// another way to get it using at()
for(size_t i = 0; i < fruit.size(); i++) {
println("Fruit #{} is {}", i, fruit.at(i));
}
// set them all to something else
vector<string> guitars = {
"Stratocaster", "Telecaster", "Bass VI",
"P-Bass", "ASAT Special", "G&L S500"
};
for(size_t i = 0; i < guitars.size(); i++) {
println("Changing fruit #{} to guitar {}", i, guitars[i]);
fruit[i] = guitars[i];
}
for(size_t i = 0; i < fruit.size(); i++) {
println("Fruit...I mean Guitar #{} is {}", i, fruit.at(i));
}
}
As usual do not blast all this code in one session the try to fix it. Get this working a little bit at a time, compiling and running constantly as you work.
Once you get this working I then want you to take everything you know about vector
and use for-loops
to work with them. You can start with the documentation for vector
and study each operation possible. Try to get as many to work as you possibly can with what you know, and any take notes on any that you don't understand.
WARNING: Remember that challenge sections like this are meant to push your understanding, not to make you feel like a failure. You can't fail these because I'm not grading you and I don't care how well you do. You won't impress me or disappoint me. Your only goal is to learn what you can and come back when you learn more.
Breaking It
Breaking classic for-loops
is harder but not impossible:
- If you're using
i
as an iterator then try changing it inside thefor-loop
so that the loop never ends. - We're using
size_t
which is a large number that isunsigned long int
on most platforms. If you take a0
number of this type and subtract one it will "underflow" and become the largest number possible on your computer. See if you can do this on accident so your loops don't end. - A simpler one is to not use
vector::size()
as inages.size()
to set the ending of the loop. This happens if you use a variable in one place for the size, but then give thevector
a different number of items.
Further Study
Look at other data structures you can use. Try some of these:
Again, try to use them but don't worry if they don't make sense yet. In the great words of a Jedi Master:
"There is only try, no fail." -- Gandalf
I think that's what he said. It's been a while since I've seen Fight Club.
Register for Learn C++ the Hard Way
Register to gain access to additional videos which demonstrate each exercise. Videos are priced to cover the cost of hosting.