Video Coming Soon...
14: while-loops
You now know everything you need to understand the rest of programming, and in this exercise I'm going to prove it to you. Do you remember this code from Exercise 12?
View Source file ex12a.cpp Only
#include <fmt/core.h>
using namespace fmt;
int main() {
println("I will run.");
goto skipped;
println("I will NOT run.");
skipped:
println("I will also run.");
return 0;
}
This means you know how to jump to another part of your code using goto
. In that exercise you also learned about the if-statement
which uses variables to make decisions by secretly using jumps combined with boolean tests.
Do you remember how to set a variable and increment it? Just in case, here's how you do that:
int count = 1;
++count;
You also know how to print that number to the screen with print()
or println()
. Remember that? Hopefully you do since you've been doing it constantly this whole time.
Let's see if you can figure out the topic of this exercise on your own. Don't cheat. Try to use what you know so far to do this:
Print the number 0 through 19 using only one
println()
orprint()
call.
You know how to goto
, increment a variable, print it, and check if that variable is less than 20. You just have to put them together.
I'll show you my solution to this at the end of the exercise so you have a chance to solve it on your own. If you get stuck glance at my solution briefly but try not to so you get practice solving problems on your own.
How to Write Code
If you attempted this and couldn't figure it out that's probably because you don't have experience writing code. It's difficult to go from idea to working software, so I'll teach you a beginner process that I actually still use to this day when I'm stuck.
- Create your starter file. It should be the usual empty but working
ex14a.cpp
file with aint main()
and yourfmt
includes. Also make sure it's in yourmeson.build
so you can build. - Next you want to a comment in English (or your language) that explain what you want the code to do. Just describe it in your own words or copy what I wrote.
- You'll then translate this large paragraph description into a series of comments that explain each step of what you want the code to do.
- Once you have the comments steps, you'll fill in the code under them and try to compile as often as possible. Compiling as you go will help catch errors right away rather than at the end when they're more difficult to find.
I'll show you what I would write for step #2 and #3, but leave #4 for you to do:
#include <fmt/core.h>
int main() {
// Print the number 0 through 19 using only one `println()` or `print()` call.
// start at 0
// print the number
// increment it
// if it's < 19 goto the start
// done
}
See how I wrote out what I want you to do first? Then I studied that and wrote out what I think the steps are to do that. After that I can "fill in the blanks" to get this to work.
You then place the code you need to make these comments work under each one like this:
// start at 0
int x = 0;
After you do that, run your build, confirm it's working, and do the next line until you're done.
How Do I Know What To Do
This is really only something that comes from experience. At first you'll probably describe the solution in weird ways that don't make sense in C++ because you aren't proficient in programming yet. As you keep trying to create code using this process you'll get better and better at writing good descriptions to follow. Eventually you won't even need the descriptions and can write the code directly. I still do this process when I'm a little lost or don't know the problem though, so don't consider it to be a "beginners only" process.
The do-while
Loop
Depending on how you approached your solution you either implemented something called a do-while
(most likely) or a while-loop
. Since you probably implemented a do-while
loop let's explore that first. Start a new file named ex14b.cpp
and get this code to work:
View Source file ex14b.cpp Only
#include <iostream>
#include <fmt/core.h>
using namespace std;
using namespace fmt;
int main() {
int x = 0; // initializer
do { // start of loop
println("X={}", x); // code
++x; // incrementer
} while(x < 20); // test
return 0;
}
A do-while
most likely works the way your goto
loop does, but it's much easier to read and understand. I'll break down only the code inside the main()
function since you should know what everything else does by now:
8
- Initializer is where you create the variable that controls the loop, initialized to a starting value.
10
- Start of loop is where your loop begins with the
do
followed by a{
(left-curly). 11
- Code is where you place the code you want repeated.
12
- Incrementer is where you increase (or decrease) the variable controlling the loop
x
. 13
- Test this is where you write a boolean test that determines if the loop should exit or not. You end the block of code with
}
(right-curly), then you use thewhile(TEST)
statement. TheTEST
in thewhile(TEST)
is just like anif(TEST)
except when it'strue
the loop will continue running. The way a while loop "continues running" is to jump back up to thedo {
part and repeat the code part.
Hopefully you can map what you wrote (or look at the end of the exercise for my solution) and see how it's similar.
The while-loop
I started with a do-while
because it's most likely similar to what you wrote for a loop, but the while-loop
is the more common looping construct. I think a do-while
shows up in my code 5% of the time depending on the language. The while-loop
is like the do-while
but with the while(TEST)
first and no do
keyword:
View Source file ex14c.cpp Only
#include <iostream>
#include <fmt/core.h>
using namespace std;
using namespace fmt;
int main() {
int x = 0; // initializer
while(x < 20) { // test & start
println("X={}", x); // code
++x; // incrementer
} // end
return 0;
}
You probably can figure this out, but just in case let me break it down for you:
8
- Initializer once again, initialize the variable you'll use to control the loop.
10
- Test and start comes first now, and works exactly like the
do-while
version. Since it's first, if thex < 20
isfalse
the loop will jump ahead to line13
instead of backwards. 11
- Code is where you write the code for the loop.
12
- Incrementer you then increment the control variable before the loop body ends.
13
:- End is where the loop will jump when the
while(x < 10)
becomes false. You end the loop with a}
(right-curly) that matches the{
(left-curly) on line 10.
Breaking It
Breaking these loops is trivially easy. Here's a few suggestions:
- The problem with
do-while
andwhile-loops
is that you can't easily tell they will end. If you get thewhile(TEST)
wrong it might not end, so try to do that first. - Next, remove the
++x
incrementer to see how that also breaks it. Another one is to get the incrementer math wrong. A common mistake people make is to do complex incrementers likex+=3
without thinking if that might not end the loop. - Another one that's very possible is forgetting the
{}
loop body syntax. If you delete these two characters from thewhile-loop
version and you'll see it runs forever. Why? Because you technically wrotewhile(x < 20) println("X={}", x);
which doesn't reach the incrementer++x
. Really study this one because it actually is the cause of many subtle errors in C++ code.
WARNING: Don't Use goto
for Loops
There's a culture of programmers to hate goto
so much they remove it from assembly languages even in 2024. These programmers are idiots and you should ignore them when they claim that goto
is "considered harmful." These same programmers who cargo cult their opinions on goto
are also the same people who would have no problem utilizing every hack on the planet to get their code to work, so their opinion on goto
is very hypocritical.
If they ever bother you, tell them to go bother Brian Kernigan, Rob Pike, and Dennis Ritchie for creating the Go programming langauge which features fairly heavy use of goto
and even uses goto
in the standard library.
That being said, goto
is a maintenance nightmare so you shouldn't use it until you are more skilled. I'm using it here as a teaching device so you understand the concept of a jump in your code and how that relates to C++ structures like do-while
, while-loops
, and if-statements
. Once you learn about these structures you should never use goto
to replace them.
Where goto
does become handy is in error handling in some languages (see Go for example), but later we'll learn how C++ deals with the problem of aborting an operation early using something called "Exceptions." For now, use goto
only in my course and only to learn how better alternatives to goto
work. It's also fine while you're learning to use goto
to get something to work, then translate it until you don't need goto
anymore.
Further Study
- If you wrote a
goto
style loop that worked likedo-while
then implement one that works like awhile-loop
. For those of you who did awhile-loop
with yourgoto
then implement ado-while
style. - See if you can use
goto
to break out of a loop early. - There's actually a keyword for this that you already know from
switch-statements
. Rememberbreak
? You can put abreak
in a while loop to exit early. Read about it on cppreference.com for more. - ADVANCED Consider this very advanced, but if you can figure it out you'll learn a lot. How would you print each character of your name to the string using only one
println()
call and awhile-loop
?
My Solution
Here's my solution to the "DIY while-loop" challenge at the beginning:
View Source file ex14a.cpp Only
#include <iostream>
#include <fmt/core.h>
using namespace std;
using namespace fmt;
int main() {
int x = 0; // initializer
start_loop: // start of loop
println("X={}", x); // code
++x; // incrementer
if(x < 20) goto start_loop; // test
return 0;
}
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.