Chapter 6
Chapter 6
Chapter 6
Functions and an Introduction to Recursion
Objectives
• To construct programs modularly from functions
• To use common math library functions
• The mechanisms for passing data to functions and returning results
• To use random number generation
• How the visibility of identifiers is limited to specific regions of programs
• To write and use recursive functions
3
Introduction
• Experience has shown that the best way to develop and maintain a large
program is to construct it from small, simple pieces, or components
▫ This technique is called divide and conquer
• Emphasize using functions to facilitate the design, implementation,
operation and maintenance of large programs
4
Functions
• Functions are the building blocks of C++ programs
• There are several ways to return control to the point at which a function was
invoked
• If the function does not return a result (i.e., it has a void return type),
control returns when the program reaches the function-ending right brace,
or by execution of the statement
return;
• In the following we are going to implement a simple square (i.e.,
num*num) function
12
result = square(x);
Note: the function (square) is
cout << "The square of number " << x << " is " declared as int because it
<< result << endl;
returns a value “answer”
return 0;
}
14
int main(void)
{
int x = 5;
square(x);
cout << "The square of number " << x << " is " << result << endl;
return 0;
} Note: the function (square) is
void square(int num) declared as void because it
{ does not return a value.
result = num * num; (“result “is a global variable and
return; // return to the caller can be used by main function)
}
15
Function Prototypes
• A function prototype (also called a function declaration) tells the
compiler:
▫ the name of the function
▫ the type of data returned by the function
▫ the number of parameters the function expects to receive
▫ the types of those parameters and
▫ the order in which the parameters of those types are expected
18
19
Argument Coercion
• Promotion also occurs when the type of a function argument does not match the
parameter type specified in the function definition or prototype
• The following figure lists the arithmetic data types in order from “highest type” to
“lowest type.”
• Converting values to lower fundamental types can result in incorrect values
• Therefore, a value can be converted to a lower fundamental type only by explicitly
assigning the value to a variable of lower type or by using a cast operator
20
21
• where shift is equal to the first number in the desired range of consecutive integers
and scale is equal to the number of consecutive integers
39
#include <iostream>
#include <cstdlib> default: // did not win or lose
#include <ctime> cout << "continue" << endl;
break;
using namespace std; } // end switch
} // end main
int rollDice();
int main()
{ // function rollDice
srand(time(0)); int rollDice()
int sumOfDice = rollDice(); {
// pick random die values
switch( sumOfDice )
{ int die1 = 1 + rand() % 6; // first die roll
case 7: // win with 7 on first roll int die2 = 1 + rand() % 6; // second die roll
case 11: // win with 11 on first roll
cout << "won" << endl; int sum = die1 + die2; // compute sum of die
break; values
case 2: // lose with 2 on first roll
case 3: // lose with 3 on first roll // display results of this roll
case 12: // lose with 12 on first roll cout << "Player rolled " << die1 << " + " <<
cout << "lost" << endl; die2 << " = " << sum << endl;
break; return sum; // end function rollDice
} // end function rollDice
41
#include <iostream>
using namespace std;
int main()
{
enum Months { JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT,
NOV, DEC };
cout << MAR;
}
OUTPUT:
3
44
Storage Duration
Storage Duration
• The storage-class specifiers can be split into four storage durations:
▫ automatic, static, dynamic
Storage Duration
• Variables with automatic storage duration (continued):
▫ Created when program execution enters the block in which they’re defined
▫ Exist while the block is active
▫ Destroyed when the program exits the block (memory conservation)
47
Storage Duration
Static Storage Duration
• Keywords extern and static declare identifiers for variables with static storage
duration and for functions
▫ Exist from the point at which the program begins execution and until the program terminates
▫ Such a variable is initialized once when its declaration is encountered
Scope Rules
• The portion of the program where an identifier can be used is known as
its scope
Scope Rules
Block Scope
• Identifiers declared inside a block which begins at the identifier’s
declaration and ends at the terminating right brace } of the block in
which the identifier is declared
• Example: variables declared in FOR loops
52
Scope Rules
Function Scope
• Labels can be used anywhere in the function in which they appear, but cannot be
referenced outside the function body
Global Namespace Scope
• An identifier declared outside all functions (usually before main function)
53
#include <iostream>
using namespace std;
int sq();
Exercise:
int main() Static variable
{
int mul=1; int x=0;
for (int counter=1; counter <=5; counter++ )
{
cout << sq() << endl;
}
return 0;
}
int sq()
{
static int k=1; Now, remove static, would the code work as desired?
k=k*3;
return k;
}
54
55
56
57
58
59
Recursion
Recursion is the ability of a subprogram to call itself. It is an alternative
control structure to repetition (looping). Rather than use a looping
statement to execute a program segment, the program uses a selection
statement to determine whether to repeat the code by calling the
subprogram again or to stop the process
Base case: The case to which we have an answer
General case: The case that expresses the solution in terms of a call to
itself with a smaller version of the problem
69
Recursion
• A recursive function is a function that calls itself, either directly, or indirectly (through
another function)
• Recursive problem-solving approaches have a number of elements in common
▫ A recursive function is called to solve a problem
▫ If the function is called with a base case, the function simply returns a result
▫ If the function is called with a more complex problem that needs recursion, it divides the
problem into two conceptual pieces - a piece that the function knows how to do (base
case) and a piece that it does not know how to do (recursive)
▫ This new problem looks like the original, so the function calls a copy of itself to work on
the smaller problem—this is referred to as a recursive call and is also called the recursion
step
70
Recursion
• The recursion step often includes the keyword return, because its result will be
combined with the portion of the problem the function knew how to pass back the
result to the original caller, usually main function
• The recursion step executes while the original call to the function is still “open,” i.e.,
it has not yet finished executing
71
Recursion
Factorial
n · (n – 1) · (n – 2) · … · 1
Recursion
The factorial of a number is defined as the number times the product of all
the numbers between itself and 0:
n! = n * (n 1)!
Base case
Factorial(0) = 1 (0! is 1) (Factorial (0) is the base case)
General Case
Factorial(n) = n * Factorial(n-1) (Factorial (n) is the general case)
Because n is clearly getting smaller with each call, the base case is reached
73
Recursion
• Iterative Factorial
▫ The factorial of an integer, number, greater than or equal to 0, can be calculated iteratively
(non-recursively) by using a loop
• Recursive Factorial
▫ A recursive definition of the factorial function is arrived at by observing the following algebraic
relationship:
n! = n · (n – 1)!
74
Recursion
• Evaluating 5!
▫ The evaluation of 5! would proceed as shown in the following figure which illustrates how the
succession of recursive calls proceeds until 1! is evaluated to be 1, terminating the recursion
▫ Figure b, shows the values returned from each recursive call to its caller until the final value is
calculated and returned
75
76
Recursion
• Using a Recursive factorial Function to Calculate Factorials
• The following program uses recursion to calculate and print the factorials of the
integers 0 - 10
77
78
79
Recursion
• C++11 Type unsigned long long int
• C++11’s new unsigned long long int type (which can be abbreviated as unsigned long
long) on some systems enables you to store values in 8 bytes (64 bits) which can hold
numbers as large as 18,446,744,073,709,551,615.
80
• begins with 0 and 1 and has the property that each subsequent Fibonacci number is
the sum of the previous two Fibonacci numbers
• The series occurs in nature and, in particular, describes a form of spiral
• The ratio of successive Fibonacci numbers converges on a constant value of 1.618….
• This frequently occurs in nature and has been called the golden ratio or the golden
mean
• Humans tend to find the golden mean aesthetically pleasing
81
fibonacci(1) = 1
• The following program calculates the nth Fibonacci number recursively by using
function Fibonacci
82
83
84
base exponent = base · base exponent – 1 and the terminating condition occurs when
exponent is equal to 1, because base1 = base
94
Solution:
#include <iostream>
using namespace std;
// recursive definition of function expo
int expo( int b, int e ); int expo( int b, int e )
{
if ( e == 1 ) // test for base case
int main() return b; // base cases: base1 = base
{ else // recursion step
int base, exponent, result; return b * expo( b, e - 1 );
cout << "Enter a base and an exponent "
<<endl; } // end function expo
cin >> base >> exponent;
Sample output if base=2, exponent=3:
result=expo( base, exponent );
cout << "The result is " << result << endl; The result is 8
} // end main
This program is similar the factorial program in slide #77
95
Solution
#include <iostream> void check(int num)
using namespace std; {
switch (num){
void check(int num); case 1:
cout<<"OK"<<endl;
int main() break;
{
int x; case 5:
cout << "Enter a number " << endl; cout<<"NOT OK"<<endl;
cin >> x; break;
check(x);
return 0; default:
} cout<<"InValid"<<endl;
break;
}
return;
}