SovranCode
Modern C++ Lesson 14
Course contents50 available · 0 planned

Get a program running

01 · C++ Introduction: What Is C++?02 · How to Install a C++ Compiler and Set Up Your Editor03 · C++ Hello World: Your First Program Explained04 · How to Compile and Run C++ Programs05 · C++ Debugging: Warnings and Breakpoints

Work with values and input

06 · C++ Variables: Initialization and Scope07 · C++ Data Types: int, double and Type Conversion08 · C++ const, constexpr and auto Explained09 · C++ Operators: Arithmetic, Comparison and Logic10 · C++ User Input: cin, getline and Validation

Control flow and functions

11 · C++ Conditions: if, else if and else12 · C++ Switch Statement: Cases, break and default13 · C++ For Loop: Syntax and Examples14 · C++ While and Do-While Loops: Examples15 · C++ Functions: Parameters and Return Values

Strings and sequences

16 · C++ Strings: std::string with Examples17 · C++ Vector: std::vector with Examples18 · C++ Arrays: std::array and Bounds Checking19 · C++ Range-Based For Loop and Iterators20 · C++ Vector Practice: Build a Data Summary

Model data with classes

21 · C++ Structs and enum class Explained22 · C++ Classes and Objects: Encapsulation23 · C++ Constructors and Member Initialization24 · C++ Const Member Functions and Composition25 · C++ Copying Objects and the Rule of Zero

Lifetime and resource ownership

26 · C++ Object Lifetime, Destructors and RAII27 · C++ Pointers and References: nullptr and Borrowing28 · C++ unique_ptr: Smart Pointers and Ownership29 · C++ Move Semantics: std::move vs Copying30 · C++ string_view and span: Avoid Dangling Views

Containers and algorithms

31 · C++ map vs unordered_map: Lookup and Examples32 · C++ set, queue and stack: When to Use Each33 · C++ Lambda Expressions and STL Algorithms34 · C++ sort and binary_search: Rules and Complexity35 · C++20 Ranges: Views, filter and transform

Errors, files, and interfaces

36 · C++ optional and variant Explained37 · C++ Exceptions: try, catch and Safe Cleanup38 · C++ File Handling: Read and Write Text Files39 · C++ Input Parsing and Data Validation40 · C++ Polymorphism: Virtual Functions and Interfaces

Generic programming and quality

41 · C++ Templates: Function and Class Examples42 · C++20 Concepts and Template Constraints43 · C++ Unit Testing: Normal and Boundary Cases44 · C++ Sanitizers: Find Memory and Undefined Behavior Bugs45 · C++ Performance: Benchmark Before Optimizing

Build and deliver a complete application

46 · C++ Header Files and Translation Units47 · C++ CMake Tutorial: Build an Executable48 · C++ Dependencies and CTest: Automated Tests49 · C++ Multithreading: Threads and Data Races50 · C++ Command-Line Applications: Help and Release Checks
Modern C++50 available · 0 planned

Get a program running

01 · C++ Introduction: What Is C++?02 · How to Install a C++ Compiler and Set Up Your Editor03 · C++ Hello World: Your First Program Explained04 · How to Compile and Run C++ Programs05 · C++ Debugging: Warnings and Breakpoints

Work with values and input

06 · C++ Variables: Initialization and Scope07 · C++ Data Types: int, double and Type Conversion08 · C++ const, constexpr and auto Explained09 · C++ Operators: Arithmetic, Comparison and Logic10 · C++ User Input: cin, getline and Validation

Control flow and functions

11 · C++ Conditions: if, else if and else12 · C++ Switch Statement: Cases, break and default13 · C++ For Loop: Syntax and Examples14 · C++ While and Do-While Loops: Examples15 · C++ Functions: Parameters and Return Values

Strings and sequences

16 · C++ Strings: std::string with Examples17 · C++ Vector: std::vector with Examples18 · C++ Arrays: std::array and Bounds Checking19 · C++ Range-Based For Loop and Iterators20 · C++ Vector Practice: Build a Data Summary

Model data with classes

21 · C++ Structs and enum class Explained22 · C++ Classes and Objects: Encapsulation23 · C++ Constructors and Member Initialization24 · C++ Const Member Functions and Composition25 · C++ Copying Objects and the Rule of Zero

Lifetime and resource ownership

26 · C++ Object Lifetime, Destructors and RAII27 · C++ Pointers and References: nullptr and Borrowing28 · C++ unique_ptr: Smart Pointers and Ownership29 · C++ Move Semantics: std::move vs Copying30 · C++ string_view and span: Avoid Dangling Views

Containers and algorithms

31 · C++ map vs unordered_map: Lookup and Examples32 · C++ set, queue and stack: When to Use Each33 · C++ Lambda Expressions and STL Algorithms34 · C++ sort and binary_search: Rules and Complexity35 · C++20 Ranges: Views, filter and transform

Errors, files, and interfaces

36 · C++ optional and variant Explained37 · C++ Exceptions: try, catch and Safe Cleanup38 · C++ File Handling: Read and Write Text Files39 · C++ Input Parsing and Data Validation40 · C++ Polymorphism: Virtual Functions and Interfaces

Generic programming and quality

41 · C++ Templates: Function and Class Examples42 · C++20 Concepts and Template Constraints43 · C++ Unit Testing: Normal and Boundary Cases44 · C++ Sanitizers: Find Memory and Undefined Behavior Bugs45 · C++ Performance: Benchmark Before Optimizing

Build and deliver a complete application

46 · C++ Header Files and Translation Units47 · C++ CMake Tutorial: Build an Executable48 · C++ Dependencies and CTest: Automated Tests49 · C++ Multithreading: Threads and Data Races50 · C++ Command-Line Applications: Help and Release Checks
PREVIOUS LESSONC++ For Loop: Syntax and Examples
NEXT LESSONC++ Functions: Parameters and Return Values
C++ foundations · Lesson 14 About 60 min with practice

C++ While and Do-While Loops: Examples

Compare C++ while and do-while loops, trace condition timing, use break and continue safely, and build a menu that stops on quit, end-of-input or a strict attempt limit.

Before you begin

Complete for loops, conditions and input validation. Provide the entire input stream before running; the editor is not an interactive terminal.

What you will learn

  • Distinguish entry-tested and exit-tested repetition.
  • Identify progress and termination on every path.
  • Use break and continue without bypassing required state updates.
  • Handle quit, input exhaustion and attempt limits separately.
  • Test a bounded menu with valid and invalid commands.

Use while when continuation depends on changing state

A while loop checks its condition before every body execution. If the condition is initially false, the body executes zero times. It is a useful fit for work that continues while an input source supplies data or while some state remains unfinished. The loop does not make progress by itself: the body or condition must change the facts that eventually allow it to stop. Write that progress rule beside the continuation rule before coding.

Our menu processes at most three input lines. It stops earlier for quit or end-of-input. Unsupported commands consume attempts, because repeatedly sending invalid text must not create an unlimited session. These are three distinct reasons to stop, and the final message should identify the actual one. Merely writing while (true) and adding occasional breaks is not a complete termination design unless every relevant path is explained.

A for loop can express some of the same behavior, but a while loop keeps the continuation state prominent. Choose based on the work rather than searching for a universally best loop. For a fixed count of generated rows, the previous for loop makes initialization and update easy to inspect. For interactive state with several stop causes, an explicit condition and early stop checks can make the interface easier to understand.

A while loop tests before the first body, allowing zero executions. A do-while loop executes a body before its continuation test, giving at least one entry when reached. A bounded command loop also checks input exhaustion and quit on each attempt.
Condition timing changes whether an initially false condition permits the first body execution.
C++ PRACTICE RUNNER

Compare initially false conditions

Both conditions start false. The while body never runs; the do body prints once before checking its condition.

#include <iostream>
int main() {
    int whileCount{};
    while (whileCount < 0) { ++whileCount; }
    int doCount{};
    do {
        ++doCount;
    } while (doCount < 0);
    std::cout << "While entries: " << whileCount << '\n';
    std::cout << "Do entries: " << doCount << '\n';
    return 0;
}
TERMINAL OUTPUT
Predict the output, edit the source, then select Run code.

C++20 compiler runner: source and input are sent only when you press Run to this website's execution endpoint, not an external vendor. Local preview requires Docker and gcc:14; production requires a separately isolated execution service. Network is disabled; execution is limited to 3 seconds, compilation to 10 seconds, memory to 384 MB and output to 32 KB. Single-file programs only. Don't enter secrets. Edits reset on refresh; Copy your work to keep it.

Compare with the starter's expected output
While entries: 0
Do entries: 1

After editing inputs, calculate a new prediction; this reference describes only the starter.

do-while guarantees an entry, not valid data

The syntax is do { body } while (condition); with a final semicolon after the condition. That semicolon is required and differs from an accidental empty body created by writing while (condition); in an ordinary while loop. Read the whole construct rather than applying one punctuation rule everywhere. A do-while can be suitable when a prompt or menu must appear once before a continuation decision is available.

At least one body entry does not mean a valid operation is always safe on that entry. If the body indexes a collection, divides by a count, or reads a variable that has not yet been validated, do-while does not establish the required preconditions. Validate before the sensitive operation even when the loop has already begun. The choice of repetition syntax controls timing, not the validity of every instruction placed inside it.

A body can exit early through break or return before reaching the bottom condition. Therefore the useful claim is that the body is entered when execution reaches the do statement, not that every statement in it necessarily runs. The menu lab uses while because a fixed attempt cap and input exhaustion make an entry check natural. You do not need to force do-while into an interface merely because menus are commonly used to demonstrate it.

Identify what changes on every continuing path

For a countdown, remaining decreases until it reaches zero. For a bounded input session, attempts increases for each successfully read line. For a stream-driven loop, reading consumes new input or reports that none is available. Each design has a progress measure. If a branch returns to the same condition without changing any relevant state or consuming input, investigate whether it can repeat forever.

continue in a while loop skips the remaining body and returns directly to the condition. Unlike the counter-based for loop, there is no separate update expression that automatically runs afterward. If attempts is incremented below a continue, rejected commands may never consume an attempt. Put the required accounting before branches that continue, or choose another structure. This is a concrete control-flow bug, not an argument that continue is always bad.

Use small bounded tests rather than intentionally running an infinite loop to learn the symptom. Write a trace showing attempts before the condition, the read result, the command, the updated attempt count and the next action. A timeout in the automated tests is a safety net, not evidence that an otherwise unbounded program is correct. The source's termination argument should stand on its own.

C++ PRACTICE RUNNER

Advance state before a skipped action

attempt increments before continue. The second action is skipped, but the third attempt is still reached and the loop stops.

#include <iostream>
int main() {
    int attempt{};
    while (attempt < 3) {
        ++attempt;
        if (attempt == 2) { continue; }
        std::cout << "Action " << attempt << '\n';
    }
    std::cout << "Attempts: " << attempt << '\n';
    return 0;
}
TERMINAL OUTPUT
Predict the output, edit the source, then select Run code.

C++20 compiler runner: source and input are sent only when you press Run to this website's execution endpoint, not an external vendor. Local preview requires Docker and gcc:14; production requires a separately isolated execution service. Network is disabled; execution is limited to 3 seconds, compilation to 10 seconds, memory to 384 MB and output to 32 KB. Single-file programs only. Don't enter secrets. Edits reset on refresh; Copy your work to keep it.

Compare with the starter's expected output
Action 1
Action 3
Attempts: 3

After editing inputs, calculate a new prediction; this reference describes only the starter.

Input failure is a stop condition, not another command

getline can read a blank line successfully, or it can fail because the source ends. Those states are different. A blank command can be classified as unsupported and consume an attempt. End-of-input provides no fresh command to classify; the program should stop instead of reusing the previous string. Check the read before inspecting command so stale text never performs an action on a failed read.

Do not repeatedly clear an exhausted stream and hope a new line appears. For a noninteractive test, end-of-input is final. A terminal program may have a different recovery policy for an actual recoverable format error, but a line-based command interface avoids leaving numeric extraction failure in std::cin. The whole line either arrives or does not, and string comparisons determine whether the arrived command is known.

A serious input error is also distinct from ordinary end-of-input. Our lab checks bad() and returns failure for that condition, while normal input exhaustion prints Input ended and returns success for ending the session. That policy is documented rather than inferred from an empty command. Different applications may treat premature exhaustion as failure; what matters is choosing and testing a truthful status for the contract at hand.

C++ PRACTICE RUNNER

A quit signal leaves the current loop

quit is recognized on the second iteration. break leaves the loop but allows the final Stopped message to print.

#include <iostream>
int main() {
    int step{};
    while (step < 3) {
        ++step;
        if (step == 2) { break; }
        std::cout << "Work " << step << '\n';
    }
    std::cout << "Stopped at " << step << '\n';
    return 0;
}
TERMINAL OUTPUT
Predict the output, edit the source, then select Run code.

C++20 compiler runner: source and input are sent only when you press Run to this website's execution endpoint, not an external vendor. Local preview requires Docker and gcc:14; production requires a separately isolated execution service. Network is disabled; execution is limited to 3 seconds, compilation to 10 seconds, memory to 384 MB and output to 32 KB. Single-file programs only. Don't enter secrets. Edits reset on refresh; Copy your work to keep it.

Compare with the starter's expected output
Work 1
Stopped at 2

After editing inputs, calculate a new prediction; this reference describes only the starter.

Test all ways the session can finish

For the lab, send quit as the first line and confirm no status action is performed. Send status then quit and confirm one status report. Send an unsupported line, status and quit to verify rejection still consumes an attempt. Send three unsupported lines followed by status: the fourth line must not be processed. An attempt cap that ignores invalid commands is not the cap described by the requirement.

Also test an empty input source, status followed by end-of-input, and a final line without a newline delimiter. getline can successfully return characters from that last line even when it also reaches the end. Do not reject valid final text merely because eof becomes true after the read. Let the read's success determine whether the command exists, then check continuation on the next attempted read if the session has not already ended.

Loop correctness combines the action policy and the termination policy. A menu that produces correct status text but never stops on exhaustion is not complete. A menu that stops safely but misreports a quit as an attempt limit is also wrong. Keep exact transcripts, final statuses and attempt counts together in your evidence. This habit prepares you for later file-processing loops, where missing data and partial results must remain visible.

LOCAL TERMINAL COMMANDS

Compile the examples and your lab

The editors can compile complete single-file programs when the execution service is available. Provide input in the Standard input field before pressing Run. Alternatively save one program as main.cpp and use your installed C++20 compiler with these terminal commands.

macOS / Clang:
clang++ -std=c++20 -Wall -Wextra -Wpedantic main.cpp -o lesson
./lesson

Linux / GCC:
g++ -std=c++20 -Wall -Wextra -Wpedantic main.cpp -o lesson
./lesson

Windows Developer Command Prompt / MSVC:
cl /std:c++20 /EHsc /W4 main.cpp /Fe:lesson.exe
lesson.exe
APPLY THE CONCEPT

Independent lab

Create a text menu with status and quit commands. Process at most three successfully read lines, count unsupported lines, and report the actual reason for stopping.

Acceptance checklist

  • Read whole commands with getline and accept exact lowercase status or quit.
  • Increment attempts after a successful read, before any continue.
  • Print Ready for status and Unsupported for unknown or blank commands.
  • Stop for quit or normal end-of-input, with distinct messages.
  • After three non-quit commands print Limit reached and ignore later lines.
Need a hint?
  1. Read failure must not reuse a previous command.
  2. Return immediately for quit so it cannot be mislabeled as a limit exit.
  3. The cap measures successfully read lines, not only successful status actions.
C++ PRACTICE RUNNER

Write and run your lab

Build your own solution before revealing the reference. Use the input field for normal, boundary and invalid cases; this runner executes your program but does not grade it.

#include <iostream>
#include <string>
#include <sstream>
#include <limits>

int main() {
    // Implement the acceptance checklist above.
    return 0;
}

TERMINAL OUTPUT
Predict the output, edit the source, then select Run code.

C++20 compiler runner: source and input are sent only when you press Run to this website's execution endpoint, not an external vendor. Local preview requires Docker and gcc:14; production requires a separately isolated execution service. Network is disabled; execution is limited to 3 seconds, compilation to 10 seconds, memory to 384 MB and output to 32 KB. Single-file programs only. Don't enter secrets. Edits reset on refresh; Copy your work to keep it.

Your lab evidence and notes

Record predictions, actual output, commands and the cause of each repair. Code is plain text: this scratchpad does not execute or grade C++.

Loading local notes…

Review your acceptance checklist and quiz explanations before marking this lesson complete. This is self-review, not a grade or certification.

Reveal the explained lab solution
C++ PRACTICE RUNNER

Reference lab solution

Compare the reference with your own reasoning. Running this solution does not grade or complete the lesson.

#include <iostream>
#include <string>
int main() {
    int attempts{};
    while (attempts < 3) {
        std::string command;
        if (!std::getline(std::cin, command)) {
            if (std::cin.bad()) { std::cout << "Input error\n"; return 1; }
            std::cout << "Input ended\n";
            return 0;
        }
        ++attempts;
        if (command == "quit") { std::cout << "Goodbye\n"; return 0; }
        if (command != "status") { std::cout << "Unsupported\n"; continue; }
        std::cout << "Ready\n";
    }
    std::cout << "Limit reached\n";
    return 0;
}
TERMINAL OUTPUT
Predict the output, edit the source, then select Run code.

C++20 compiler runner: source and input are sent only when you press Run to this website's execution endpoint, not an external vendor. Local preview requires Docker and gcc:14; production requires a separately isolated execution service. Network is disabled; execution is limited to 3 seconds, compilation to 10 seconds, memory to 384 MB and output to 32 KB. Single-file programs only. Don't enter secrets. Edits reset on refresh; Copy your work to keep it.

Expected output

Unsupported
Ready
Goodbye

Every arrived line counts toward the bound, including rejected commands. continue cannot bypass the increment.

Quit and end-of-input have their own return paths. A serious stream error reports failure rather than pretending input ended normally.

If three ordinary or unsupported commands are processed, the condition becomes false and Limit reached prints once. A fourth line remains unprocessed.

Review before moving on

Explain the lesson's objectives in your own words, compare your lab evidence with the acceptance checklist, and keep the first failing case alongside your repair. Completing a page is not proof that every C++ feature or input is supported.

  • Distinguish entry-tested and exit-tested repetition.
  • Identify progress and termination on every path.
  • Use break and continue without bypassing required state updates.
  • Handle quit, input exhaustion and attempt limits separately.
  • Test a bounded menu with valid and invalid commands.

References and further reading

Original examples and exercises accompany these primary references. Tool-specific diagnostics and support depend on your installed version.

  • C++ draft: while statement
  • C++ draft: do statement
  • C++ draft: continue
KNOWLEDGE CHECK

Check your understanding

Answer all five questions, then review the explanations. Answers are not saved or synced; completion is a separate self-review choice.

01Which loop can execute zero times because its first condition is false?
02Where does continue go in a while loop?
03Why count an unsupported arrived line before continue?
04What should happen when the next getline fails at normal end-of-input?
05What does break leave in a simple while body?
PREVIOUS LESSONC++ For Loop: Syntax and Examples
NEXT LESSONC++ Functions: Parameters and Return Values
ON THIS PAGELearning objectivesUse while when continuation depends on changing statedo-while guarantees an entry, not valid dataIdentify what changes on every continuing pathInput failure is a stop condition, not another commandTest all ways the session can finishIndependent labReviewKnowledge checkReferences
Course overview