Search

5.5 — While statements

The while statement is the simplest of the four loops that C++ provides, and it has a definition very similar to that of an if statement:

while (expression)
    statement;

A while statement is declared using the while keyword. When a while statement is executed, the expression is evaluated. If the expression evaluates to true (non-zero), the statement executes.

However, unlike an if statement, once the statement has finished executing, control returns to the top of the while statement and the process is repeated.

Let’s take a look at a simple while loop. The following program prints all the numbers from 0 to 9:

This outputs:

0 1 2 3 4 5 6 7 8 9 done!

Let’s take a closer look at what this program is doing. First, count is initialized to 0. 0 < 10 evaluates to true, so the statement block executes. The first statement prints 0, and the second increments count to 1. Control then returns back to the top of the while statement. 1 < 10 evaluates to true, so the code block is executed again. The code block will repeatedly execute until count is 10, at which point 10 < 10 will evaluate to false, and the loop will exit.

It is possible that a while statement executes 0 times. Consider the following program:

The condition 15 < 10 immediately evaluates to false, so the while statement is skipped. The only thing this program prints is done!.

Infinite loops

On the other hand, if the expression always evaluates to true, the while loop will execute forever. This is called an infinite loop. Here is an example of an infinite loop:

Because count is never incremented in this program, count < 10 will always be true. Consequently, the loop will never terminate, and the program will print "0 0 0 0 0 ..." forever.

We can declare an intentional infinite loop like this:

The only way to exit an infinite loop is through a return statement, a break statement, an exit statement, a goto statement, an exception being thrown, or the user killing the program.

Programs that run until the user decides to stop them sometimes intentionally use an infinite loop along with a return, break, or exit statement to terminate the loop. It is common to see this kind of loop in web server applications that run continuously and service web requests.

Loop variables

Often, we want a loop to execute a certain number of times. To do this, it is common to use a loop variable, often called a counter. A loop variable is an integer variable that is declared for the sole purpose of counting how many times a loop has executed. In the examples above, the variable count is a loop variable.

Loop variables are often given simple names, such as i, j, or k. However, naming variables i, j, or k has one major problem. If you want to know where in your program a loop variable is used, and you use the search function on i, j, or k, the search function will return half your program! Many words have an i, j, or k in them. Consequently, a better idea is to use iii, jjj, or kkk as your loop variable names. Because these names are more unique, this makes searching for loop variables much easier, and helps them stand out as loop variables. An even better idea is to use "real" variable names, such as count, or a name that gives more detail about what you're counting.

It is best practice to use signed integers for loop variables. Using unsigned integers can lead to unexpected issues. Consider the following code:

Take a look at the above example and see if you can spot the error. It's not very obvious.

It turns out, this program is an infinite loop. It starts out by printing "10 9 8 7 6 5 4 3 2 1 blastoff!" as desired, but then goes off the rails, and starts counting down from 4294967295. Why? Because the loop condition count >= 0 will never be false! When count is 0, 0 >= 0 is true. Then --count is executed, and count overflows back to 4294967295. And since 4294967295 is >= 0, the program continues. Because count is unsigned, it can never be negative, and because it can never be negative, the loop won't terminate.

Rule: Always use signed integers for your loop variables.

Iteration

Each time a loop executes, it is called an iteration.

Because the loop body is typically a block, and because that block is entered and exited with each iteration, any variables declared inside the loop body are created and then destroyed with each iteration. In the following example, variable x will be created and destroyed 5 times:

For fundamental variables, this is fine. For non-fundamental variables (such as structs and classes) this may cause performance issues. Consequently, you may want to consider defining non-fundamental variables before the loop. This is another one of the cases where you might declare a variable well before its first actual use.

Note that variable count is declared outside the loop. This is necessary because we need the value to persist across iterations (not be destroyed with each iteration).

Often, we want to do something every n iterations, such as print a newline. This can easily be done by using the modulus operator on our counter:

This program produces the result:

01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50

Nested loops

It is also possible to nest loops inside of other loops. In the following example, the inner loop and outer loops each have their own counters. However, note that the loop expression for the inner loop makes use of the outer loop's counter as well!

This program prints:

1
1 2
1 2 3
1 2 3 4
1 2 3 4 5

Quiz

1) In the above program, why is variable inner declared inside the while block instead of immediately following the declaration of outer?

Show Solution

2) Write a program that prints out the letters a through z along with their ASCII codes. Hint: to print characters as integers, you have to use a static_cast.

Show Solution

3) Invert the nested loops example so it prints the following:

5 4 3 2 1
4 3 2 1
3 2 1
2 1
1

Show Solution

4) Now make the numbers print like this:

        1
      2 1
    3 2 1
  4 3 2 1
5 4 3 2 1

hint: Figure out how to make it print like this first:

X X X X 1
X X X 2 1
X X 3 2 1
X 4 3 2 1
5 4 3 2 1

Show Solution

5.6 -- Do while statements
Index
5.4 -- Goto statements

227 comments to 5.5 — While statements

  • jaasdsfae rgegraewr

  • C.E

    Hi Alex
    Just really wondering about the storage of 'sum' ( where does it go ? ) ( how do the unqiue values persist over mutiple iterations) once there has been at least one iteration

    • @sum is declared outside of the loop. It's value is preserved over iterations. @sum dies when it goes out of scope, which in this case is equivalent to when to program ends.

      • C. E

        Does that mean for every x value sum has a unique value over multiple iterations
        How would  it be possible  for one variable to hold multiple variables without using a initializer list

        • @sum's value updates in every iteration. In line 14, @sum has it's old value. In line 16, @sum has it's old value + @x. When the loop is over, @sum stores the sum of all @x's entered by the user.
          Try printing @sum's value inside the loop to get a better understanding of what's happening.

  • Sini Paolo

    In the "Loop variables" section :

    "Many words have an i, j, or k in them. Consequently, a better idea is to use iii, jjj, or kkk as your loop variable names."

    I don't think you should use "kkk" as a name for anything ^^ :p .
    More seriously though thanks for all these awesome lessons, been binge-learning, love the quizzes and exercises as well.
    Lots of love <3

  • ChilaKiller

    i got the requested output in the last quiz but i did it with a different approach and i realized how much better the actual solution was, so can you guys tell me if the following code is acceptable, if not why:

    thanks in the advance

  • George

    To solve (2), I did this :

    and got the same result. Is this worse than the solution Alex provided and, if yes, how? Does casting integers to chars instead of the inverse increase compilation time, for instance?

    • Hi George!

      There shouldn't be a performance difference. But Alex' code is easier to read, because it's obvious at which letter his loop starts and stops. In order to understand your code one has to know the ASCII values of the characters.

  • And the next one:

  • Solution one was easy:

    Now to reverse the loop for number 2.....

  • damian

    #include <iostream>

    using namespace std;

    int main()
    {

        int numberOfLines =1;
        while (numberOfLines<=5){

        int number = 5;
        while (number>=1){
        if (number<=numberOfLines){

            cout<<number<<" ";

        }else {
        cout<< "  ";
        }
        number--;
        }

        cout<<endl;
        numberOfLines++;
        }
        return 0;
    }

  • For the above code, I get the output in the following format:
         1
        2 1
       3 2 1
      4 3 2 1
    5 4 3 2 1
    Which isn't the intended format for the last question.
    The issue is an additional space in the following code line;

    change that statement to the below one

    And I get it in the format that the question has.

    Can anyone confirm if it is the same for them? (It should be!)

    @Alex: Great lessons by the way! Enjoying them! Can't wait to see what exercises you have in store for the core OOPS concepts.
    I hope there is atleast one small game developed at the end of all the chapters! 🙂

  • carlitosblvd

    #include<iostream>

    int main(){
        
        char empty = ' ';
        
        int counter = 1;
        
        while (counter <= 5){
            int num = 1;
            int inner = 5;
            while (inner > counter){
                std::cout << empty;
                --inner ;
                ++num;
            }
            while (num <= 5){
                std::cout << inner;
                --inner;
                ++num;
            }
            std::cout << "\n";
            counter++;
        }
        return 0;
    }
    Nascar driver what do you think now?

    • You removed the using-statement and partially changed postfix++ to ++prefix, though, you're still using counter++, you're not using uniform initialization and you're still initializing @empty to a space.

      Also, please use code tags (See the yellow message beneath the comment box).

  • Arumikaze

    Hello! I did the last question and came up with a different answer again. I looked at both of the solutions (given and mine) and I am confused as to which one is better. The given answer completes the problem with significantly less code, but with more iterations. On the other hand, my code is longer but completes it in less iterations. Is there a better solution here?

    • Hi Arumikaze!

      Code-wise, Alex' code is better. Your switch-statement screams "use a loop instead".
      Performance-wise, I don't think there's a significant difference. Your code produces a larger binary though, because the code inside the cases is repeated.

  • carlitosblvd

    #include<iostream>

    using namespace std;

    int main(){
        
        char empty = ' ';
        
        int counter = 1;
        
        while (counter <= 5){
            int num = 1;
            int inner = 5;
            while (inner > counter){
                cout << empty <<" ";
                inner --;
                num++;
                
            }
            while (num <= 5){
                cout << inner <<" ";
                inner--;
                num++;
            }
            cout << endl;
            counter++;
        }
        
        
        return 0;
    }

  • Josh 2

    Slightly off topic but after playing around with loops I've created my first little app, thanks Alex.
    However, when I build the app and run it as an executable and not in the compiler the cmd prompt closes before I see the result.
    Whats the best way to stop this from happening?

    • nascardriver

      Hi Josh!

      > run it as an executable and not in the compiler
      IDE, not compiler

      Shift+Right Click in the directory the executable resides in -> Open Command Prompt here (Or similar).
      Then run the program from the command prompt.

      Alternatively, you can add

      to the end of your program, but this causes poor results on operating systems that use a terminals for interaction.

  • Kristian

    Never mind, I actually understand now that the inner loop is executed until the condition is satisfied each time.

  • Kristian

    Could you please try to explain to me more why this program works? Like I understand the variable inner is being reset to one and incremented after the output is displayed but I can't seem to understand how it works exactly, like does it have something to do with the queued output that's left in cout?
    I'm talking about the last example.

  • Jack

    In the example:

    Is the lack of {} around the inner loop intentional? I know they're equivalent, but which is best practice in C++?

    • nascardriver

      Hi Jack!

      Do as you wish. I prefer to always use curly braces. It's easier to add code if you ever decide to, they're less prone to poor formatting and easier to read.

    • Alex

      It's intentional. There is no best practice here, either is acceptable. I tend to not use braces in these cases because it makes the code vertically longer for little benefit, but if you prefer to always use them you certainly can.

      • test

        Hey guys,

        I'm playing around with this particular snippet of code in Xcode (IDE), and I do get different results if I use the {} in the inner loop?

        • Alex

          Is that a question or a statement?

          Putting {} around the most indented line in the above program shouldn't change the output, so either that was a question, or you put your {} around the wrong statements.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]