C++ Loops Masterclass: for, while, do-while, Range-for,
이 글의 핵심
Choose the right loop: counted for, condition-driven while, do-while for at-least-once, range-based for, break/continue rules, off-by-one, and floating-point loop pitfalls. Complete guide with practical examples.
The for Loop
The for loop packages initialization, condition, and increment together — ideal when you know the iteration count or range up front:
#include <iostream>
int main() {
// Count from 1 to 5
for (int i = 1; i <= 5; i++) {
std::cout << i << ' ';
}
std::cout << '\n'; // 1 2 3 4 5
// Count down
for (int i = 5; i >= 1; i--) {
std::cout << i << ' ';
}
std::cout << '\n'; // 5 4 3 2 1
// Step by 2
for (int i = 0; i < 10; i += 2) {
std::cout << i << ' ';
}
std::cout << '\n'; // 0 2 4 6 8
}
The three parts of the for header are all optional. Any of them can be empty:
int i = 0;
for (; i < 5; ) {
std::cout << i << ' ';
i++;
}
// Same as while (i < 5) { ...; i++; }
The while Loop
while is best when the number of iterations isn’t known in advance:
#include <iostream>
int main() {
// Read until the user enters 0
int n;
int sum = 0;
std::cout << "Enter numbers (0 to stop): ";
while (std::cin >> n && n != 0) {
sum += n;
}
std::cout << "Sum: " << sum << '\n';
}
// Retry until success
int attempts = 0;
bool connected = false;
while (!connected && attempts < 3) {
connected = tryConnect();
attempts++;
}
if (!connected) {
std::cerr << "Failed after 3 attempts\n";
}
The do-while Loop
do-while runs the body first, then checks the condition. Use it when the body must run at least once:
#include <iostream>
int main() {
// Input validation — show prompt, read, then check
int value;
do {
std::cout << "Enter a positive number: ";
std::cin >> value;
} while (value <= 0);
std::cout << "You entered: " << value << '\n';
}
// Menu-driven program
int choice;
do {
std::cout << "1. Play 2. Options 3. Quit\nChoice: ";
std::cin >> choice;
switch (choice) {
case 1: play(); break;
case 2: showOptions(); break;
}
} while (choice != 3);
Range-Based for (C++11)
For iterating containers, range-based for is the clearest option:
#include <vector>
#include <string>
#include <iostream>
int main() {
std::vector<int> nums = {3, 1, 4, 1, 5, 9};
// By value — copies each element (fine for ints)
for (int n : nums) {
std::cout << n << ' ';
}
// By const reference — no copy, read-only (use for large types)
std::vector<std::string> words = {"hello", "world"};
for (const std::string& w : words) {
std::cout << w << ' ';
}
// By reference — can modify elements
for (int& n : nums) {
n *= 2; // double each element
}
// auto — let the compiler deduce the type
for (const auto& w : words) {
std::cout << w.size() << ' ';
}
}
Rule of thumb for element type in range-for:
- Small types (int, double): use
autoor the type by value - Large types (string, vector, struct): use
const auto&— avoids copy - When modifying elements: use
auto&
Choosing the Right Loop
| Loop | Best when |
|---|---|
for | Number of iterations known; index needed; iterating 0..n |
while | Condition-driven; could run 0 times; EOF or retry patterns |
do-while | Body must run at least once; input validation; menu loops |
Range-for | Iterating a container; no index needed |
break and continue
break exits the innermost enclosing loop (or switch):
std::vector<int> nums = {2, 5, 3, 8, 1, 7};
// Find first number > 6
for (int n : nums) {
if (n > 6) {
std::cout << "Found: " << n << '\n'; // Found: 8
break; // stop searching
}
}
continue skips the rest of the current iteration:
// Print only odd numbers
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) continue; // skip even numbers
std::cout << i << ' ';
}
// 1 3 5 7 9
break and continue only affect the innermost enclosing loop. They cannot break out of multiple levels at once.
Nested Loops
// Multiplication table
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 5; j++) {
std::cout << i * j << '\t';
}
std::cout << '\n';
}
Exiting Nested Loops
C++ has no labeled break. Options:
Option 1: Use a function and return
// Cleanest approach
std::pair<int,int> findTarget(const std::vector<std::vector<int>>& grid, int target) {
for (int r = 0; r < (int)grid.size(); r++) {
for (int c = 0; c < (int)grid[r].size(); c++) {
if (grid[r][c] == target) {
return {r, c}; // return exits both loops
}
}
}
return {-1, -1}; // not found
}
Option 2: Flag variable
bool found = false;
for (int r = 0; r < rows && !found; r++) {
for (int c = 0; c < cols && !found; c++) {
if (grid[r][c] == target) {
found = true;
result = {r, c};
}
}
}
Option 3: goto (use sparingly)
// Only with team agreement — goto is clearer than complex flag logic here
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (grid[r][c] == target) goto done;
}
}
done:
Common Mistakes
Off-by-One Errors
The most common loop bug. Use half-open ranges [0, n) consistently:
std::vector<int> v = {10, 20, 30, 40, 50};
// WRONG: i <= v.size() — goes one past the end (undefined behavior)
for (int i = 0; i <= (int)v.size(); i++) {
std::cout << v[i] << '\n'; // v[5] is out of bounds
}
// CORRECT: i < v.size()
for (int i = 0; i < (int)v.size(); i++) {
std::cout << v[i] << '\n';
}
// Better: use range-for when index not needed
for (int x : v) {
std::cout << x << '\n';
}
Stray Semicolon
for (int i = 0; i < 10; i++); // semicolon — empty loop body
{
std::cout << "runs once after the loop\n"; // NOT inside the loop!
}
// Correct:
for (int i = 0; i < 10; i++) {
std::cout << i << '\n';
}
Floating-Point Loop Counter
// WRONG — floating-point accumulation error may miss the exit condition
for (double x = 0.0; x != 1.0; x += 0.1) {
// x may never equal exactly 1.0 due to rounding
// loop may run forever or stop at wrong value
}
// CORRECT — integer counter, compute float from it
for (int i = 0; i < 10; i++) {
double x = i * 0.1; // 0.0, 0.1, 0.2, ..., 0.9
// process x
}
Modifying a Container While Iterating
std::vector<int> v = {1, 2, 3, 4, 5};
// WRONG — erasing invalidates the iterator
for (auto it = v.begin(); it != v.end(); ++it) {
if (*it % 2 == 0) {
v.erase(it); // iterator is now invalid!
}
}
// CORRECT — erase returns next valid iterator
for (auto it = v.begin(); it != v.end(); ) {
if (*it % 2 == 0) {
it = v.erase(it); // it now points to next element
} else {
++it;
}
}
// v: {1, 3, 5}
Practical Examples
Prime Number Sieve
#include <vector>
#include <iostream>
std::vector<int> sieve(int n) {
std::vector<bool> is_prime(n + 1, true);
is_prime[0] = is_prime[1] = false;
for (int i = 2; i * i <= n; i++) {
if (is_prime[i]) {
for (int j = i * i; j <= n; j += i) {
is_prime[j] = false;
}
}
}
std::vector<int> primes;
for (int i = 2; i <= n; i++) {
if (is_prime[i]) primes.push_back(i);
}
return primes;
}
int main() {
auto primes = sieve(50);
for (int p : primes) std::cout << p << ' ';
// 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
}
Fibonacci Sequence
#include <iostream>
int main() {
int n = 10;
long long a = 0, b = 1;
for (int i = 0; i < n; i++) {
std::cout << a << ' ';
long long next = a + b;
a = b;
b = next;
}
// 0 1 1 2 3 5 8 13 21 34
}
Key Takeaways
forfor known iteration counts and ranges;whilefor condition-driven loops;do-whilewhen body runs at least once- Range-based
foris the cleanest way to iterate containers — useconst auto&for large types breakexits the innermost loop only;continueskips to the next iteration- Off-by-one: use
i < n(noti <= n) with zero-based indexing; range-for avoids this entirely - Floating-point counters: use integer counters and compute the float — never test
float == floatas a loop condition - Nested loop exit: refactor into a function with
return, or use a flag variable - Modifying containers while iterating: use
it = v.erase(it)pattern or use algorithms likestd::remove_if
Frequently Asked Questions (FAQ)
Q. When would I use this in practice?
A. Choose the right loop: counted for, condition-driven while, do-while for at-least-once, range-based for, break/continue …
Q. What should I read before this?
A. Follow the previous article or related articles links at the bottom of each post to learn in sequence. See the C++ series index for the full picture.
Q. Where can I study this more deeply?
A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.
Related Articles (Internal Links)
Other articles related to this topic.
- C++ if / else / switch: Conditionals, Pitfalls, and switch
- C++ Functions: Parameters, Return Values, Overloading, and
- C++ STL vector | ‘배열보다 편한’ 벡터 완벽 정리 [실전 예제]
Keywords Covered in This Article (Related Search Terms)
This article covers C++, for, while, loops, control flow.