Video Coming Soon...

Created by Zed A. Shaw Updated 2024-10-28 08:02:26

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() or print() 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.

  1. Create your starter file. It should be the usual empty but working ex14a.cpp file with a int main() and your fmt includes. Also make sure it's in your meson.build so you can build.
  2. 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.
  3. 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.
  4. 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 the while(TEST) statement. The TEST in the while(TEST) is just like an if(TEST) except when it's true the loop will continue running. The way a while loop "continues running" is to jump back up to the do { 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 the x < 20 is false the loop will jump ahead to line 13 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:

  1. The problem with do-while and while-loops is that you can't easily tell they will end. If you get the while(TEST) wrong it might not end, so try to do that first.
  2. 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 like x+=3 without thinking if that might not end the loop.
  3. Another one that's very possible is forgetting the {} loop body syntax. If you delete these two characters from the while-loop version and you'll see it runs forever. Why? Because you technically wrote while(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

  1. If you wrote a goto style loop that worked like do-while then implement one that works like a while-loop. For those of you who did a while-loop with your goto then implement a do-while style.
  2. See if you can use goto to break out of a loop early.
  3. There's actually a keyword for this that you already know from switch-statements. Remember break? You can put a break in a while loop to exit early. Read about it on cppreference.com for more.
  4. 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 a while-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;
}
Previous Lesson Next Lesson

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.