CodeRigor

LESSON

Write functions and finish a complete program

Name a step as a function with typed parameters and a return value, then combine variables, input, decisions and loops into one complete interactive program.

You have been calling functions since lesson 3: std::getline and std::stoi are functions that someone else wrote. In this lesson you write your own. Then you put everything from this unit together in one complete program.

A function is a named step

A function is a block of code with a name. Writing the block and giving it its name is called defining the function. Running it, by writing the name followed by round brackets, is called calling it.

C++
#include <iostream>

void print_line() {
    std::cout << "--------------------\n";
}

int main() {
    print_line();
    std::cout << "Results\n";
    print_line();
}

This prints a line of dashes, then Results, then another line of dashes.

Lines 3 to 5 define a function named print_line. The block between its braces is called the function's body. The word void in front of the name says that this function does a job and hands nothing back; the next sections show functions that do hand something back.

Three things to notice:

  • Defining a function does not run it. The program still starts at the first statement of main. The body of print_line runs only when a statement calls it, and it runs again for every call.
  • When the body is finished, the program carries on from the place of the call.
  • The definition is written above main. The compiler reads a program from the top, and it must have seen a function before it meets a call to it.

Functions let you give a step a name, write it once and use it many times. A program made of well-named steps is much easier to read than one long list of statements.

Parameters let a function work on different values

A function becomes more useful when the caller can give it values to work with. A parameter is a variable written in the round brackets of the definition, with its type. Each call supplies a value for it, and that value is called an argument.

C++
#include <iostream>
#include <string>

void greet(std::string name) {
    std::cout << "Hello, " << name << "!\n";
}

int main() {
    greet("Ada");
    greet("Grace");
}

This prints Hello, Ada! and Hello, Grace!. In the first call the parameter name holds "Ada"; in the second it holds "Grace". A parameter exists only inside its function's body.

A function can have several parameters, separated by commas. Each needs its own type, and a call must supply one argument for each, in the same order.

return hands a value back

Most functions work something out and give the answer back to the caller. Such a function names the type of its answer in front of its name, where print_line had void, and uses a return statement to hand the answer back. The answer is called the return value, and its type is the function's return type.

C++
#include <iostream>

int area(int width, int height) {
    return width * height;
}

int main() {
    int floor = area(3, 4);
    std::cout << floor << '\n';
    std::cout << area(2, 5) + 1 << '\n';
}

This prints 12 and 11. A call to a function that returns a value can be used anywhere a value can: stored in a variable, as on line 8, or used inside a calculation, as on line 10.

One call, there and back
start / 5 ⇄ code
The arguments travel into the parameters, the body runs, and return sends one value back to the place of the call.
One call, there and back
The arguments travel into the parameters, the body runs, and return sends one value back to the place of the call.

return also ends the function at once. Statements after a return that has run are not reached.

main is a function too

You can now read the frame you have been copying since lesson 1. int main() defines a function named main with no parameters and the return type int. It is special in one way: you never call it yourself. Starting the program calls it.

The int that main returns goes to whatever started the program, and 0 means "finished without problems". main is the only function where C++ lets you leave the return statement out; reaching the closing brace of main counts as return 0;. That is why none of the programs in this unit wrote it.

The void program() in the exercises is an ordinary function of the kind you have seen in this lesson: no parameters, nothing handed back. The tests have a main of their own, and it calls program.

Print or return?

Sending a value to std::cout and returning it are different things. Printing puts characters on the screen for a person to read. Returning hands a value to the code that called the function, which can then calculate with it, test it or print it.

C++
#include <iostream>

void show_double(int n) {
    std::cout << n * 2 << '\n';
}

int get_double(int n) {
    return n * 2;
}

int main() {
    show_double(5);
    int big = get_double(5) + 1;
    std::cout << big << '\n';
}

This prints 10 and 11. show_double(5) shows 10 on the screen and gives nothing back, so there is nothing to add 1 to: show_double(5) + 1 would not compile. get_double(5) shows nothing, but hands back a 10 that the program goes on to use.

Prefer functions that return their answer. The caller can always print a returned value, but a value that was only printed cannot be used for anything else.

Functions can contain everything you know

A body can use variables, decisions and loops, as main does.

C++
#include <iostream>
#include <string>

std::string size_name(int length) {
    if (length < 10) {
        return "small";
    }
    if (length < 100) {
        return "medium";
    }
    return "large";
}

int sum_up_to(int n) {
    int total = 0;
    for (int i = 1; i <= n; ++i) {
        total += i;
    }
    return total;
}

int main() {
    std::cout << size_name(42) << '\n';
    std::cout << sum_up_to(4) << '\n';
}

This prints medium and 10. In size_name, 42 is not under 10, so the first return is skipped; 42 is under 100, so the second return runs and the function ends there. Because return leaves the function, no else is needed. Every path through a function with a return type must end in a return.

A complete program

Here is a small but complete interactive program: a three-question quiz on the 7 times table. It uses every idea in this unit. It reads input, so run it in the C++ playground with three answers, such as 21, 40 and 63, as standard input.

C++
#include <iostream>

// Asks one question. Returns true when the answer was right.
bool ask(int number) {
    int answer = 0;
    std::cout << "What is 7 x " << number << "? ";
    std::cin >> answer;
    return answer == 7 * number;
}

int main() {
    int score = 0;
    for (int i = 1; i <= 3; ++i) {
        if (ask(i * 3)) {
            std::cout << "Correct.\n";
            score += 1;
        } else {
            std::cout << "Not quite.\n";
        }
    }
    std::cout << "Score: " << score << " out of 3\n";
}

With those three answers typed on a keyboard, the session is:

Text
What is 7 x 3? 21
Correct.
What is 7 x 6? 40
Not quite.
What is 7 x 9? 63
Correct.
Score: 2 out of 3
How the quiz program is put together
start / 6 ⇄ code
main holds the loop, the decision and the running score. The function ask holds the prompt, read and compare for one question, and returns true or false.
How the quiz program is put together
main holds the loop, the decision and the running score. The function ask holds the prompt, read and compare for one question, and returns true or false.

Read the program as its parts: ask is one prompt, read and compute step, with a name; main is a loop with a decision and a running total inside it. Every larger program is built the same way, from small named steps.

Three errors you will meet

Calling a function above its definition.

C++
#include <iostream>

int main() {
    std::cout << area(3, 4) << '\n';
}

int area(int width, int height) {
    return width * height;
}
Text
main.cpp: In function 'int main()':
main.cpp:4:18: error: 'area' was not declared in this scope
    4 |     std::cout << area(3, 4) << '\n';
      |                  ^~~~

The same message as for a misspelt variable, and for the same reason: on line 4 the compiler has not yet been told about the name area. Move the definition of area above main.

The wrong number of arguments.

C++
#include <iostream>

int area(int width, int height) {
    return width * height;
}

int main() {
    std::cout << area(3) << '\n';
}
Text
main.cpp: In function 'int main()':
main.cpp:8:22: error: too few arguments to function 'int area(int, int)'
    8 |     std::cout << area(3) << '\n';
      |                  ~~~~^~~
main.cpp:3:5: note: declared here
    3 | int area(int width, int height) {
      |     ^~~~

The error line says which call is wrong (line 8) and quotes the function as int area(int, int): it takes two int values. The line marked note adds helpful detail to the error above it, here the place where the function was defined. The call needs two arguments.

Forgetting return. This program compiles, with two warnings:

C++
#include <iostream>

int area(int width, int height) {
    width * height;
}

int main() {
    std::cout << area(3, 4) << '\n';
}
Text
main.cpp: In function 'int area(int, int)':
main.cpp:4:11: warning: statement has no effect [-Wunused-value]
    4 |     width * height;
      |     ~~~~~~^~~~~~~~
main.cpp:5:1: warning: no return statement in function returning non-void [-Wreturn-type]
    5 | }
      | ^

Line 4 works out 12 and then throws it away, because nothing says return. "Non-void" means "with a return type other than void": the function promised an int and reaches its closing brace without handing one back. C++ does not define what such a program does. It may print a meaningless number or stop with a crash. Treat both of these warnings as errors and fix them: return width * height;.

What you can do now, and where to go next

You can define a function with typed parameters, return a result from it, and build a complete interactive program from variables, input, decisions, loops and functions. That is the core of programming in any language. The capstone build asks you to write one more complete program: a number-guessing game.

When you have finished it, the next unit of this course is the next step. It starts at values, references and const. Expect a change of pace: from there the course moves quickly, and its next lessons use parts of C++ that this unit did not reach, such as std::vector (a list of values) and struct and class (types you define yourself). Read slowly, run every example, and use the videos under Watch & read on each lesson when a term is new.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →

Starts at 'User defined functions' (2:03:10) and continues through 'Return keyword' to 2:16:42: defining a function, parameters and arguments, and returning a value. The chapter before it (1:59:05) builds a number guessing game, like this lesson's capstone.