Functions (chap 5)

This chapter contains the two most difficult concepts in the course. I haven’t decided for sure when to teach the second one.

The Concept of a Function (Module)

A series of instructions with one specific purpose is called a module. A module can be written directly in the main program or we can write a function that consists of the module. Then, in the main body of the program, a single instruction (known as the call to the function) utilizes this function in a particular situation. We’ve used functions like sqrt(), abs(), ceil, etc.. We don't know what the statements inside the sqrt() module look like--we just issue a call to tell sqrt() what to work on. For example, we could write the following in a main program:

y = sqrt(w);

This call tells the sqrt() function to find the square root of w. This extra information sent to the function is called a parameter (in the example, it is w).

S’pose we want to call a function that isn’t in the library. We have to write it ourselves. As our first example of a programmer-defined function, let's write a function called triple() that takes an integer and triples it. This is too simple to be a useful function (in fact, the function shell is much larger than the actual instructions), but it is a good first example.

// function to return three

// times the parameter numb

int triple(int numb) // function header

{

return 3 * numb;

}

A C program is made up of functions. There is always one function called main().The computer starts executing with main.There are many features of the function that are familiar to us from main():

• every function should have a comment describing what task it is designed to accomplish.

  • the function header. Among other things, the header gives the identifier that is used to call the function from the main program. Identifier names for functions are lowercase like variable identifier ones.
  • The function header, just like the main program header, does not end in a semicolon.

• The header starts with a data type which indicates the type of answer returned by the function; in this case, the answer returned has type double. In all of our previous programs, the main program header started with the data type int, to indicate that the main program would return an integer value.

  • the function has a pair of braces surrounding the body

• The final statement of the function, called a return statement, returns this value to the program that called the function. In our previous programs, the main program always used a return 0; The value returned should match the data type in the function header

In addition to these familiar features, there is something new. Inside the parentheses is a list of identifiers with their associated data type.This is the parameter list. These values are sent to the function so it can do its task.

There could also be a declaration of local variables, which isn’t needed here.

The code above for the function is called the function definition because it defines to the compiler what this function means. This explains why the function header does not end in a semicolon, since it is just part of the function definition.

Main might look like this:

// triple_print.cpp main program to test function triple

#include <stdlib.h>

#include <iostream>

using namespace std;

//leave space for prototype

int main()

{

int a;

a = 5;

b = triple(a);

cout < "Original value is " < a < " and its triple is " < b < endl;

system("PAUSE");

return 0;

}

Function Terminology

When a function is called, the value of the variable in the parentheses (a) is matched up with the variable in the parentheses in the function header (numb). So numb actually gets the value of a. The name numb in the function is simply a place holder for the value that we want tripled, a.

• This place holder numb is called a formal or dummy parameter of the function. The word "dummy" is more descriptive of its role as a place holder, but "formal parameter" is the more common term.

• The object that we want to find the triple of (a) is called the actual or real parameter; sometimes it is called an argument. It can be a variable, a constant, or an expression.

The names of the formal and actual parameters do not have to match exactly, although, if by chance they do, there is no problem. On the other hand, the data types for both parameters should match. In the main program, we use the actual name of the parameter, but in the function, we use only the formal parameter name.

Tracing a Call to the Function

• Execution begins in the main program. First, a is assigned the value 5.

• The value of a is sent to the function triple(). The main program temporarily stops, and the function begins to execute. The first step of every function call is to match the value of the formal and actual parameters.

• In the function, the formal parameter numbgets the value of the actual parameter a.

• When the function executes the return statement, it stops execution, returns a value, and control passes to the main program. The function always returns to the point where it was called. For clarity, you might put parentheses around the value to be returned if it’s not a simple expression. In that case, the return statement looks like this:

return (3 * numb);

• When we get back to the main program, the answer returned by the function is assigned to the variable b and printed.

Function Prototype

Inside the function, the compiler can do type checking based on the function header. As the compiler goes through a program, it hits the call to a function before it sees the definition. Afunction prototype gives the compiler the information it needs to perform type checking in the main program. The function prototype contains the type of answer returned by the function, the name of the function, plus the number and type of the parameters. It comes before main and ends in a semicolon. This is the function declaration.NOTE TO ME: add int triple(int numb);

If we include this function prototype, the compiler knows exactly what to expect when we call triple() from the main program:

• The function will return an answer of type int.

• The name of the function is triple().

• The function will expect to receive one parameter of type int.

Header Files and Location of Function Prototypes

  • The function prototype must appear before the call to the function.
  • Put it above the header of the main program directly beneath the #include .This way it is visible to the entire program. (We will see that one function cannot look inside another.)
  • It’s a declaration so it ends with a semicolon

When using a programmer-defined function, it is the programmer's responsibility to include the function prototype explicitly. In the case of a library function, the function prototype is contained in a header file. We have inserted header files into our programs by using a #include directive such as #include <iostream>. This directive tells the preprocessor to include the header file iostream.h at this point in the program.

A header file contains function prototypes for library functions. The header files iostream and cmath contain function prototypes for the functions in these two portions of the standard library. By including the compiler directives for these header files, we allow our programs to use the appropriate library functions.

The header files for iostream and cmath are always placed at the beginning, above the main program, so that the prototypes they contain can be accessed from anywhere. Placing the prototype for a programmer-defined function directly beneath these header files puts it in the same position as the prototypes for the functions from the C++ library. By the time the main program calls the function, the prototype must have been seen. Therefore, the main program and any other functions in the file can access the function correctly.

Notes:

  • Alternate form of prototype.I don’t like it.

int triple(int numb);

This form gives a name, in addition to a data type, to the function's parameter. In this case, the name in the prototype matches the formal parameter name in the function header, but that is not necessary. Actually, any name can be used (or no name at all). . The important point is the type: int.

  • With certain compilers, it may be possible to omit the function prototype, but I strongly recommend that you always include it.

See triple_print.cpp. Notes:

  • Trace carefully.
  • the main program calls the function several times. However, it never gets confused about which call it is executing or where to return the answer.
  • There is also a variable numb in main. They are distinct.
  • the actual parameter does not have to be a variable (although things are easier if it is). The actual parameter can be an expression which is evaluated to obtain a value; this value is then sent to the function for the formal parameter.

Driver

Before adding a complicated function to a long program, we take it for a “test drive.” Write a main program which calls the function prints the results, called a driver program.

Advantages of Functions:

  • Code it once and call it many times, possibly in multiple programs
  • Concentrate on the logic of main and postpone the details (top down programming—stepwise refinement).Separate the mechanics of a function from its use in a larger program. Come back to it after a night’s sleep or get an expert(accountant) to write it.
  • Can produce program quickly by assigning programs to several programmers. Point to students in class. They don’t even have to know each others variable names.
  • Each module can be debugged and tested independently using a driver program. When we believe that it works, it can be trusted as a step in a larger process.
  • Facilitates maintenance. Can modify one function (e.g. tax laws) without affecting the whole program.
  • Functions are often defined in separate files and #included when needed (or more advanced—compiled together)

Function style:

  • Single well defined task
  • Comment saying what it does
  • Not more than one page long
  • We tend to put functions after main and so need prototype before main.
  • Main should only call other functions

RULES: (Scope) Functions are selfish. They do not share variables.

  • A function is always allowed to refer to its formal parameters. For example, triple() refers to numb, and sign() refers to x. In addition, if the function declares one or more local variables, it can refer to them. For example, sign() refers to answer. However, a function cannot refer to any variables which are declared in the main program.
  • Similarly, a local variable declared within a function can be used only within that function. It is impossible for the main program to reference a function's local variable. In fact, a local variable can have the same name as a variable within the main program. When the function is executing, a reference to that name means the variable declared in the function; when the main program is operating, a reference to that name means the variable declared in the main program.

Parameter Transmission by Value

During execution of the program, the function is sent the value of the actual parameter, and this value is placed in the formal parameter. This method of sending a parameter to a function is called passing a parameter by value or parameter transmission by value. In C++, parameters are passed by value.When a parameter is passed by value, if there is a change in the formal parameter inside the function, the value of the corresponding actual parameter does not change.

See compute.cpp

The Use of Local Variables within a Function: the Function sign()

Let's write a function called sign() that does the following: Given a real number x, if x is 0, the function returns 0; if x is positive, it returns 1; if x is negative, it returns 1. This is called the sign function, since it tells us the sign (but not the value) of the original number.

// return the sign of the parameter x: +1, 0, or 1

int sign(double x)

{

int answer;

if (x == 0)

answer = 0;

if (x > 0)

answer = 1;

if (x < 0)

answer = 1;

return answer;

}

The variable (answer) is declared within the function. Such a variable is called a local variable of the function. Each time the function is called, it has a new temporary storage location with this name. In this function, answer holds the value that is eventually returned. The function can be written without a local variable. We are purposely writing it this way to illustrate the concept.

The function prototype for this function can look like:

int sign(double);

Formal Parameter as a Local Variable

It is sometimes useful to view the formal parameter in a function as a local variable. The match-up of actual and formal parameters can then be interpreted as an assignment statement which is executed just before the function starts. For example, consider the function sign() from Example 5-3. The formal parameter inside sign() is called x. That example has a main program containing several calls to the function. For the last function call, the actual parameter is the constant -5. Therefore, we can view the following assignment as occurring just before the function starts to execute:

x = -5;

In general, if the actual parameter is the expression expr, and the formal parameter is called param, then the match-up can be interpreted as the following:

param = expr;

Note that expr gives an initial value to param, but they are in fact separate storage locations. If the formal parameter param changes inside the function, the corresponding actual parameter in the main program does not.

CAUTION

Since a formal parameter in a function is a local variable, the function cannot have a local variable and a formal parameter with the same name. However, either of them can repeat a name used in the main program.

Using Multiple return Statements

There are many other ways to write the body of the function sign(). As we mentioned earlier, you can avoid the local variable answer. As soon as you determine a value for the function, you can return it.

// return the sign of the parameter x: +1, 0, or 1

int sign(double x)

{

if (x == 0)

return 0;

if (x > 0)

return 1;

if (x < 0)

return -1;

}

A function can return only one value. Therefore, this function seems to be illegal because of the three return statements. However, the function is valid because only one statement is used on any one call to sign(). Since only one of the three if conditions is true for each x value, only one value is returned by the function. Control returns to the main program and the rest of the function is ignored. In other words, the last statement executed in the function will be the return statement from one of these three if statements, depending upon the particular value stored in x. In fact, if we reach the third if, its question must be true. Therefore, the third if can be replaced by the following:

return -1;

STYLE

Many people avoid multiple return statements. They think it is better to have one way to enter a function (at the top), and one way to exit (via a single return statement at the bottom). On the other hand, some people prefer multiple return statements to avoid extra local variables. You should be comfortable with both techniques.

A Function with Several Parameters: the Function max3()

Spose we want to find the largest of 3 integers. We will write a function called max3() with three parameters. The header for the function mentions each of these parameters, giving it a name and data type.

See max_of_3.cpp

Notes:

  • Look at max3()
  • Just as the header mentions three parameters, so, too, does the function prototype.
  • RULE: Can’t factor the type. Each parameter has its own type.
  • RULE: the formal and actual parameters are matched according to position,x to a, y to b, z to c. Names are ignored. Inside the function, a gets the value 3, b gets the value 5, and c gets the value 7. • The first if condition is false, so the local variable maxsofar is set to 5 (the value of b). The second if condition is false, so the local variable maxsofar is assigned 7 (the value of c). This value is returned to the main program, the function stops execution, and the main program resumes. Back in the main program, ans is given the value 7, which is the correct answer for the maximum of 3, 5, and 7.
  • Our next call reiterates several points.
  • the answer returned from a function can be part of an expression or printed.
  • the actual parameter can be a constant or an expression; in fact it can be an

expression whose value depends upon the value returned by a call to another function.

  • A complicated expression like the one printed by this program is evaluated from the inside out. In this case, the function max3()is called, and then the answer returned is multiplied by 3. Note that the call to max3() has three arguments or parameters. See Figure 5-8.

•The first actual parameter is the expression p + 2, which has the value 10; this is sent to max3() as the value of the first formal parameter a.