Step 1 of 5 · Reading · ~4 min
Learn
Control Flow
Loops
A loop runs the same block of code again and again while a condition holds. By the end of this lesson you can repeat work a counted number of times, keep a running result across passes, and pick the right loop shape for a problem.
The counted for loop
for (int k = 1; k <= 4; ++k) {
std::cout << k << " ";
}
// prints: 1 2 3 4
The header has three parts separated by semicolons: the init (int k = 1, runs once), the condition (k <= 4, checked before every pass; the loop stops the first time it is false), and the step (++k, runs after every pass). k exists only inside the loop.
The condition decides the last value. k < 4 visits 1 2 3; k <= 4 visits 1 2 3 4. Say to yourself whether the upper bound is included, then pick the operator on purpose.
Write ++k, not k++, in the header. For an int both do the same thing. Postfix k++ has to keep a copy of the old value to hand back; that is free for an int but not for the iterators and class types you meet later. Nobody reads the old value in a loop header, so ++k says what you mean.
Keeping a result across passes
To combine values over many passes, declare a variable before the loop, give it a starting value, and update it inside the body. Here the loop multiplies 1 through 5, which gives 5 factorial:
int m = 5;
long long product = 1; // start at 1 for a product
for (int k = 1; k <= m; ++k) {
product *= k;
}
std::cout << "5! = " << product << "\n"; // 5! = 120
Trace it: product goes 1, 1, 2, 6, 24, 120. Three details carry the whole pattern:
- Declared outside. A variable declared inside the braces is created fresh on every pass and is gone after the loop, so it cannot remember anything.
- Right start value. 0 for a sum, 1 for a product. Starting a product at 0 prints 0 forever.
- Wide enough type. With
int product, the product of 1 through 13 is already 6227020800, past theintlimit of 2147483647. Signed overflow is undefined behavior; in practice you get a garbage number such as1932053504.long longholds up to about 9.2 * 10^18.
The print goes after the closing brace. Put it inside the body and you print every partial value (1, 2, 6, 24, 120) instead of one answer.
while and do-while
int value = 4096;
int halvings = 0;
while (value > 1) { // condition first: may run zero times
value /= 2;
++halvings;
}
std::cout << halvings << "\n"; // 12
Use while when you do not know the pass count in advance, only a stopping condition. do { ... } while (cond); checks at the end, so its body always runs at least once. break leaves a loop immediately; continue skips to the next pass.
A stray semicolon, as in for (...); or while (...);, gives the loop an empty body. The block below it then runs once, after the loop. -Wall warns about it.
Range-based for
std::string word = "cab";
for (char c : word) {
std::cout << c << '-';
}
// prints: c-a-b-
Read for (char c : word) as "for each char c in word". There are no indices, so there is no off-by-one. Each c is a copy. Write for (char& c : word) to change the real characters, and for (const auto& x : things) to read without copying. That last form is the everyday idiom, and it works on the std::vector coming in a later lesson. Use the counted for when the position itself matters.
Common mistakes
<instead of<=. The loop stops one value early. A sum of 1 through 5 comes out as 10 instead of 15.intaccumulator. Small inputs look fine, but the sum of 1 through 65536 is 2147516416, just past theintlimit. Aninttotal prints-2147450880.- Printing inside the loop. For 5 you print
1 3 6 10 15on five lines instead of the single line15. - Starting the counter at 0 with
<.0..n-1adds 0 and misses n, so you get the same wrong 10 for 5.
Your exercise
Print the sum of every whole number from 1 up to and including N. The starter already reads n; you write the running total, the loop, and one print after it. The mistake to watch for is the accumulator type: large N overflows an int.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…