Learning pathOriginal reference
Lesson 2 of 12

Return, print, and start fresh

Use return values, void actions, early exits, and local scope deliberately.

Returning is different from printing

return value; sends a value back to the caller. std::cout writes output. A call that returns 12 does not display 12 unless a statement explicitly prints it. A caller can store a result, compare it, or use it in another calculation.

A return exits the current function immediately, even when it appears inside a loop. break exits only the innermost loop or switch, while continue starts the next loop iteration. Every reachable result-producing path of an ordinary non-void helper must return a value.

C++23
// Complete C++23 program. Input: two integers in [-10^9, 10^9].
#include <iomanip>
#include <iostream>
double average(int a, int b) {
    long long total = 1LL * a + b;
    return static_cast<double>(total) / 2.0;
}
int main() {
    int a = 0, b = 0;
    std::cin >> a >> b;
    std::cout << std::fixed << std::setprecision(1)
              << average(a, b) << '\n';
}

Actions can return void

void means there is no result value to store. A helper named printLine may print deliberately; a helper named isEven should normally return a bool so the caller chooses what to do with the decision. A void helper can leave early with return; or reach its closing brace.

An empty parameter list is valid. void printWelcome() needs no arguments, while int readChoice() could take no arguments and still return a value. Parameter count and return type are separate decisions.

Scope and lifetime are different

Scope describes where a name can be used. A counter declared in a for-loop header belongs to that loop. A variable named total inside a helper is separate from a variable named total in main.

Lifetime describes when an object exists. An ordinary local total initialized to zero starts again on each call; it does not remember the previous answer. Return a result by value when needed. Returning a reference to a destroyed local object cannot keep it alive.

C++23
// Complete C++23 program. No input; output: 6 6 100
#include <iostream>
int sumTo(int n) { // Contract: 0 <= n <= 1000.
    int total = 0;
    for (int i = 1; i <= n; ++i) total += i;
    return total;
}
int main() {
    int total = 100;
    std::cout << sumTo(3) << ' ' << sumTo(3) << ' ' << total << '\n';
}

Value or reference?

The helper executes x += 10. Compare the caller’s value before and after the call.

Caller before5
Inside helper15
Caller after5

The parameter is a copy. Changing it leaves the caller’s variable untouched.

Guided simulation · Change the inputs to test your understanding.

Pause & predict

A helper returns 12. main executes calculate(); and discards the result. What must be printed?

Choose an answer
Try it yourself

Turn the idea into code

Implement clampToRange(value, low, high) for low ≤ high. Return the nearest endpoint for an outside value; otherwise return the original value. Test 17 3 10, both endpoints, and a negative interval.

Give me a hint

Use two early returns for values outside the range; the remaining path is already inside.

Show the explained solution

The three cases cover all permitted inputs. Each performs a fixed number of comparisons, so the helper uses O(1) time and auxiliary space.

C++23
// Complete C++23 program. Input: value low high, with low <= high.
#include <iostream>
int clampToRange(int value, int low, int high) {
    if (value < low) return low;
    if (value > high) return high;
    return value;
}
int main() {
    int value = 0, low = 0, high = 0;
    std::cin >> value >> low >> high;
    std::cout << clampToRange(value, low, high) << '\n';
}

Your notes

Ready for the next idea?

Mark complete when you can explain it yourself.

From a problem to a programIdentify the input, output, and constraints, then translate a small plan into C++.Variables, types, and remembered valuesChoose a representation, initialize it, and understand what assignment really changes.Arithmetic without surprisesPredict division and remainder, widen before multiplication, and format decimal answers.Conditions and logical decisionsBuild exclusive categories, combine comparisons, and protect operations with short-circuit logic.Optional: other ways to chooseRecognize switch for exact choices and the conditional operator for choosing a value.For loops: make repetition preciseTrace initialization, condition, body, and update—and avoid an extra iteration.While, do-while, and stopping rulesChoose a loop from its stopping condition and read the exact input format.Break, continue, and early answersDistinguish leaving a loop from skipping one iteration, without losing required input.Five patterns worth understandingUse sums, counts, best-so-far candidates, products, and flags to process a stream.Nested loops: rows and columnsTranslate a shape into two loop roles and count the total work.Take a number apart, one digit at a timeUse remainder and division to process decimal digits, including zero.Multiple cases and a debugging mindsetCombine the patterns, isolate each case, and test the boundaries that can break your idea.Arrays: give every value a placeUnderstand indices, initialization, capacity, active length, and the first safe array loop.Scan, count, search, and compareDistinguish values from positions and preserve the exact tie rule a problem asks for.Change a sequence without losing itUpdate, copy, compare, reverse, and inspect neighbours using the correct bounds.Matrices: think in two coordinatesTraverse tables, total rows and columns, inspect diagonals, and protect grid neighbours.Characters become stringsSeparate characters from numbers, then safely inspect and edit managed text.Read the text the problem actually givesChoose words or full lines, preserve empty cases, and reset only the state that needs it.Scan text: count, filter, transformBuild a result from matching characters without losing leading zeros or skipping shifted text.Join, compare, and find textLearn content comparison, lexicographical order, substring counts, and the not-found sentinel.