Loops

Learn how we can use loops to iterate over a block of code, executing it as many times as needed.
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, Unlimited Access
3D art showing a dragon
Ryan McCombe
Ryan McCombe
Updated

So far, the code we have written has been able to create programs that execute a single stream of statements, and then exit.

In this lesson, we will learn about loops. Loops will allow us to repeatedly execute a block of code, until some condition within our program changes.

While Loops

The most basic form of loop is the while loop. It executes a block of code as long as a boolean expression remains true.

The basic structure of a while loop looks like this:

while (someBoolean) DoSomething();

Where we need to have multiple statements executed in our loop, we can wrap them with { and }, like in the following example:

while (someBoolean) {
  DoSomething();
  DoAnotherThing();
}

For example, to write the numbers from 1 to 10 to the console using a while loop, we could do this:

#include <iostream>
using namespace std;

int main(){
  int Number{1};
  while (Number <= 10) {
    cout << Number << ", ";
    ++Number;
  }
}
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,

The syntax of a while loop is very similar to the if statements we have seen in the past. We have the keyword while, a boolean expression inside ( and ), and a statement to execute.

The main difference between an if and a while is that:

  • an if statement will execute once if the provided expression is true
  • a while statement will execute continuously, as long as the provided expression remains true.

Iteration

The phrase iteration is commonly used to describe code that involves loops. For example,

  • "the variable is increased on every iteration"
  • "we iteratively call the Log() function"
  • "we iterate over every object in the collection"

If the condition provided to a while loop is false at the point the while loop attempts to start, the code inside the block is not executed - not even once.

The following code will not log out anything:

while (false) {
  cout << "Can't see me!";
}
Test your Knowledge

Using while Loops

What will be the value of i after running this code?

int i { 0 };
while (i <= 5) {
  ++i;
}

Preview: Application Loops

In most software we use, we’ve probably noted that the program runs continuously until we explicitly tell it to stop by, for example, pressing a button in the UI.

This is possible because the program is effectively just one big loop - usually a while loop.

The outermost loop of a program, that keeps everything running, is sometimes referred to as the application loop or, if our application is specifically a game, the game loop. On every iteration, this loop orchestrates tasks like:

  • Handling any user input that has happened since the previous iteration - including whether the user wants to quit
  • Updating the state of any variables and objects as needed
  • Rendering an update to the screen
int main(){
  bool shouldQuit{false};
  while (!shouldQuit) {
    shouldQuit = getUserInput();
    UpdateState();
    RenderToScreen();
  }
}

We’ll be building our own, real application loops later in the course

Do While Loops

A do while loop is very similar to a while loop, with two key differences. The first is that the syntax is slightly different - the condition comes at the end of the block:

do {
  // Body here
} while (shouldLoop);

To log out the numbers from 1-10 using a do while loop, we could do this:

#include <iostream>
using namespace std;

int main(){
  int Number{1};
  do {
    cout << Number << ", ";
    ++Number;
  } while (Number <= 10);
}

The second difference between a while and a do while is that the code inside the block of a do while loop will always be executed at least once, even if the boolean is initially false.

The following code will log out Hello World! one time.

do {
  cout << "Hello World!" << endl;
} while (false);
Test your Knowledge

Using do while Loops

What will be the value of i after running this code?

int i = 0;
do {
  ++i;
} while (i < 0);

For Loops

The third type of loop, the for loop, is slightly more complicated. The basic structure is:

for (initialize; condition; update) {
  // Code here
}

We have three components inside the ( and ) of the for loop. These are:

  • Initialize - this statement is executed a single time, before our loop starts
  • Condition - this is the boolean expression that indicates if our loop should continue
  • Update - this code is executed at the end of each loop iteration

These three components are separated by a semicolon ;

Let's see an example of how we can use this to log out the numbers from 1 to 10:

#include <iostream>
using namespace std;

int main(){
  for (int Number{1}; Number <= 10; ++Number) {
    cout << Number << ", ";
  }
}
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
Test your Knowledge

Using for Loops

What will be the value of i after running this code?

int Number { 0 };
for (int i { 0 }; i < 10; ++i) {
  Number++;
};

With for loops, all three components inside the ( and ) are optional. We can omit the ones we don't need.

However, we still do need to keep the semicolons, to disambiguate which components we are using.

For example, to omit the 1st and 3rd components, we could do this:

int Number { 1 };
for ( ; Number < 10 ; ) {
  cout << Number << ", ";
  ++Number;
}

The above is rather messy code. We should just use a while loop in that scenario, but it is possible to use a for loop. We can even remove the conditional check:

int Number { 1 };
for ( ; ; ) {
  cout << Number << ", ";
  ++Number;
}

This code will compile, but you may see a problem with it. We're not specifying when the loop should stop, so the loop will never stop.

Infinite Loops

Inevitably, we will make a mistake when writing a loop that causes the loop to never end. For example:

int Number { 1 };
while (Number <= 10) {
  cout << Number << ", ";
  // Oops!  we forgot to increment Number
}

Because the body of our loop does not affect the boolean expression that controls when our loop ends, this loop will not end under normal circumstances.

Number will always be <= 10. This is a fairly common scenario, called an infinite loop.

When we introduce an infinite loop, the remedy is usually just to force our program to close. For programs running in our terminal that are stuck in an infinite loop, we should still be able to close them from the title bar.

If that doesn't work, or we're creating a program that doesn't have the title bar, we can generally force our programs to close from our operating system - eg, ctrl + alt + delete in Windows, or Force Quit on macOS.

Loop Scopes

The blocks created by our loop statements behave like any blocks we've seen, such as those associated with functions and if statements.

They have their scope, inside which we can create variables and call functions.

The same scope rules apply - for example, code within the blocks created by our loop can access variables in parent scopes, as we’ve seen:

int Number { 1 };
while (Number <= 10) {
  // Accessing a parent scope
  cout << Number << ", ";
}

However, if we create a variable within our loop, code outside of the loop will not be able to access it, for the exact same reasons we covered earlier in our lesson on scopes:

#include <iostream>
using namespace std;

int main() {
  while (true) {
    int Number{1};
    //
  }
  cout << Number;
}
error: 'Number': undeclared identifier

Finally, it’s worth acknowledging that every iteration of our loop creates a new block scope.

Every iteration of our previous loop creates a new variable called Hello, in a new block created just for that iteration of the loop.

Any variables that were declared within an iteration’s block are no longer accessible once that iteration completes.

Nesting Conditionals within Loops

Within the block of a loop, we can apply most of the techniques we’ve been doing so far. For example, we can create variables, call functions, and use conditional logic.

For example, to log out the numbers from 1-10, but to treat one number differently, we could nest an if statement inside our loop:

#include <iostream>
using namespace std;

int main(){
  int Number{1};
  while (Number <= 10) {
    if (Number == 5) {
      cout << "Five" << ", ";
    } else { cout << Number << ", "; }
    ++Number;
  }
}
1, 2, 3, 4, Five, 6, 7, 8, 9, 10,

Nesting Loops within Loops

We can also nest loops within loops. For example, the following logs out a 3x3 grid using nested loops:

#include <iostream>
using namespace std;

int main(){
  for (int Row{1}; Row <= 3; ++Row) {
    for (int Col{1}; Col <= 3; ++Col) {
      cout << "Row " << Row << ", "
        << "Col " << Col << " | ";
    }
    cout << '\n';
  }
}
Row 1, Col 1 | Row 1, Col 2 | Row 1, Col 3 |
Row 2, Col 1 | Row 2, Col 2 | Row 2, Col 3 |
Row 3, Col 1 | Row 3, Col 2 | Row 3, Col 3 |

In the above example, we have an outer loop that logs out 3 rows, with a new line - \n - after each one.

Within each iteration of this outer loop, we have an inner loop, which also performs 3 iterations. Each iteration logs out a cell of that row.

The net effect is our outer loop iterates 3 times, each causing 3 iterations of the inner loop.

So, the code within the inner loop is invoked 9 times in total.

In the next lesson, covering the modulus operator, we will see a slightly simpler way of implementing this behavior.

The continue Statement

We can use the continue keyword within the body of a loop to give us more control over its execution. When we call continue, the loop will skip over the remaining code for this iteration, and continue onwards to the next.

If the condition that controls the loop is no longer true, the loop will instead end.

The continue statement is most typically used in a conditional block within our loop.

For example, to log the numbers from 1-10, whilst skipping over 5, we could write this code:

#include <iostream>
using namespace std;

int main(){
  int Number{0};
  while (Number < 10) {
    ++Number;
    if (Number == 5) continue;
    cout << Number << ", ";
  }
}
1, 2, 3, 4, 6, 7, 8, 9, 10,
Test your Knowledge

Using the continue Statement

What will be the value of Number after running this code?

int Number { 0 };
for (int i = 0; i < 10; ++i) {
  if (i == 5) continue;
  Number++;
};

The break Statement

The break keyword can be called within the body of a loop, to exit the loop entirely, and to stop iterating. Similar to how continue was used, break is generally most useful within a conditional in our loop.

For example, to limit a while loop to 100 iterations, regardless of whether the condition is true, we could do this:

#include <iostream>
using namespace std;

int main(){
  int RemainingIterations{100};

  while (true) {
    --RemainingIterations;
    if (RemainingIterations <= 0) break;
  }
}

The break statement gives us an alternative way to control when our loops end. In some situations, using this approach can be an easier way to control program flow than using a boolean expression. We’re free to use whatever approach makes most sense for our specific problem.

Test your Knowledge

Using the break Statement

What will be the value of Number after running this code?

int i { 0 };
while (i >= 0) {
  if (i == 5) break;
  ++i;
};

Returning from Loops

Within a loop, we can also use a return statement to end the execution of the function where our loop is running.

This act also implicitly ends our loop, as if we called break on it.

#include <iostream>
using namespace std;

void Log(){
  for (int i{1}; i < 10; ++i) {
    cout << i << ", ";
    if (i == 5) return;
  }
}

int main(){ Log(); }
1, 2, 3, 4, 5,

Note, however, that there is a subtle difference between return and break

  • break will end the loop
  • return will end both the loop and function

This has implications if our function has further code after the end of the loop. In the following example, our program will never say "Goodbye" - that is effectively unreachable code:

#include <iostream>
using namespace std;

void Log(){
  for (int i{1}; i < 10; ++i) {
    cout << i << ", ";
    if (i == 5) return;
  }
  cout << "Goodbye";
}

int main(){ Log(); }
1, 2, 3, 4, 5,

But replacing the return statement with break will have the desired effect:

#include <iostream>
using namespace std;

void Log(){
  for (int i{1}; i < 10; ++i) {
    cout << i << ", ";
    if (i == 5) break; 
  }
  cout << "Goodbye";
}

int main(){ Log(); }
1, 2, 3, 4, 5, Goodbye

Summary

In this lesson, the key points we should remember are:

  • Loops: Loops allow for repeating a block of code multiple times based on certain conditions.
  • While Loops: The while loop executes as long as its condition remains true
  • Do While Loops: The do while loop executes at least once, regardless of the initial condition.
  • For Loops: The for loop allows us to set initialization, condition, and update components.
  • Infinite Loops: Infinite loops do not end under normal circumstances. They’re usually bugs, often caused by the loop body not affecting the boolean expression that determines when the loop should terminate
  • Loop Scopes: Each iteration of a loop creates a new block scope. Variables defined within a loop are not accessible outside of it.
  • Nesting Conditionals and Loops: We can use conditional statements and other loops within a loop, enhancing the flexibility of each.
  • Control Statements in Loops: We can use continue, break, and return statements within loop bodies to further control the flow of our program

Preview of the Next Lesson: The Modulus Operator

The next lesson will delve into the modulus operator %, a tool often used in conjunction with loops.

  • Integer Division: Understanding the quotient and remainder of integer division
  • Practical Applications: We will explore how the modulus operator can be used to perform operations like determining even or odd numbers, creating patterns, and more.
  • Integration with Loops: The lesson will demonstrate how the modulus operator can be used within different types of loops.

Was this lesson useful?

Next Lesson

The Modulus Operator (%)

Learn how we can use the modulus operator to get the remainder of integer division, and some common use cases.
3D art showing two RPG characters
Ryan McCombe
Ryan McCombe
Updated
3D art showing a progammer setting up a development environment
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, Unlimited Access
3D art showing a progammer setting up a development environment
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, unlimited access

This course includes:

  • 60 Lessons
  • Over 200 Quiz Questions
  • 95% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Next Lesson

The Modulus Operator (%)

Learn how we can use the modulus operator to get the remainder of integer division, and some common use cases.
3D art showing two RPG characters
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved