Loading
All articles
Programming 20 min read

The While and Do-While Loops: A Visual, Hands-On Guide

Learn the while and do-while loops visually: how they check before or after, the three ingredients of every loop, input validation, sentinels, break and continue, infinite-loop traps, plus fun real examples (paper folding, Collatz) and exercises.

nbkhope
On this page

Computers never get bored. Ask one to do something a million times and it will, without complaint. Loops are how you ask. This article covers the two loops built for "keep going until something happens": the while loop and its sibling, the do-while loop.

You'll see how they work step by step, fold a sheet of paper all the way to the Moon, chase a number that bounces like a hailstone, build a game and a menu, and learn to spot the infinite loop before it freezes your program. Exercises with answers wrap it up.

The examples are in C++, but while and do-while look almost the same in C, Java, C#, JavaScript and many other languages.

while vs. do-while at a glance

Both loops repeat a block of code as long as a condition stays true. The only difference is when they check it:

while checks first; do-while checks last, as two flowcharts. The while loop runs 0 or more times: from the start, it checks the condition; if true, it runs the body and goes back to check again; if false, it goes to after the loop. The do-while loop runs 1 or more times: from the start, it runs the body first, then checks the condition; if true, it goes back to run the body again; if false, it goes to after the loop. If the condition is false from the very start, a while loop never runs its body, but a do-while still runs it once
while (condition) {
    // runs again and again, as long as condition is true
}
do {
    // runs once first, then again as long as condition is true
} while (condition);   // note the semicolon!

The while loop

Here's the classic example, counting from 1 to 10:

1#include <iostream>
2
3int main() {
4    int count = 1;              // 1. start
5
6    while (count <= 10) {       // 2. check
7        std::cout << "The value of count is " << count << "\n";
8        count++;                // 3. step: without this, the loop never ends
9    }
10
11    std::cout << "Done! count is now " << count << "\n";
12}

Sample run:

1The value of count is 1
2The value of count is 2
3The value of count is 3
4The value of count is 4
5The value of count is 5
6The value of count is 6
7The value of count is 7
8The value of count is 8
9The value of count is 9
10The value of count is 10
11Done! count is now 11

Step by step: count starts at 1. Is 1 ≤ 10? Yes, so the body prints and adds one. Back to the check: is 2 ≤ 10? Yes… and so on, until count becomes 11. Then 11 ≤ 10 is false, and the program moves on past the loop. That's why the last line says 11: the loop stops because count went past 10.

The three ingredients

Almost every while loop has the same three parts. Leave one out, or get it wrong, and the loop misbehaves:

Every while loop needs three ingredients. 1, start: int count = 1; gives the loop variable a starting value. Forget it and the loop starts from garbage. 2, check: while (count <= 10) decides whether to go around again. Get it wrong and you get one step too many or too few. 3, step: count++; moves toward the finish line. Forget it and the loop never ends. A for loop packs the same three parts into one line: for (int count = 1; count <= 10; count++)

When you don't know how many times

Fold a piece of paper to the Moon

A sheet of paper is about 0.1 mm thick. Each time you fold it in half, the thickness doubles. How many folds until it would reach the Moon, 384,400 km away? You can't easily count that in your head, so let a while loop find out:

1#include <iostream>
2
3int main() {
4    double thicknessInMeters = 0.0001;  // a sheet of paper: 0.1 mm
5    const double distanceToMoon = 384400000.0;  // 384,400 km
6    int folds = 0;
7
8    while (thicknessInMeters < distanceToMoon) {
9        thicknessInMeters *= 2;  // each fold doubles the thickness
10        folds++;
11    }
12
13    std::cout << "Folds needed to reach the Moon: " << folds << "\n";
14    std::cout << "Final thickness: " << thicknessInMeters / 1000 << " km\n";
15}

Sample run:

Folds needed to reach the Moon: 42
Final thickness: 439805 km

Only 42! Here's the whole journey, fold by fold:

Fold a 0.1 mm sheet of paper in half, again and again. Each fold doubles the thickness, shown on a logarithmic scale where each grid line is 1,000 times the one below. 7 folds: 1.3 cm, as far as most people get by hand. 23 folds: 839 m, taller than the Burj Khalifa. 27 folds: 13 km, higher than Mount Everest. 32 folds: 429 km, past the Space Station. 42 folds: 439,805 km, past the Moon. Doubling grows shockingly fast. The loop runs only 42 times, but you couldn't easily have guessed that number before running it

(In real life, nobody has folded a sheet of paper more than a dozen or so times. But the math, and the loop, don't care.)

The hailstone numbers

Here's a famous puzzle. Pick any whole number. If it's even, halve it. If it's odd, triple it and add 1. Repeat until you reach 1. How many steps does it take?

1#include <iostream>
2
3int main() {
4    long long number = 27;
5    int steps = 0;
6    long long highest = number;
7
8    while (number != 1) {
9        if (number % 2 == 0) {
10            number = number / 2;
11        } else {
12            number = 3 * number + 1;
13        }
14        steps++;
15        if (number > highest) highest = number;
16    }
17
18    std::cout << "27 reaches 1 after " << steps << " steps\n";
19    std::cout << "Highest value on the way: " << highest << "\n";
20}

Sample run:

27 reaches 1 after 111 steps
Highest value on the way: 9232

We ran the same loop for every starting number from 1 to 30:

How many steps to reach 1, for starting values 1 to 30. Rule: if even, halve it; if odd, triple it and add 1. Most starting numbers need between 0 and 23 steps, but 27 takes 111 steps. Neighbors behave completely differently: 26 needs 10 steps and 27 needs 111. You can't know the count in advance, which is exactly when you reach for a while loop

And here's the wild ride 27 takes on its way down:

The wild ride of 27: up to 9,232 and back down to 1. The value bounces up and down for 111 steps, climbing slowly at first, shooting up to a peak of 9,232 at step 77, then falling quickly to 1 at step 111. Mathematicians call these hailstone numbers because they bounce up and down like hail in a storm cloud. Nobody has proved that every starting number reaches 1; it's an unsolved problem called the Collatz conjecture

Taking a number apart, digit by digit

% 10 gives the last digit of a number, and / 10 chops it off. Repeat until nothing's left:

1#include <iostream>
2
3int main() {
4    int number = 90210;
5    int digitCount = 0;
6    int digitSum = 0;
7
8    while (number > 0) {
9        digitSum += number % 10;  // the last digit
10        number /= 10;             // chop off the last digit
11        digitCount++;
12    }
13
14    std::cout << "Digits: " << digitCount << ", sum of digits: " << digitSum << "\n";
15}
Digits: 5, sum of digits: 12

Reading until a stop signal

A sentinel is a special value that means "I'm done". This program reads scores until the user types -1:

1#include <iostream>
2
3int main() {
4    int total = 0;
5    int count = 0;
6    int score;
7
8    std::cout << "Enter scores (-1 to finish): ";
9    std::cin >> score;
10    while (score != -1) {
11        total += score;
12        count++;
13        std::cin >> score;
14    }
15
16    if (count > 0) {
17        std::cout << count << " scores, average " << static_cast<double>(total) / count << "\n";
18    } else {
19        std::cout << "No scores entered\n";
20    }
21}

Sample run:

Enter scores (-1 to finish): 90 85 77 -1
3 scores, average 84

If the very first value is -1, the loop body never runs at all, and the program says "No scores entered". That "zero times is fine" behavior is exactly what a while loop is for.

The do-while loop

A do-while runs its body first and checks the condition after. So the body always runs at least once. Here's the difference in one program, with a condition that's false from the start:

1#include <iostream>
2
3int main() {
4    int number = 2;
5
6    do {
7        std::cout << "do-while sees " << number << "\n";
8        number++;
9    } while (number < 2);
10
11    number = 2;
12    while (number < 2) {
13        std::cout << "while sees " << number << "\n";
14        number++;
15    }
16
17    std::cout << "The end\n";
18}
do-while sees 2
The end

The do-while printed once before discovering that 3 < 2 is false. The while loop checked 2 < 2 first, found it false, and never ran its body.

Perfect for: asking until the answer is valid

You can't check an answer before you've asked the question, which makes input validation the do-while's classic job:

1#include <iostream>
2
3int main() {
4    int rating;
5
6    do {
7        std::cout << "Rate the movie from 1 to 5: ";
8        std::cin >> rating;
9        if (rating < 1 || rating > 5) {
10            std::cout << "  That's not between 1 and 5, try again.\n";
11        }
12    } while (rating < 1 || rating > 5);
13
14    std::cout << "Thanks! You gave it " << rating << " stars.\n";
15}

Sample run:

1Rate the movie from 1 to 5: 7
2  That's not between 1 and 5, try again.
3Rate the movie from 1 to 5: 0
4  That's not between 1 and 5, try again.
5Rate the movie from 1 to 5: 4
6Thanks! You gave it 4 stars.

Perfect for: menus

A menu should appear at least once, and keep coming back until the user picks "quit":

1#include <iostream>
2
3int main() {
4    int choice;
5    int coffees = 0;
6
7    do {
8        std::cout << "1) Order coffee  2) Show total  0) Quit\n> ";
9        std::cin >> choice;
10        if (choice == 1) {
11            coffees++;
12            std::cout << "Coffee ordered!\n";
13        } else if (choice == 2) {
14            std::cout << "You've ordered " << coffees << " coffee(s).\n";
15        }
16    } while (choice != 0);
17
18    std::cout << "Bye!\n";
19}

Sample run:

11) Order coffee  2) Show total  0) Quit
2> 1
3Coffee ordered!
41) Order coffee  2) Show total  0) Quit
5> 1
6Coffee ordered!
71) Order coffee  2) Show total  0) Quit
8> 2
9You've ordered 2 coffee(s).
101) Order coffee  2) Show total  0) Quit
11> 0
12Bye!

Perfect for: games

A guessing game: keep asking until the guess is right. You need at least one guess, so do-while fits naturally:

1#include <iostream>
2
3int main() {
4    const int secret = 37;
5    int guess;
6    int tries = 0;
7
8    do {
9        std::cout << "Guess (1-100): ";
10        std::cin >> guess;
11        tries++;
12        if (guess < secret) {
13            std::cout << "  Higher!\n";
14        } else if (guess > secret) {
15            std::cout << "  Lower!\n";
16        }
17    } while (guess != secret);
18
19    std::cout << "Got it in " << tries << " tries!\n";
20}

Sample run:

1Guess (1-100): 50
2  Lower!
3Guess (1-100): 25
4  Higher!
5Guess (1-100): 37
6Got it in 3 tries!

How you choose each guess matters enormously. We had a program play every secret number from 1 to 100 with two strategies: counting up 1, 2, 3…, or always guessing the middle of what's left:

Guess a number from 1 to 100: two strategies, each tried on every secret number by a C++ program. Counting up 1, 2, 3, 4: 50.5 guesses on average, 100 in the worst case. Halving the range, 50, then 25 or 75: 5.8 guesses on average, 7 in the worst case. Both are do-while loops that run until the guess is right. A smarter rule for picking the next guess cuts the work from about 50 guesses to under 6

Same loop, a smarter rule inside it, and 7 guesses is always enough. That halving idea is called binary search, and it shows up all over computing.

Steering the loop: break and continue

Two keywords let you change course from inside the body:

  • break leaves the loop immediately.
  • continue skips the rest of this round and jumps back to the check.
break leaves the loop; continue skips to the next round. In a while (true) loop that adds one to number, if number % 3 == 0 then continue jumps back to the top of the loop, skipping the rest of the round. If number > 10, break leaves the loop right away and carries on after it. Otherwise it prints number. Output: 1 2 4 5 7 8 10
1#include <iostream>
2
3int main() {
4    int number = 0;
5    while (true) {
6        number++;
7        if (number % 3 == 0) {
8            continue;  // skip multiples of 3, jump back to the check
9        }
10        if (number > 10) {
11            break;     // leave the loop completely
12        }
13        std::cout << number << " ";
14    }
15    std::cout << "\nStopped at " << number << "\n";
16}
1 2 4 5 7 8 10 
Stopped at 11

while (true) looks like it runs forever, and it would, without the break. It's a common, handy pattern when the natural place to stop is in the middle of the body.

Infinite loops: the loop that never ends

The most common loop bug is a loop that never stops. Here are three classic ways to write one:

Three ways to write a loop that never ends. Forgot the step: count starts at 1 and while count <= 10 prints it, but count never changes, so it stays 1 forever. Stepping the wrong way: count starts at 10, while count > 0 prints it and does count++, so count grows away from 0. Waiting for an exact decimal: amount starts at 0.0 and while amount != 1.0 adds 0.1, but amount skips from 0.99999999999999989 to 1.0999999999999999. Tip: if a program seems frozen, press Ctrl+C in the terminal to stop it

The third one surprises almost everyone, so let's watch it happen (with a safety net so it stops after 12 rounds):

1#include <iostream>
2
3int main() {
4    double amount = 0.0;
5    int steps = 0;
6
7    std::cout.precision(17);
8    while (amount != 1.0 && steps < 12) {   // steps < 12 is a safety net
9        amount += 0.1;
10        steps++;
11        std::cout << "step " << steps << ": " << amount << "\n";
12    }
13}
1step 1: 0.10000000000000001
2step 2: 0.20000000000000001
3step 3: 0.30000000000000004
4step 4: 0.40000000000000002
5step 5: 0.5
6step 6: 0.59999999999999998
7step 7: 0.69999999999999996
8step 8: 0.79999999999999993
9step 9: 0.89999999999999991
10step 10: 0.99999999999999989
11step 11: 1.0999999999999999
12step 12: 1.2

Computers store decimals in binary, and 0.1 can't be stored exactly, just like 1/3 can't be written exactly as 0.333… in decimal. The tiny errors add up, and amount never lands on exactly 1.0. The fix is to never wait for an exact decimal: compare with < instead of !=, or count whole steps with an int.

Which loop should you use?

Which loop should you use? First question: do you know how many times to repeat before the loop starts? If yes, use for: count to 10, visit every element of an array. If no, second question: must the body run at least once, like asking for input? If yes, use do-while: menus, input checks, play again. If no, use while: repeat until something happens, like a sum or a guess
whiledo-whilefor
Checks the conditionBefore each roundAfter each roundBefore each round
Minimum runs010
Best for"Until something happens"Menus, input validation, "play again?"Counting, walking through arrays
Classic exampleReading until a sentinel"Enter 1 to 5"for (int i = 0; i < 10; i++)

The same idea in other languages

JavaScript has both loops, just like C++:

1let count = 1;
2while (count <= 3) {
3  console.log("count is " + count);
4  count++;
5}

Python has a while loop but no do-while. The usual stand-in is while True with a break:

1while True:
2    answer = input("Type yes to continue: ")
3    if answer == "yes":
4        break

Practice time

Try these before peeking at the answers. Copy each program into a file, compile with g++ -std=c++20 -Wall program.cpp, and run it.

Exercise 1: Predict the output (warm-up). What does this print? Watch the last number carefully.

1int number = 5;
2while (number > 0) {
3    std::cout << number << " ";
4    number -= 2;
5}
6std::cout << "| " << number << "\n";

Exercise 2: Find the bug. This countdown never finishes. Why?

1int seconds = 10;
2while (seconds > 0) {
3    std::cout << seconds << "... ";
4    seconds++;
5}
6std::cout << "Liftoff!\n";

Exercise 3: Reverse a number. Using % 10 and / 10, turn 1234 into 4321.

Exercise 4: Three tries. Ask for a PIN with a do-while loop. Stop when it's right (4321) or after 3 wrong attempts, then print Unlocked! or Too many attempts. Card blocked.

Exercise 5: Greatest common divisor (challenge). Over 2,000 years ago, Euclid found a loop that finds the largest number dividing two numbers evenly: while the second number isn't 0, replace the pair (first, second) with (second, first % second). Find the greatest common divisor of 1071 and 462, printing each step.

Quick quiz

  1. A while loop's condition is false the first time it's checked. How many times does the body run? And for a do-while?
  2. What's missing from int count = 0; while (count < 5) { std::cout << count; }?
  3. What's the difference between break and continue?
  4. Why is while (amount != 1.0) dangerous when amount goes up by 0.1?
  5. Which loop fits "show the menu until the user picks Quit"?

Answers

Exercise 1: 5 3 1 | -1. The loop prints 5, 3 and 1. After 1 it subtracts 2 to get -1, the check -1 > 0 fails, and the loop stops. The variable keeps its last value, -1.

5 3 1 | -1

Exercise 2: seconds++ moves away from the finish line: 10, 11, 12… and seconds > 0 stays true forever. It should be seconds--:

1#include <iostream>
2
3int main() {
4    int seconds = 10;
5    while (seconds > 0) {
6        std::cout << seconds << "... ";
7        seconds--;
8    }
9    std::cout << "Liftoff!\n";
10}
10... 9... 8... 7... 6... 5... 4... 3... 2... 1... Liftoff!

Exercise 3: Each round, shift the result left one digit (* 10) and add the last digit of the number.

1#include <iostream>
2
3int main() {
4    int number = 1234;
5    int reversed = 0;
6
7    while (number > 0) {
8        reversed = reversed * 10 + number % 10;
9        number /= 10;
10    }
11
12    std::cout << "Reversed: " << reversed << "\n";
13}
Reversed: 4321

Exercise 4: The condition combines both reasons to keep asking: the PIN is wrong and there are attempts left.

1#include <iostream>
2
3int main() {
4    const int correctPin = 4321;
5    int pin;
6    int attempts = 0;
7
8    do {
9        std::cout << "Enter PIN: ";
10        std::cin >> pin;
11        attempts++;
12    } while (pin != correctPin && attempts < 3);
13
14    if (pin == correctPin) {
15        std::cout << "Unlocked!\n";
16    } else {
17        std::cout << "Too many attempts. Card blocked.\n";
18    }
19}

Two sample runs:

Enter PIN: 1111
Enter PIN: 4321
Unlocked!
1Enter PIN: 1
2Enter PIN: 2
3Enter PIN: 3
4Too many attempts. Card blocked.

Exercise 5: Three rounds are enough:

1#include <iostream>
2
3int main() {
4    int first = 1071;
5    int second = 462;
6
7    while (second != 0) {
8        int remainder = first % second;
9        std::cout << first << " % " << second << " = " << remainder << "\n";
10        first = second;
11        second = remainder;
12    }
13
14    std::cout << "Greatest common divisor: " << first << "\n";
15}
11071 % 462 = 147
2462 % 147 = 21
3147 % 21 = 0
4Greatest common divisor: 21

Quiz: (1) Zero times for while; once for do-while. (2) The step: count never changes, so the loop never ends. Add count++;. (3) break leaves the loop entirely; continue skips the rest of the current round and goes back to the check. (4) 0.1 can't be stored exactly, so amount jumps from 0.99999999999999989 to 1.0999999999999999 and is never exactly 1.0. (5) do-while, since the menu must appear at least once.

Cheat sheet

I want to…Write
Repeat while something is truewhile (condition) { ... }
Run at least once, then repeatdo { ... } while (condition);
Count from 1 to 10int count = 1; while (count <= 10) { ...; count++; }
Read until a stop valuestd::cin >> value; while (value != -1) { ...; std::cin >> value; }
Ask until the answer is validdo { ask; } while (answer is invalid);
Leave the loop earlybreak;
Skip to the next roundcontinue;
Loop until a breakwhile (true) { ...; if (done) break; }
Take a number apartwhile (number > 0) { digit = number % 10; number /= 10; }
Stop a frozen programCtrl+C in the terminal

Wrapping up

While loops are how a program says "keep going until…":

  • while checks first and may run zero times; do-while checks last and always runs at least once.
  • Every loop needs a start, a check and a step that moves toward the finish line.
  • Reach for while when you don't know the count in advance: doubling to the Moon took 42 rounds, and 27 needed 111 steps to reach 1.
  • Reach for do-while for menus, input validation and games.
  • break leaves a loop; continue skips to the next round.
  • Infinite loops come from a missing step, a step in the wrong direction, or waiting for an exact decimal.

Next, meet the counting specialist in The For Loop, make decisions inside your loops with The If Statement, and loop over real data with C++ Arrays.

Learning the C++ programming language? How about doing it with One Hour a Day.

Thanks for reading!

Know someone who would enjoy this? Send it their way.

More articles

Read next

Comments

Be kind and specific. Comments with links from new accounts appear after a moderator reviews them.