Writing C+ + Functions
Computers never become bored. They perform the same input, output, and computations your program requires—for as long as you want them to do it. You can take advantage of their repetitive natures by looking at your programs in a new way: as a series of small routines that execute whenever you need them, however many times you require.
This chapter approaches its subject a little differently than the previous chapters do. It concentrates on teaching you to write your own functions, which are modules of code that you execute and control from the mai n() function. So far, the programs in this book have consisted of a single long function called mai n() . As you learn here, the mai n() function’s primary purpose is to control the execu- tion of other functions that follow it.
This chapter introduces the following:
-
The need for functions
-
How to trace functions
-
How to write functions
-
How to call and return from functions
Chapter 16 ♦ Writing C++ Functions
This chapter stresses the use of structured programming, some- times called modular programming. C++ was designed in a way that the programmer can write programs in several modules rather than in one long block. By breaking the program into several smaller routines (functions), you can isolate problems, write correct pro- grams faster, and produce programs that are easier to maintain.
C++ programs should consist of many small functions.
Function Basic s
When you approach an application that has to be programmed, it is best not to sit down at the keyboard and start typing. Rather, first think about the program and what it is supposed to do. One of the best ways to attack a program is to start with the overall goal, then divide this goal into several smaller tasks. You should never lose sight of the overall goal, but think also of how individual pieces can fit together to accomplish such a goal.
When you finally do sit down to begin coding the problem, continue to think in terms of those pieces fitting together. Don’t approach a program as if it were one giant problem; rather, continue to write those small pieces individually.
This does not mean you must write separate programs to do everything. You can keep individual pieces of the overall program together—if you know how to write functions. Then you can use the same functions in many different programs.
C++ programs are not like BASIC or FORTRAN programs. C++ was designed to force you to think in a modular, or subroutine- like, functional style. Good C++ programmers write programs that consist of many small functions, even if their programs execute one or more of these functions only once. Those functions work together to produce a program quicker and easier than if the program had to be written from scratch.
EXAMPLE
Breaking Down Problem s
If your program does very much, break it into several func- tions. Each function should do only one primary task. For example, if you were writing a C++ program to retrieve a list of characters from the keyboard, alphabetize them, then print them to the screen, you could—but shouldn’t—write all these instructions in one big mai n() function, as the following C++ skeleton (program outline) shows:
mai n( )
{
/ / :
/ / C++ code t o r et r i eve a li st of char act er s.
/ / :
/ / C++ code t o al phabet i ze t he char act er s.
/ / :
/ / C++ code t o pr i nt t he al phabet i zed li st on- scr een.
/ / :
r et ur n 0;
}
This skeleton is not a good way to write this program. Even
though you can type this program in only a few lines of code, it is much better to begin breaking every program into distinct tasks so this process becomes a habit to you. You should not use mai n() to do everything—in fact, use mai n() to do very little except call each of the functions that does the actual work.
A better way to organize this program is to write a separate function for each task the program is supposed to do. This doesn’t mean that each function has to be only one line long. Rather, it means you make every function a building block that performs only one distinct task in the program.
The following program outline shows you a better way to write the program just described:
mai n( )
{
get l ett er s() ; / / Call s a f unct i on t o r et r i eve t he number s. al phabet i ze() ; / / Call s a f unct i on t o al phabet i ze
/ / l ett er s.
Chapter 16 ♦ Writing C++ Functions
pr i nt l ett er s() ; / / Call s a f unct i on t o pr i nt l ett er s
/ / on- scr een.
r et ur n 0; / / Ret ur ns t o t he oper at i ng syst em.
}
get l et t ers( )
{
/ / :
/ / C++ code t o get a li st of char act er s.
/ / :
r et ur n 0; / / Ret ur ns t o mai n() .
}
al phabet i ze( )
{
/ / :
/ / C++ code t o al phabet i ze t he char act er s
/ / :
r et ur n 0; / / Ret ur ns t o mai n() .
}
pr i nt l et t ers( )
{
/ / :
/ / C++ code t o pr i nt t he al phabet i zed li st on- scr een
/ / :
r et ur n 0; / / Ret ur ns t o mai n() .
}
The program outline shows you a much better way of writing
this program. It takes longer to type, but it’s much more organized. The only action the mai n() function takes is to control the other functions by calling them in a certain order. Each separate function executes its instructions, then returns to mai n() , whereupon mai n() calls the next function until no more functions remain. The mai n() function then returns control of the computer to the operating system.
Do not be too concerned about the 0 that follows the r et ur n statement. C++ functions return values. So far, the functions you’ve seen have returned zero, and that return value has been ignored.
EXAMPLE
Chapter 19, “Function Return Values and Prototypes,” describes how you can use the return value for programming power.
Themai n() function is usually a calling function that controls the remainder of the program.
The first function called mai n() is what you previously used to hold the entire program. From this point, in all but the smallest of programs, mai n() simply controls other functions that do the work. These listings are not examples of real C++ programs; instead,
they are skeletons, or outlines, of programs. From these outlines, it is easier to develop the actual full program. Before going to the keyboard to write a program such as this, know that there are four distinct sections: a primary function-calling mai n() function, a key- board data-entry function, an alphabetizing function, and a print- ing function.
Never lose sight of the original programming problem. (Using the approach just described, you never will!) Look again at the mai n() calling routine in the preceding program. Notice that you can glance at mai n() and get a feel for the overall program, without the remain- ing statements getting in the way. This is a good example of structured, modular programming. A large programming problem is broken into distinct, separate modules called functions, and each function performs one primary job in a few C++ statements.
More Function Basic s
Little has been said about naming and writing functions, but you probably understand much of the goals of the previous listing already. C++ functions generally adhere to the following rules:
-
Every function must have a name.
-
Function names are made up and assigned by the program- mer (you!)
following the same rules that apply to naming
Chapter 16 ♦ Writing C++ Functions
variables: They can contain up to 32 characters, they must begin with a letter, and they can consist of letters, numbers, and the underscore (_ ) character.
-
All function names have one set of parentheses immediately following
them. This helps you (and C++) differentiate them from variables. The parentheses may or may not contain something. So far, all such parentheses in this book have been empty (you learn more about functions in Chapter 18, “Passing Values”).
-
The body of each function, starting immediately after the closing
parenthesis of the function name, must be enclosed by braces. This means a block containing one or more state- ments makes up the body of each function.
Although the outline shown in the previous listing is a good example of structured code, it can be improved by using the under- score character (_ ) in the function names. Do you see how get_l et t ers() and pr i nt _l ett er s() are much easier to read than are get l ett er s() and pr i nt l et t ers( ) ?
All programs must have amai n() function.
The following listing shows you an example of a C++ function. You can already tell quite a bit about this function. You know, for instance, that it isn’t a complete program because it has no mai n() function. (All programs must have a mai n() function.) You know also that the function name is cal c_i t because parentheses follow this name. These parentheses happen to have something in them (you learn more about this in Chapter 18). You know also that the body of the function is enclosed in a block of braces. Inside that block is a
EXAMPLE
smaller block, the body of a whil e loop. Finally, you recognize that the
r et ur n statement is the last line of the function.
cal c_i t ( i nt n)
{
/ / Funct i on t o pr i nt t he squar e of a number . i nt squar e;
whil e ( squar e <= 250)
{ squar e = n * n;
cout << “ The squar e of “ << n << “ i s “ << squar e << “ \ n” ;
n++; } / / A bl ock i n t he f unct i on.
r et ur n 0;
}
Calling and Returnin g Functions
You have been reading much about “function calling” and “returning control.” Although you might already understand these phrases from their context, you can probably learn them better through an illustration of what is meant by a function call.
A function call is like a temporary program detour.
A function call in C++ is like a detour on a highway. Imagine you are traveling along the “road” of the primary function called mai n() and then run into a function-calling statement. You must temporarily leave the mai n() function and execute the function that was called. After that function finishes (its r et ur n statement is
Chapter 16 ♦ Writing C++ Functions
reached), program control reverts to mai n() . In other words, when you finish a detour, you return to the “main” route and continue the trip. Control continues as mai n() calls other functions.
A complete C++ program, with functions, will make this concept clear. The following program prints several messages to the screen. Each message printed is determined by the order of the functions. Before worrying too much about what this program does, take a little time to study its structure. Notice that there are three functions defined in the program: mai n() , next _f un() , and t hi r d_f un() . A fourth function is used also, but it is the built-in C++ pr i ntf () function. The three defined functions appear sequentially. The body of each is enclosed in braces, and each has a r et ur n statement at its end.
As you will see from the program, there is something new following the #i ncl ude directive. The first line of every function that mai n() calls is listed here and also appears above the actual function. C++ requires these prototypes. For now, just ignore them and study the overall format of multiple-function programs. Chapter 19, “Func- tion Return Values and Prototypes, ” explains prototypes.
/ / C16FUN1. CPP
/ / The f oll owi ng pr ogr am ill ust r at es f unct i on call s. #i ncl ude <st di o. h>
next _f un() ; / / Pr ot ot ypes. t hi rd_f un( ) ;
mai n() / / mai n() i s al ways t he f i r st C++ f unct i on execut ed.
{
pr i ntf (“ Fi r st f unct i on call ed mai n() \ n”) ;
next _f un() ; / / Second f unct i on i s call ed her e.
t hi r d_f un() ; / / Thi s f unct i on i s call ed her e. pr i ntf (“ mai n() i s compl et ed \ n”) ; / / All cont r ol
/ / r et ur ns her e.
EXAMPLE
r et ur n 0; / / Cont r ol i s r et ur ned t o
//t he oper at i ng syst em.
} / / Thi s br ace concl udes mai n() .
next _f un() / / Second f unct i on.
/ / Par ent heses al ways r equi r ed.
{
pr i ntf (“ I nsi de next _f un() \ n”) ; / / No var i abl es ar e
/ / def i ned i n t he pr ogr am.
r et ur n 0; / / Cont r ol i s now r et ur ned t o mai n() .
}
t hi r d_f un() / / Last f unct i on i n t he pr ogr am.
{
pr i ntf (“ I nsi de t hi r d_f un() \ n”) ;
r et ur n 0; / / Al ways r et ur n f r om all f unct i ons.
}
The output of this program follows:
Fi r st f unct i on call ed mai n() I nsi de next _f un()
I nsi de t hi r d_f un() mai n() i s compl et ed
Figure 16.1 shows a tracing of this program’s execution. Notice that mai n() controls which of the other functions is called, as well as the order of the calling. Control always returns to the calling function after the called function finishes.
To call a function, simply type its name—including the paren- theses—and follow it with a semicolon. Remember that semicolons follow all executable statements in C++, and a function call (some- times called a function invocation) is an executable statement. The execution is the function’s code being called. Any function can call any other function. In the previous program, mai n() is the only function that calls other functions.
Now you can tell that the following statement is a function call:
pr i nt _t ot al ( ) ;
Chapter 16 ♦ Writing C++ Functions
Figure 16.1. Tracing function calls.
Because pr i nt _t ot al is not a C++ command or built-in function name, it must be a variable or a written function’s name. Only function names end with the parentheses, so it must be a function call or the start of a function’s code. Of the last two possibilities, it must be a call to a function because it ends with a semicolon. If it didn’t have a semicolon, it would have to be the start of a function definition.
When you define a function (by typing the function name and its subsequent code inside braces), you never follow the name with a semicolon. Notice in the previous program that mai n() , next _f un() , and t hi r d_f un() have no semicolons when they appear in the body of the program. A semicolon follows their names only in mai n() , where these functions are called.
EXAMPLE
Examples
- Suppose
you are writing a program that does the following. First, it asks users for their departments. Then, if they are in accounting, they receive the accounting department’s report. If they are in engineering, they receive the engineering department’s report. Finally, if they are in marketing, they receive the marketing department’s report.
The skeleton of such a program follows. The code for mai n() is shown in its entirety, but only a skeleton of the other functions is shown. The swi t ch statement is a perfect function-calling statement for such multiple-choice selections.
/ / Skel et on of a depar t ment al r epor t pr ogr am. #i ncl ude <i ost r eam. h>
mai n( )
{
i nt choi ce;
do
{ cout << “ Choose your depar t ment f r om t he “ << “ f oll owi ng li st\ n” ;
cout << “ \t 1. Account i ng \ n” ; cout << “ \t 2. Engi neer i ng \ n” ; cout << “ \t 3. Mar ket i ng \ n” ;
cout << “ What i s your choi ce? “ ; ci n >> choi ce;
} whil e (( choi ce<1) | | ( choi ce>3)) ; / / Ensur e 1, 2,
/ / or 3 i s chosen.
swi t ch choi ce
{ case( 1) : { acct _r epor t () ; / / Call account i ng f unct i on.
Chapter 16 ♦ Writing C++ Functions
br eak; } / / Don’ t f all t hr ough. case( 2) : { eng_r epor t () ; / / Call engi neer i ng f unct i on.
br eak; }
case( 3) : { mt g_r epor t () ; / / Call mar ket i ng f unct i on. br eak; }
}
r et ur n 0; / / Pr ogr am r et ur ns t o t he oper at i ng
/ / syst em when f i ni shed.
}
acct _r epor t ( )
{
/ / :
/ / Account i ng r epor t code goes her e.
/ / :
r et ur n 0;
}
eng_repor t ( )
{
/ / :
/ / Engi neer i ng r epor t code goes her e.
/ / :
r et ur n 0;
}
mt g_repor t ( )
{
/ / :
/ / Mar ket i ng r epor t code goes her e.
/ / :
r et ur n 0;
}
The bodies of swi t ch statements normally contain function calls. You can tell that these case statements execute func- tions. For instance, acct _r epor t () ; (which is the first line of the first case ) is not a variable name or a C++ command. It is the name of a function defined later in the program. If users enter 1 at the menu, the function called acct _r epor t () executes. When it finishes, control returns to the first case
EXAMPLE
body, and its br eak statement causes the swi t ch statement to end. The mai n() function returns to DOS (or to your inte- grated C++ environment if you are using one) when its
r et ur n statement executes.
- In
the previous example, the mai n() routine is not very modular. It displays the menu, but not in a separate func- tion, as it should. Remember that mai n() does very little except control the other functions, which do all the work.
Here is a rewrite of this sample program, with a fourth function to print the menu to the screen. This is truly a modular example, with each function performing a single task. Again, the last three functions are shown only as skeleton code because the goal here is simply to illustrate function calling and returning.
/ / Second skel et on of a depar t ment al r epor t pr ogr am. #i ncl ude <i ost r eam. h>
mai n( )
{
i nt choi ce;
do
{ menu_pr i nt () ; / / Call f unct i on t o pr i nt t he menu. ci n >> choi ce;
} whil e (( choi ce<1) | | ( choi ce>3)) ; / / Ensur e 1, 2,
/ / or 3 i s chosen.
swi t ch choi ce
{ case( 1) : { acct _r epor t () ; / / Call account i ng f unct i on.
br eak; } / / Don’ t f all t hr ough. case( 2) : { eng_r epor t () ; / / Call engi neer i ng f unct i on.
br eak; }
case( 3) : { mt g_r epor t () ; / / Call mar ket i ng f unct i on. br eak; }
}
r et ur n 0; / / Pr ogr am r et ur ns t o t he oper at i ng syst em
/ / when f i ni shed.
}
menu_pr i nt ( )
{
Chapter 16 ♦ Writing C++ Functions
cout << “ Choose your depar t ment f r om t he f oll owi ng" " li st\ n” ;
cout << “ \t 1. Account i ng \ n” ; cout << “ \t 2. Engi neer i ng \ n” ; cout << “ \t 3. Mar ket i ng \ n” ;
cout << “ What i s your choi ce? “ ; r et ur n 0; / / Ret ur n t o mai n() .
}
acct _r epor t ( )
{
/ / :
/ / Account i ng r epor t code goes her e.
/ / :
r et ur n 0;
}
eng_repor t ( )
{
/ / :
/ / Engi neer i ng r epor t code goes her e.
/ / :
r et ur n 0;
}
mt g_repor t ( )
{
/ / :
/ / Mar ket i ng r epor t code goes her e.
/ / :
r et ur n 0;
}
The menu-printing function doesn’t have to follow mai n() . Because it’s the first function called, however, it seems best to define it there.
- Readability
is the key, so programs broken into separate functions result in better written code. You can write and test each function, one at a time. After you write a general outline of the program, you can list a bunch of function calls in mai n() , and define their skeletons after mai n() .
EXAMPLE
The body of each function initially should consist of a single r et ur n statement, so the program compiles in its skeleton format. As you complete each function, you can compile and test the program. This enables you to develop more accurate programs faster. The separate functions enable others (who might later modify your program) to find the particular function easily and without affecting the rest of the program.
Another useful habit, popular with many C++ programmers, is to separate functions from each other with a comment consisting of a line of asterisks (* ) or dashes (- ). This makes it easy, especially in longer programs, to see where a function begins and ends. What follows is another listing of the previous program, but now with its four functions more clearly separated by this type of comment line.
/ / Thi r d skel et on of a depar t ment al r epor t pr ogr am. #i ncl ude <i ost r eam. h>
mai n( )
{
i nt choi ce;
do
{ menu_pr i nt () ; / / Call f unct i on t o pr i nt t he menu. ci n >> choi ce;
} whil e (( choi ce<1) | | ( choi ce>3)) ; / / Ensur e 1, 2,
/ / or 3 i s chosen.
swi t ch choi ce
{ case( 1) : { acct _r epor t () ; / / Call account i ng f unct i on.
br eak; } / / Don’ t f all t hr ough. case( 2) : { eng_r epor t () ; / / Call engi neer i ng f unct i on.
br eak; }
case( 3) : { mt g_r epor t () ; / / Call mar ket i ng f unct i on. br eak; }
}
r et ur n 0; / / Pr ogr am r et ur ns t o t he oper at i ng syst em
/ / when f i ni shed.
}
/ / **** **** **** **** **** **** **** *** **** **** **** **** **** **** * menu_pr i nt ( )
Chapter 16 ♦ Writing C++ Functions
{
cout << “ Choose your depar t ment f r om t he f oll owi ng" " li st\ n” ;
cout << “ \t 1. Account i ng \ n” ; cout << “ \t 2. Engi neer i ng \ n” ; cout << “ \t 3. Mar ket i ng \ n” ;
cout << “ What i s your choi ce? “ ; r et ur n 0; / / Ret ur n t o mai n() .
}
/ / **** **** **** **** **** **** **** **** *** **** **** **** **** **** ** acct _r epor t ( )
{
/ / :
/ / Account i ng r epor t code goes her e.
/ / :
r et ur n 0;
}
/ / **** **** **** **** **** **** **** **** *** **** **** **** **** **** ** eng_repor t ( )
{
/ / :
/ / Engi neer i ng r epor t code goes her e.
/ / :
r et ur n 0;
}
/ / **** **** **** **** **** **** **** **** *** **** **** **** **** **** ** mt g_repor t ( )
{
/ / :
/ / Mar ket i ng r epor t code goes her e.
/ / :
r et ur n 0;
}
Due to space limitations, not all program listings in this book separate the functions in this manner. You might find, however, that your listings are easier to follow if you put these separating comments between your functions. The application in Appendix F, “The Mailing List Application,”
EXAMPLE
for example, uses these types of comments to separate its functions.
- You can execute a function more than once simply by calling it from
more than one place in a program. If you put a function call in the body of a loop, the function executes repeatedly until the loop finishes.
The following program prints the message C++ i s Fun! several times on-screen—forward and backward—using functions. Notice that mai n() does not make every function call. The second function, name_pr i nt () , calls the function named r ever se_pr i nt () . Trace the execution of this program’s cout s.
/ / Fil ename: C16FUN2. CPP
/ / Pr i nt s C++ i s Fun! sever al t i mes on- scr een. #i ncl ude <i ost r eam. h>
name_pr i nt ( ) ;
reverse_pr i nt ( ) ; one_per_l i ne( ) ;
mai n( )
{
i nt ct r ; / / To cont r ol l oops
f or ( ct r =1; ct r <=5; ct r ++)
{ name_pr i nt () ; } / / Call s f unct i on f i ve t i mes.
one_per _li ne() ; / / Call s t he pr ogr am’ s l ast
/ / f unct i on once.
r et ur n 0;
}
/ / **** **** **** **** **** **** **** **** *** **** **** **** **** **** ** name_pr i nt ( )
{
/ / Pr i nt s C++ i s Fun! acr oss a li ne, separ at ed by t abs. cout << “ C++ i s Fun!\t C++ i s Fun!\t C++ i s Fun!
\t C++ i s Fun!\ n” ;
cout << “ C++ i s F u n !\t C++ i s F u n ! “ << “ \t C++ i s F u n !\ n” ;
Chapter 16 ♦ Writing C++ Functions
r ever se_pr i nt () ; / / Call next f unct i on f r om her e.
r et ur n 0; / / Ret ur ns t o mai n() .
}
/ / **** **** **** **** **** **** **** **** *** **** **** **** **** **** ** reverse_pr i nt ( )
{
/ / Pr i nt s sever al C++ i s Fun! messages,
/ / i n r ever se, separ at ed by t abs.
cout << “ ! nuF si ++C\t! nuF si ++C\t! nuF si ++C\t\ n” ;
r et ur n 0; / / Ret ur ns t o name_pr i nt () .
}
/ / **** **** **** **** **** **** **** **** *** **** **** **** **** **** ** one_per_l i ne( )
{
/ / Pr i nt s C++ i s Fun! down t he scr een. cout << “ C++\ n \ ni \ ns\ n \ nF\ nu\ nn\ n!\ n” ; r et ur n 0; / / Ret ur ns t o mai n()
}
Here is the output from this program:
C++ i s |
Fun! |
C++ i s |
Fun! |
C++ |
i s |
Fun! |
C++ i s Fun! |
||
---|---|---|---|---|---|---|---|---|---|
C++ i |
s F u |
n ! |
C++ |
i |
s F | u |
n ! |
C++ i s F u n |
! |
! nuF si |
++C |
! nuF si |
++C |
! nuF |
si |
++C |
|||
C++ i s |
Fun! |
C++ i s |
Fun! |
C++ |
i s |
Fun! |
C++ i s Fun! |
||
C++ i |
s F u |
n ! |
C++ |
i |
s F | u |
n ! |
C++ i s F u n |
! |
! nuF si |
++C |
! nuF si |
++C |
! nuF |
si |
++C |
|||
C++ i s |
Fun! |
C++ i s |
Fun! |
C++ |
i s |
Fun! |
C++ i s Fun! |
||
C++ i |
s F u |
n ! |
C++ |
i |
s F | u |
n ! |
C++ i s F u n |
! |
! nuF si |
++C |
! nuF si |
++C |
! nuF |
si |
++C |
|||
C++ i s |
Fun! |
C++ i s |
Fun! |
C++ |
i s |
Fun! |
C++ i s Fun! |
||
C++ i |
s F u |
n ! |
C++ |
i |
s F | u |
n ! |
C++ i s F u n |
! |
! nuF si |
++C |
! nuF si |
++C |
! nuF |
si |
++C |
|||
C++ i s |
Fun! |
C++ i s |
Fun! |
C++ |
i s |
Fun! |
C++ i s Fun! |
||
C++ i |
s F u |
n ! |
C++ |
i |
s F | u |
n ! |
C++ i s F u n |
! |
! nuF si |
++C |
! nuF si |
++C |
! nuF |
si |
++C |
|||
C++ |
EXAMPLE
i s F
u n
!
Review Question s
The answers to the review questions are in Appendix B.
- True or false: A function should always include a r et ur n
statement as its last command.
-
What is the name of the first function executed in a C++ program?
-
Which
is better: one long function or several smaller functions? Why?
-
How do function names differ from variable names?
-
How can you use comments to help visually separate functions?
-
What
is wrong with the following program section?
cal c_i t ( )
{
cout << “ Gett i ng r eady t o cal cul at e t he squar e of 25 \ n” ;
sq_25()
{
cout << “ The squar e of 25 i s “ << ( 25* 25) ; r et ur n 0;
}
cout << “ That i s a bi g number ! \ n” ; r et ur n 0;
}
Chapter 16 ♦ Writing C++ Functions
- Is the following a variable name, a function call, a function
definition, or an expression?
scan_names( ) ;
- True or false: The following line in a C++ program is a function
call.
cout << “ C++ i s Fun! \ n” ;
Summary
You have now been exposed to truly structured programs. Instead of typing a long program, you can break it into separate functions. This method isolates your routines so surrounding code doesn’t clutter your program and add confusion.
Functions introduce just a little more complexity, involving the way variable values are recognized by the program’s functions. The next chapter (Chapter 17, “Variable Scope”) shows you how vari- ables are handled between functions, and helps strengthen your structured programming skills.