Loops

If you did the exercise mentioned in control flows, you might have seen something a bit irritating. For you to find the smallest number of years, until the probability was higher than 50%, you needed to go through each number, starting from 0, one by one, then put it in the appropriate variable and run the program. If the program printed some message, great, you found the minimal value, if not, oh well, better luck next time. This task seems irritating. We’re running the same exact instruction, but with a different value. There must be some way to shorten the process. You’re in luck, because most programming languages since their creating have something implemented in them and it’s called loops.
In comparison to if statements, where if the condition is true, the block of code beneath it gets executed, loops continue executing the block of code beneath them until the statement you provide turns false. Let us give you an example.
Imagine a valet standing in front of a parking garage of some fancy restaurant. His job is simple: When a new car arrives, he checks if there are free parking spaces. If there are, he takes the persons car, drives it to the free parking space and then returns to his original position. It seems as if the valet is in a loop. Now, if we assume that the parking garage has a finite amount of parking spaces and that, for some reason, the fancy guests leave their cars there forever. The valet will continue doing the exact same thing until every single parking space is occupied. But, there’s a slight catch. Even though it seems that the valet is doing the exact same task, we’re missing one crucial detail: He’s checking if there are free parking spaces. Our valet is very intelligent so he doesn’t want to work at the parking space forever. He probably wants to get home and watch some tv. That’s why our valet before starting his shift counts the number of free spaces. When a new car arrives, he checks to see for free parking spaces and parks the car to the one he found, but after that he decreases the number of free spaces by one. That’s why after he parks the last car and sees on his handy notepad that the number of free spaces is zero, he packs his things and goes home. This is a crucial detail which we will use later. Now, let’s write some code.
Before we get into the actual code, we will give you something called a pseudocode. It’s a type of code which is not specifically a programming language and its use is just to give the reader an intuition and logic about the given problem. It can’t be compiled and it can’t be run.
loop(some_condition)
{
  contents_of_the_loop
}

The two most important things you should take away from this pseudocode is the “some_condition” and “contents_of_the_loop”. “some_condition” represents a statement which gets evaluated to either true or false. If it’s true, “contents_of_the_loop” gets executed and the program returns to the “some_condition”. If not, you exit the loop. This is the takeaway point. Unlike if statements, this chunk of code gets repeatedly executed until “some_code” becomes false. For us to further show you the power of loops, we will start with our first loop, the while loop.

While loop

The name says it all: While something is true, execute the code in the loop. The structure of the while loop looks almost identical to the pseudocode:

while(condition)
{
  some_statements;
}

Let’s look at a BAD example how we can use this. Imagine you wanted to print every number from 0 to 100 which is divisible by 5. One way you can do it is to increment it by 5, then print it, then increment it by 5 again, then print it again… until your number reaches 100:

#include <iostream>

using namespace std;

int main()
{
  int number = 0;
  number += 5; // number = 5
  cout << number << endl; //endl will move the output cursor to the next line
  number += 5; // number = 10
  
  //...
  
  number += 5; // number = 100
  cout << number << endl;
}

As you can see, we are doing the exact same task and it’s inefficient. Not only do you need to write all this out, you also need to keep track of the number of times you are doing it. If you wanted to change the maximum number from 100 to 75, you would need to delete a certain number of lines. If then you decide “Hmm, maybe I need up until 170”, you then need to calculate how many more lines you need to add. If finally, for some God-forbidden reason you wanted to change the logic of your code to print all the numbers divisible by 3, you would need to change every second line of your code. This repetitive work can easily be avoided using a while loop:

#include <iostream>

using namespace std;

int main()
{
  int number = 0;
  while(number <= 100)
  {
    number += 5;
    cout << number << endl;
  }
  return 0;
}
Now we can easily control every single aspect of the execution. If now you wanted to change the maximum number to, let’s say 180, you would just change it in the condition of the while loop. Do you want to print all the numbers divisible by 7 now? No problem! Change the increment number in the loop from 5 to 7.
Our code is now not only cleaner, but it is also easily maintainable if we want to introduce some changes.
 
Let us look at another example. Imagine you wanted to sum up all the number from 1 to 10. Even though there is an exact formula for this task, we will take the slower approach and just try to sum up all the numbers one by one. One approach to solve the problem could be:
  • Define a variable where we will store the sum (“sum”)
  • Define a variable (“number“) which will represent the number we are adding
  • While the “number” is less then 10, do the following:
    • Add the “number” to the “sum
    • Increment the “number” so it can be the next number we are adding
Number” will be 1 at the beginning. After we add it to the sum, we want to add the next number (2) and so on… We increment each number until we hit the maximum, in this case 10.
#include <iostream>

using namespace std;

int main()
{
  int sum = 0;
  int number = 1;
  int N = 10;
  while(number <= N)
  {
    sum += number;
    number++;
  }
  cout << sum << endl;
  return 0;
}

Do-while

The do-while loop is relatively similar to the while loop, but with one key difference. In the while loop, the first thing that is done is the check whether the condition is true. If in some special case that was not true, the condition was indeed false and the program will just skip the whole loop, just like that! What if, for some reason you wanted to execute at least one iteration, even if the condition was false? What if you wanted just one iteration and if the condition was true, you continue the same way as with the while loop, but if the condition was false, oh well, at least you got one iteration out of that sucker. That exactly is the structure and logic of a do while loop. In some sense, it looks like a reverse while loop and you’ll see why in the example below:

do
{
  do_some_important_work;
}
while(condition);
Before getting into the next topic, let’s look at one particular example.
Let’s say you wanted to make a program which will calculate the number of days you need to work out to achieve your current weight. Let’s assume that you managed to calculate how much weight you gain each day by taking into consideration how much weight you gain from eating and how much weight you lose from workouts. For example, you managed to make a meal plan which increases your weight each day by 0.01 kilograms and you managed to make a workout regime which decreases your weight by 0.01 kilograms times your workout streak. If you manage to workout three days in a row, the first day you would have lost 0.01 kilograms, the next 0.02 and the third 0.03. Finally, let’s assume that you currently have 78 kilograms and want to lose 3 kilograms which means your ideal weight would be 75 kilograms. Let’s start with some key elements our program must have:
  • At the start, we need to define variables for the current weight, ideal weight, number of kilograms gained from eating, number of kilograms lost from working out per day and the current workout streak which will be incremented every day
  • We need to loop through, where each iteration represents a day
  • During one iteration, we must calculate the number of kilograms lost/gained
  • We need to add that number to the current weight
  • Finally, we check if the current weight is below the ideal weight
#include <iostream>

using namespace std;

int main()
{
    
    double current_weight = 78;
    double ideal_weight = 75;
    int streak = 0;

    do
    {
        streak++;
        double weight_gain = 0.01 - 0.01 * streak; /* weight_gain = from_eating - (from_workout * streak)*/
        cout << "Current weight: " << current_weight << endl;
        cout << "Kilograms to goal: " << current_weight - ideal_weight << endl;
    
    }
    while(current_weight > ideal_weight);


    return 0;
}

Let’s check the output:

Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
Current weight: 78
Kilograms to goal: 3
...
Oh oh, something went wrong! Firstly, if you haven’t noticed, some code’s here are left “broken” on purpose for 2 reasons:
  1. Don’t be a code monkey – Copying and pasting code blindly will do you more harm than help. Try understanding the code before you run it
  2. They are left as an exercise – There’s nothing greater in programming than figuring out a problem on your own. If you can come up with a solution on your own, that means that you have understood every step so far and are also starting to develop some crucial problem-solving skills which are very sought after by the industry
Now, let’s try to find where we messed up. Because the current code runs indefinitely and we get the same numbers as the starting values, it must be something we did in the do-while loop. The more obvious analysis was the actual output – if you see something running indefinitely, you should check all of your loops to see if by accident you forgot to update the iterator properly. That is our problem right here. We calculated the weight gained/lost, but never updated the current weight. Finally, we will change the code a bit so that instead of giving us the weight every iteration, it gives us the number of days it takes to get to the ideal weight. Fortunately, our streak gets increased by one each iteration, so logically that also represents the number of days it took to get to the ideal weight:
As an exercise project: Think how you would change the code so that instead of just loosing weight, there would be a difference between the ideal and current weight.
 
Finally, one more thing to keep in mind: these are just examples. The actual logic behind these phenomena in the real world are totally different, so please don’t take diet and workout advice from a coding website.

For loops

Now that we know what loops are and how to use them, we’ll introduce a new type of loop and see one of the most practical uses for loops.
 
One thing that may have bugged you in the while loops example is to do with the variable number. Before using it, we had to not only declare it, but also initialize it to some value. Secondly, we had to increment it inside of the while loop. If by some mistake we forgot to increment the variable, we would encounter an infinite loop (a loop which continues running “forever”). Finally, if you tried and tweaking the code in some way, you would have seen that even though we exited out of the loop, we still had our variable number with the last value it had. Your program in that case still has allocated memory for that variable even though we may not use it anymore. This isn’t such a big problem when we’re tackling small projects, but imagine if we had a bunch of these loops and every single loop would need its own number variable, per say. You could assume that having variables like this would be resource inefficient and you would be correct. Let’s sum up all this arguments in a couple of statements:
  • If for any reason you forgot to initialize your variable, the code might do some strange things (due to the compiler putting some garbage value in the declared variables)
  • If you forget to increment your variable, you’ll encounter something called an infinite loop (a loop which does not end and continues running until you forcefully terminate your program)
  • After exiting the loop, the variable still exists, even though it served its purpose
 
Before going any further, we should talk a bit about a concept called local variables. Throughout this and previous lessons we have seen a lot of these symbols “{}“. In the first lesson in the introduction we have only said that they are used to contain a single code block, but their purpose is a bit more than that. Every single variable has a property called lifespan. It determines how long a variable may live, or to put it in different words, from which point in code to which other point in code is the variable visible. Every single variable declared in a code block is called a local variable and its visibility is from the point its defined until the end of the code block. The term visibility just means “where can I use my variable”. You surely cannot use it before you declare it, but now we also know that you cannot use a variable after the code block ends in which the variable is declared. Finally, we would like to add just one more new term before continuing on with loops and that is global variables. For now, you just need to know that global variables are declared outside every code block and their visibility or sometimes called scope is from the moment they are declared until the end of the program.
Now, for the reasons mentioned above our paragraph about local variables, programmers have decided to create a new type of loop, exploiting the fact of local variables. This new type of loop is called the for loop. It serves the same purpose as the previously mentioned loops, but with some additional features:
  • You can declare and initialize a local variable at the start of the for loop so that the variables scope is only inside of the for loop
  • If you declare additional local variables in the body of the for loop, they will only exist until the for loop is done
  • You can add a statement in the for loop which will be executed after every iteration of the loop
The pseudocode of the for loop is given as such:
for(local variable declaration/initialization; condition; statement)
{
  ...
}

Let’s see an example. If we try rewriting the example for the while loop with a for loop, it may look something like this:

#include <iostream>

using namespace std;

int main()
{
  int sum = 0;
  int N = 10;
  // number is defined at the start of the for loop and will only be visible inside the loop
  for(int number = 0; number < N; number++ )// number gets incremented after every iteration 
  {
     sum += number;
  }
  // number does not exist here
  cout << sum << endl;
  return 0;
}
Now, we eliminated all three problems:
  • number is only needed inside of the loop and we defined it at the start of the loop, so we didn’t need to do any prior declaration.
  • Because number is declared at the start of the loop, its scope is just inside of the loop. After the loop is done, number doesn’t exist anymore.
  • We were able to supply the increment at the start of the loop, making this a good practice not to forget to increment the number every time
As you can see, the for loop has a very nice structure we can follow: declare a local variable, add the condition and finally supply the post operation.
 
Now, let’s look at that practical example we talked about. In previous lectures, we have seen a data structure called arrays. They’re useful for storing data, but imagine you wanted to add all the elements of the array. Let’s first look at how we would do it without loops.
int array[] = {1, 3, 4, 5};
int sum = array[0] + array[1] + array[2] + array[3];

This seems easy enough, but now imagine if the array was a lot bigger, let’s say, 10 elements. If we just changed the number of elements of the array, we would also need to redefine our sum, which seems like a tedious task. Instead, we can notice a pattern. We see that the sum has one thing in common. We’re summing elements of the array where the index gets increased by one and the last index is the (number of elements – 1) in the array (because indexes start from 0). We can exploit this and actually do the summation inside of a for loop like this:

int array[] = {1, 5, 21, 43, 21, 22, 11, 75, 21, 13, 8, 68};
int sum = 0;
int N = 12; // 12 elements in the array
for (int i = 0; i < N; i++)
{
  sum += array[i];
}

This seems to do the trick. We go through every element and add it to the sum. More importantly, if we now add a new element to the array, we just need to change the variable N and everything works perfectly!

Table of contents

Leave a Reply