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 wraps around back to 4294967295 (Assuming 32 bit integers). 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.

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 loop 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 time

Question #1


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

Show Solution

Question #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

Question #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

Question #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

1 comment to 5.5 — While statements

  • Tobito

    currently all the comments is disappear for all pages

  • Aditya

    Here's my solution to #4, took really long lol. As always thank you for these tutorials!!

  • Uyph

    Hi, in relation to quiz 4, i want to ask why decrementing counter inside the second while loop changes the final value of it, causing the program to overflow. Don't changes made to it only exist inside the loop?

  • Artyom

    This is my solution for task 4

  • Attila

    This is question 4 just all done with while loops

  • Andreas Krug

    Small fix in second code example of chapter Iteration, line 12:
    std::cout << '0' << count << ' '; instead of std::cout << "0" << count << ' ';

  • Martin

    The section on loop variables contains the statement "Then --count is executed, and count overflows back to 4294967295."
    Earlier in the tutorial I learned that unsigned integers do not overflow, but wrap around, so I suggest to use this wording here, too. :)

  • Christian

    Hi and thank you so much for this tutorial. I am a newbie and I am confused about while loops. In the following program I am trying to calculate the standdev of a set of numbers from a file

    The number in the current file are
    80
    90
    just to test the program. What I really don't understand is why it reads the last value twice.

    Thanks for all your help.

    /**************************************************************
    Description: Design and write a C++ program that reads a set of
                 scores from the file scores.dat, and
                             outputs their
                 mean and standard deviation on cout.
    **************************************************************/

    #include <iostream>
    #include <fstream>
    #include <cmath>

    using namespace std;

    int main(){
        // Declare input stream
        ifstream inData;
        
        // Declare variables
        int count = 0;
        float value;
        float valueSquared = 0.0;
        float sum = 0.0;
        float sumSquared = 0.0;
        float average, standDev;
        // Open file
        inData.open("scores.dat");
            if(!inData){
                cout << "Cannot open the file." << endl;
                return 1;
            }
        //inData >> value;
        //valueSquared = value*value;
        //cout << value << ", " << valueSquared << endl;
        //sum = value;
        //sumSquared = valueSquared;
        //cout << sum << ", " << sumSquared << endl;
        // Get values and calculate sums
        while(!inData.eof()){ //Set the EOF flag
            inData >> value;
            valueSquared = value*value;
            cout << value << ", " << valueSquared << endl;
            sum = sum + value;
            sumSquared = sumSquared + valueSquared;
            count++;
        }
        cout << count << ", " << sum << ", " << sumSquared << ", " << sum*sum << endl;
        // Check that you have at least two values
        if(count<=1){
            cout << "Average and standard deviation are meaningless for one single value." << endl;
            return 1;
        }
        else{
            // Calculate average
            average = sum/count;
            // Calculate standard deviation
            standDev = sqrt((sumSquared-(sum*sum))/(count*(count-1)));
            // Output results
            cout << "The average and standard deviation of the set of scores are\n" <<
                "average: " << average << "\n" << "standard deviation: " << standDev << endl;
        }
        return 0;
    }

  • Tony

    For me, this is by far the most difficult chapter ever, at least the questions. Didn't seem to actually get a correct solution at all, and had to check the solutions multiple times (and I still haven't understood much). I guess I'll have to re-do this chapter later on. Thanks for the tutorials again :)

  • #Prints alphabets a - z

    • Ohh... Sorry I made a mistake in my code
      Correct one

  • Hi there, I am having some little issues understanding your code understand Nested Loops

    This code

  • for whatever reason, on debian 10, using the terminal in VSCode, my initial solution to the last problem resulted in the shape of some sort of binary tree being printed out.. just to make sure it was an issue with my code, i tried the provided solution, however the same thing resulted when compiling and executing the answer.

    ended up doing this really weird and gross looking answer that doesnt satisfy me all that much, but i assume it'll get cleaner in time

    • nascardriver

      I suppose you saw the cool pyramid

      This happens if you print a single space, rather than 2 spaces, in line 21 of the quiz's solution. It might also happen if you're not using a monospace font.

  • AE35_Unit

    Okay, got all three. Wanted to use a continue; in solution 2 but that's section 5.8. Comments and few questions in the code, thanks. Cheers.

    • nascardriver

      - You're not using `argc` or `argv`, so they shouldn't be there.
      - Your formatting will only get worse. Use an auto-formatter.
      - Use characters, not integers, for characters.
      - Avoid `static` variables, your code isn't reusable.

      • AE35_Unit

        Thanks Nascar.  Got it cleaned up and made the changes. I understand what you mean by use chars 'A' and not number 65, saw and got it fixed. I want to make sure I understand the static comment.  I move the variable to outside the while loop so I could just use int variable and not static int variable. Your comment "your code isn't reusable" is in reference to that (static int variable) not being able to be used from an outside or another file as in a header file.  I re-read chapter 6.6 and that's what I gathered from it, just wanted to make sure I understood.  Thanks for the help. Cheers.

        • nascardriver

          You wrote everything in `main`, so I had to say "code" isn't reusable rather than "function xx" isn't reusable, which would be easier to grasp. Say you wrote a function instead

          Now what happens when you call `quiz4()`? Everything is as it was before.
          What happens when you call `quiz4()` a second time? It's broken, because `printNumber` was never reset.
          If `printNumber` is non-static, it doesn't matter how often you call `quiz4()` or where you call it from. The function the same every time it called (If we ignore `std::cout`'s flags, which could be changed from the outside). The way you solved it now is correct.

          Keeping `printNumber` `static` and resetting it at the end of the function would have seemingly solved them problem, but it would still be there, just in a different case. `quiz4()` could only be called from one place at a time. That's what we do throughout the entire tutorial so you wouldn't have noticed that it's broken. But if you get into multithreading, this is no longer the case. `quiz4()` could run several times in parallel. But if all running `quiz4()`s share a variable, you'll run into trouble.

  • John

    Hello, I quite don't understand the last example. If "inner" is created and initialized after every iteration, then how does it print "1 2", "1 2 3", etc.

  • Amir

    maybe not the best, but it is how  I was thinking before looking at solution !

  • Jimmy

    This is really discouraging cause after nearly an hour of work, mainly due to sorting out bugs through trial and error, this is the best solution i can come up with. Yet the solution posted is way simpler. I am having serious doubt about me becoming a programmer.

    The worst part is if you ask me to write the same program a few hours later. I would have to trial and error my way through the same bugs.

    • nascardriver

      And every time you do it, you get better. You can't expect from yourself to be able to write great code after reading a tutorial. You'll only get better by writing code, failing, and looking up how to do it properly.

  • Joshua

    This is my honest first attempt... I was kinda reaching on this one... Is my solution with the string initialization less effective than just putting a conditional in there?

    • nascardriver

      `std::string` has to perform a dynamic memory allocation (If the string is long enough), which makes it slower than printing manually. You're not going to notice this, so your solution is fine. "\n" should be '\n'.

  • samira

    Hello Nascardriver and Alex,

    The following is the short solution to the question 3 using JUST one (do)while-loop. (I put two versions)

    SOLUTION VERSION ONE

    SOLUTION VERSION TWO

    • Petter Nybråten

      Instead of the string of spaces below, is it better to concatenate two space chars? How about three? Asking with regards to performance.

  • sami (typo)

    " In the following example, the inner loop and outer loops each have their own counters."

    Shouldn't it be "and outer loop"?

Leave a Comment

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