# Courses/CS 2114/Lab Manual/Functions and Value Parameters

# Functions and Value Parameters

## Introduction

This lab will introduce the purpose and structure of functions, a fundamental notion in programming.

Topics Covered in this Lab:

- the structure of C++ functions
- function prototypes
- parameter declaration
- default parameter values
- return values and types
- scoping in functions
- function overloading
Questions Answered in this Lab:

- What is the purpose of a function?
- How is a function declared and called?
- What is meant by a local variable?
- What is a default parameter value?
- What does it mean to
returna value?- What is an overloaded function?
Demonstrable Skills Acquired in this Lab:

- ability to modularize a program using functions
- knowledge of function structures, prototypes and scoping
- knowledge of return values
- knowledge of default parameter values and function overloading

## Divide-and-Conquer Problem Solving

In the programs of this course to date, the single function `main`

has sufficed to express the solution to the problem at hand. When problems become more complex, such a strategy will lead to a large, complicated program that is difficult to understand. The divide-and-conquer strategy for problem solving calls for the initial problem to be broken down into a series of sub-problems, the detailed solutions of which will be taken up later. This approach is a practical way of not only programming, but problem solving in general. For instance, if a car were needed to get to work, one might list the following steps that must be performed in order to get that car and then be able to drive it.

- shop for the car
- purchase the car
- license the car

These steps must be followed in this order; it makes no sense to license a car that has not been purchased, for example. But these steps are not detailed enough to specify how to carry out each of them. That is the nature of the divide-and-conquer strategy; detail is delayed until a later time in order to keep the focus on the initial, larger problem. Each sub-problem of the original problem will eventually be solved in its own turn in the same fashion. When developing a programmed solution, each sub-problem becomes a *function*.

Functions represent one of the most important concepts in program construction. They allow higher level problem solving to be mirrored in programs; when a problem is broken down into sub-problems, corresponding functions may be written to carry out the individual tasks. These naturally smaller functions are more easily written and understood.

## Library Functions

The C++ standard library contains a wide assortment of pre-written functions ready for use in other programs. Collections of these functions are stored together in specific libraries; a program which uses a particular function must specify a `#include`

preprocessor directive for the library defining it. Functions for mathematical operations such as square root, sine, cosine, logarithm and power are stored in the *cmath* library; programs using these functions must include the *cmath* library, just as programs using `cout`

and `cin`

must include the *iostream* library.

Start a program in file spFunctions1Tutorial.cpp; add the following to function `main` to make use of the square root function `sqrt` . Be sure to include the `cmath` library. |

| ||

```
double x = 5;
cout << "sqrt(x): " << sqrt(x) <<endl;
``` |

The value `2.23607`

should be displayed when the program is run.

Another useful function, `rand`

, generates a pseudo-random number between 0 and `RAND_MAX`

, a constant defined along with the `rand`

function in the `cstdlib`

library. The numbers are pseudo-random in that they follow a sequence from a *seed* planted with a call to function `srand`

. To illustrate, add the following to function `main`

. Be sure to include *cstdlib*; there is no need for a `using`

statement.

Execute the program and verify that the same sequence of eight random numbers appears twice. Change one of the seeds and verify that two different sequences result. Change both seeds to another new value and verify that new but equal sequences are produced.

| ||

In real programs it is usually not desirable to generate the Modern C++ (beginning with C++11) also provides a better library specifically designed for generating random numbers. The |

## User-Defined Functions

Each program to this point in the course has utilized one user-defined function, `main`

; consider its basic format.

| ||

```
int main (void)
{
// body
return 0;
} // end function main
``` |

Function `main`

follows the format used by most functions.

| ||

```
returnType functionIdentifier (parameter list)
{
// body
return returnValue; // returnValue must be of returnType
} // end function functionIdentifier
``` |

The *return type* of function `main`

is `int`

; correspondingly, the *return value* of `main`

is zero. The return value is communicated back to the caller of a function. In the case of `main`

, the caller is outside the scope of the program itself and so need not be discussed here. Not all functions will return a value, more on this later. The *parameter list* is another means of communication, but it can flow to, as well as from, the function. Function `main`

utilizes no parameter list communication; keyword `void`

explicitly indicates this.

A program may consist of an arbitrarily large number of user-defined functions. A console application must have one function named `main`

as this is where the linker sets up execution to start. (Console applications utilize "console" input and output with `cin`

and `cout`

, respectively.) Add the following to the program before function `main`

.

| ||

```
void writeRandoms8 (void)
{
cout << "function writeRandoms8\n";
for (int i = 1; i <= 8; i++)
cout << i << "\t" << setw(6) << rand() << endl;
return;
} // end function writeRandoms8
``` |

Compare this function with the outline of function `main`

above. Note that the keyword `void`

is used here in two contexts, first to indicate nothing will be returned and second to explicitly indicate an empty parameter list. Corresponding to the `void`

return type, the `return`

statement includes no value. (The `return`

statement is not strictly required in situations like this, but it does serve to document the end of the function.) Extend function `main`

with a call to this function.

| ||

```
writeRandoms8 ();
``` |

Execute the program and verify that it works as expected.

Function `writeRandoms8`

illustrates the mechanics of functions, but it is not really practical in and of itself. In fact, function `rand`

, whose results lie between 0 and `RAND_MAX`

, is of less use than it might be; problems of a statistical nature are typically concerned with probabilities on the range from zero to one. If the results of `rand`

are divided by `RAND_MAX`

, probabilities are produced. Consider a function which will do precisely that.

| ||

```
double rand01 (void)
{
return static_cast <double> (rand()) / RAND_MAX;
}
``` |

Compare the return type and return value of this function to those of `writeRandoms8`

. Add the function definition for `rand01`

(shown above) to your program just below the definition of `writeRandoms8`

. Then, extend function `main`

so that it invokes this function eight times and displays the results on the screen.

## Function Prototypes

Each identifier in a C++ program appears in one of two contexts, *definition* or *usage*. It stands to reason that the definition of an identifier must precede its usage; otherwise, the compiler will not know what to do with it. Functions `writeRandoms8`

and `rand01`

were defined before function `main`

was defined; thus the definitions of the identifiers `writeRandoms8`

and `rand01`

precede their usage. Since functions can call one another, the definition-usage ordering becomes more complicated as the number of functions increases. Function *prototypes* may be used as *pre-definitions* of functions to allow for any ordering of the function definitions themselves.

A function prototype is essentially the function header followed by a semicolon (rather than a left curly brace, as in a function definition). Add prototypes for functions `writeRandoms8`

and `rand01`

to the program immediately following the programs's `#include`

preprocessor directives.

| ||

```
void writeRandoms8 (void);
double rand01 (void);
``` |

Move the full definitions of these functions so that they follow function `main`

. Execute the program to verify that everything is in place. Without the prototypes, the usages of the function identifiers would precede their respective definitions.

Note that the identifers for functions `writeRandoms8`

and `rand01`

each now appear in the program three times; each occurrence has a different purpose. The first occurrence is in the *function prototype*, telling the compiler what this function will look like but not how it will do its work. The second occurence is within function `main`

in a *function call*; when the program's execution reaches this point it will jump from there to begin execution of the function. The third and final occurrence is after function `main`

in the *function header* of the *function definition*; this is followed immediately by the *function body*.

## Value Parameters

As stated earlier, a function's *parameter list* can be used to pass information to the function. The previous examples had empty (`void`

) parameter lists as they could perform their tasks without additional information. Consider again function `writeRandoms8`

; it will now be modified to write as many random numbers as requested. Begin by making copies of the function prototype and definition. Change the copies of the prototype and function header as follows.

| ||

```
void writeRandoms (int n) // was writeRandoms8 (void)
``` |

Next, change the function body's `cout`

statement to reflect the new name of the function and modify the body's `for`

loop to count from 1 to `n`

, rather than 1 to 8. Finally, extend function `main`

to include a call to the new function as follows.

| ||

```
srand (2231);
int k = 8;
writeRandoms (k);
``` |

Execute the program and verify that the same eight pseudo-random numbers are generated (following the same seed) by the new function.

The parameter list with which the function is called (within function `main`

) is referred to as the *actual* parameter list; the list with which the function is defined is the *formal* parameter list. **When a function is called, memory is allocated for each variable in the formal parameter list, and the value of the corresponding actual parameter is then copied into it.** For example, calling function `writeRandoms`

creates a new variable `n`

into which the value of `k`

, 8, is copied. Variable `n`

, like every other variable encountered so far, is of the *automatic storage class*; as such, it "lives and dies" within the curly braces in which it is defined. In this case, `n`

is associated with the curly braces of function `writeRandoms`

; when execution reaches the end of the function, the memory of variable `n`

is released and is no longer accessible. Variable `k`

, having been defined within the curly braces of function `main`

, still exists and will do so until function `main`

reaches its conclusion.

Incidentally, the compiler reads only the *types* specified in a prototype parameter list; any identifiers present are ignored. Change function `writeRandom`

's prototype list `(int n)`

to `(int)`

and recompile the program to verify that this is so. Typically, the presence of identifiers is helpful in describing the nature of the function's parameter list.

## Default Parameter Values

As it stands now, each call to function `writeRandoms`

must provide a parameter indicating how many random numbers are to be displayed. It is possible to specify a *default* value which will be used should no parameter be given. Change the prototype of `writeRandom`

so that it reads as follows.

| ||

```
void writeRandoms (int n = 5); // default parameter value
``` |

(Again, the identifier `n`

in the parameter list may be omitted.) Next, extend function `main`

with the following.

| ||

```
writeRandoms (); // force use of default parameter value
``` |

Finally, modify the function header of `writeRandoms`

definition as follows.

| ||

```
void writeRandoms (int n /* =5 */)
``` |

Note that this last modification is not strictly required, as it inserts a comment only; however, it serves as a useful reminder in the function definition.

Execute the program and verify that the call to `writeRandoms`

with an empty parameter list does indeed display five random numbers.

## Using a Formal Parameter to Obtain a Return Value

A function will now be developed which computes a return value based on its formal parameter. Recall from algebra that the expressions and are equivalent. Recall also that logarithms are exponents; specifically, is the exponent to which is raised to get .

From this, the following can be seen to hold true.

One of the fundamental properties of logarithms states that the logarithm of a number raised to a power is equivalent to that power multiplied by the logarithm of the number.

By combining these facets of logarithms, square roots can also be determined using logarithms.

Use the `cmath`

functions `pow`

and `log10`

to write a function `sqrtViaLogs`

which implements this formula; add it and its prototype to the program. Extend function `main`

with a `for`

loop to use this function to display the square roots of the integers 1 through 9, one to a line; be sure that the index of the for loop, which is being passed to the square root function, is an integer.

## Testing

In order to see that the results of function `sqrtViaLogs`

are correct, it might be a good idea to display the results of parallel calls to standard function `sqrt`

. Copy the `for`

loop from the previous section and adjust it to display two square roots per line, one using `sqrtViaLogs`

and the other using `sqrt`

.

Execute the program and verify that the results of both square roots are identical.