0% found this document useful (0 votes)
29 views94 pages

Chapter 6

Uploaded by

maryam osama
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views94 pages

Chapter 6

Uploaded by

maryam osama
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 94

Introduction to Computer Programming (CSCI 112)

Chapter 6
Functions and an Introduction to Recursion

Dr. Ali Alnoman


Spring 2023

Reference: C++ How to Program, 10th edition, P. Deitel and H. Deitel


2

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

Program Components in C++


• C++ programs are typically written by combining new functions and classes you
write with “pre-packaged” functions and classes available in the C++ Standard
Library
• The C++ Standard Library provides a rich collection of functions
• Functions allow you to modularize a program by separating its tasks into sub-tasks
or functions
• Functions you write are referred to as user-defined functions
• The statements in the function body are written only once and can be reused from
different locations in the program
5
6

Program Components in C++


• A function is invoked by a function call, and when the called function completes its
task, it either returns a result or simply returns control to the caller
• An analogy to this program structure is the hierarchical form of management
▫ A boss (similar to the calling function) asks a worker (similar to the called function) to perform a
task and report back (i.e., return) the results after completing the task
▫ The boss function does not know how the worker function performs its designated tasks
▫ The worker may also call other worker functions
• This hiding of implementation details promotes good software engineering
7
8

Math Library Functions


• The <cmath> header file provides a collection of functions that enable
you to perform common mathematical calculations

• All functions in the <cmath> header file are global functions—therefore,


each is called simply by specifying the name of the function followed by
parentheses containing the function’s arguments

• Some math library functions are summarized in the next slide


▫ In the figure, the variables x and y are of type double
9
10
11

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

Functions: Version 1 (no returned value)


#include<iostream>
using namespace std; void square(int num)
{
//Declaration of the square function int answer;
void square(int num); answer = num * num;
int main() cout << "The square of number " << num << " is "
{ << answer << endl;
int x=5; return; //return to the caller
}
//calling the square function and passing the value
of x Note: the function (square) is
square(x);
return 0; declared as void because it does
} not return a value. (Suitable for
printing the result directly within
the function)
13

Functions: Version 2 (returns value)


#include<iostream> int square(int num)
using namespace std; {
//Declaration of the square function int answer;
int square(int num); answer = num * num;
return answer;
int main() // returning the square of the parameter
{ }
int x = 5;
int result;

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

Functions: Version 3 (returns value using a global variable)


#include<iostream>
using namespace std;
void square(int num); //Declaration of the square function
int result; // declaring result as a global variable

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

Example: Calculate the cube of a number


#include <iostream>
using namespace std;

double cube( const double side ) const double:


{ const tells the compiler that the
return side * side * side; // calculate cube function does not modify the
} // end function cube variable “side”
int main() This ensures that the value of “side”
{ is not changed by the function
double sideValue; // stores value entered by user during the calculation (read only
cout << "Enter the side length of your cube: "; variable)
cin >> sideValue; // read value from user

// calculate cube of sideValue and display result


cout << "Volume of cube with side " << sideValue << " is " << cube( sideValue ) <<endl;
}
16
17

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

C++ Standard Library Header Files


• The C++ Standard Library is divided into many portions, each with its own header file
• The header files contain the function prototypes for the related functions that form
each portion of the library
• The header files also contain definitions of various class types and functions, as well as
constants needed by those functions
• A header file “instructs” the compiler on how to interface with library and user-written
components
• The following figure lists some common C++ Standard Library header files
22
23
24

Case Study: Random Number Generation


• The function rand generates an unsigned integer between 0 and RAND_MAX (a
symbolic constant defined in the <cstdlib> header file)
• The value of RAND_MAX is at least 32767—the maximum positive value for a two-
byte (16-bit) integer
• For GNU C++, the value of RAND_MAX is 2147483647
• Every number between 0 and RAND_MAX has an equal chance (or probability) of
being chosen each time rand is called
25

Case Study: Random Number Generation


• Rolling a Six-sided Die
• The function prototype for the rand function is in <cstdlib>
• To produce integers in the range 0 to 5, we use the modulus operator
(%) with rand:
 rand() % 6
▫ This is called the scale
▫ The number 6 is called the scaling factor. Six values are produced
• We can shift the range of numbers produced by adding a value
▫ This is called shift
26
27
28

Case Study: Random Number Generation


• To show that the numbers produced by rand occur with approximately equal
likelihood, the following program simulates 6,000,000 rolls of a die
29
30
31
32

Case Study: Random Number Generation


• Executing the previous program again produces exactly the same
sequence of values
▫ This repeatability is an important characteristic of function rand
▫ Essential for proving that program works and for debugging
33

Case Study: Random Number Generation


• Randomization is accomplished with the C++ Standard Library function srand
• Function srand takes an unsigned integer argument and seeds the rand function to
produce a different sequence of random numbers for each execution.
• C++11 provides additional random number capabilities that can produce
nondeterministic random numbers - a set of random numbers that can’t be
predicted
• Such random number generators are used in simulations and security scenarios
where predictability is undesirable
34

Case Study: Random Number Generation


• Seeding the Random Number Generator with srand
35
36
37

Case Study: Random Number Generation


• To randomize without having to enter a seed each time, we may use a statement like
srand( time( 0 ) );
• This causes the computer to read its clock to obtain the value for the seed
• The function prototype for time is in <ctime>
38

Case Study: Random Number Generation


• To produce random numbers in a specific range use:

number = shift + rand() % scale;

• 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

Case Study: Game of Chance; Introducing enum


• Case study:
• A player rolls two dice. Each die has six faces. These faces contain 1, 2, 3, 4, 5 and 6
spots
• After the dice have come to rest, the sum of the spots on the two upward faces is
calculated:
▫ If the sum is 7 or 11 on the first roll, the player wins
▫ If the sum is 2, 3 or 12 on the first roll, the player loses
▫ If the sum is 4, 5, 6, 8, 9 or 10 on the first roll, then that sum becomes the player’s “point.”
40

#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

Case Study: Game of Chance; Introducing enum


• An enumeration, introduced by the keyword enum and followed by a type name, is a
set of integer constants represented by identifiers
• The values of these enumeration constants start at 0, unless specified otherwise, and
increment by 1
• The identifiers in an enum must be unique, but separate enumeration constants can
have the same integer value
• Variables of an enum type can be assigned only one of the values declared in the
enumeration
42

Case Study: Game of Chance; Introducing enum


• Another popular enumeration is
enum Months { JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG,
SEP, OCT, NOV, DEC };
▫ creates user-defined type Months with enumeration constants representing the
months of the year
▫ The first value in the preceding enumeration is explicitly set to 1, so the remaining
values increment from 1, resulting in the values 1 through 12
43

#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 Classes and Storage Duration


• Each identifier in a program also has other attributes, including storage duration, scope and
linkage
• Duration
▫ An identifier’s storage duration determines the period during which that identifier exists in memory
▫ Some exist briefly, some are repeatedly created and destroyed and others exist for a program’s entire
execution
• Scope
▫ An identifier’s scope is where the identifier can be referenced in a program
▫ Some identifiers can be referenced throughout a program; others can be referenced from only limited
portions of a program
• Linkage
▫ An identifier’s linkage determines whether it’s known only in the source file where it’s declared or across
multiple files that are compiled, then linked together. (use of static and extern storage class specifiers)
45

Storage Duration
Storage Duration
• The storage-class specifiers can be split into four storage durations:
▫ automatic, static, dynamic

• Variables with automatic storage duration (automatic variables) include:


▫ local variables declared in functions
▫ function parameters
46

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

Identifiers with Static Storage Duration


• There are two types of identifiers with static storage duration
▫ external identifiers (such as global variables and global function names)
▫ local variables declared with type static
48
49

Storage Classes and Storage Duration


static Local Variables
• Local variables declared static are still known only in the function in which they’re
declared, but, unlike automatic variables, static local variables retain their values
when the function returns to its caller
• The next time the function is called, the static local variables contain the values they
had when the function last completed execution
50

Scope Rules
• The portion of the program where an identifier can be used is known as
its scope

• This section discusses


▫ block scope
▫ function scope,
▫ global namespace scope
▫ function-prototype scope
51

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

Functions with Empty Parameter Lists


• In C++, an empty parameter list is specified by writing either void or nothing at all in
parentheses as shown in the following example
60
61
62

References and Reference Parameters


• Two ways to pass arguments to functions in many programming languages are pass-
by-value and pass-by-reference (or call-by-value and call-by-reference)
• When an argument is passed by value, a copy of the argument’s value is made and
passed (on the function call stack) to the called function. Large data passed.
▫ Changes to the copy do not affect the original variable’s value in the caller
63

References and Reference Parameters


• With pass-by-reference, the caller gives the called function the ability to access the
caller’s data directly, and to modify that data
• A reference parameter is an alias for its corresponding argument in a function call
• To indicate that a function parameter is passed by reference, simply follow the
parameter’s type in the function prototype by an ampersand (&); use the same
convention when listing the parameter’s type in the function header
• The following program compares pass-by-value and pass-by-reference with
reference parameters
64
65
68

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

• The factorial of a nonnegative integer n, written n! (and pronounced “n factorial”), is


the product

n · (n – 1) · (n – 2) · … · 1

• with 1! equal to 1, and 0! defined to be 1.


72

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

Example Using Recursion:


Fibonacci Series
• The Fibonacci series
 0, 1, 1, 2, 3, 5, 8, 13, 21, …

• 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

Example Using Recursion: Fibonacci Series


• Recursive Fibonacci Definition
• The Fibonacci series (each number is the sum of the two preceding ones) can be
defined recursively as follows:
 fibonacci(0) = 0

fibonacci(1) = 1

fibonacci(n) = fibonacci(n – 1) + fibonacci(n – 2)

• The following program calculates the nth Fibonacci number recursively by using
function Fibonacci
82
83
84

Example Using Recursion: Fibonacci Series


• The following figure shows how function fibonacci would evaluate fibonacci(3)
85

Recursion vs. Iteration


• Both iteration and recursion are based on a control statement:
▫ Iteration uses a repetition structure
▫ recursion uses a selection structure
• Both iteration and recursion involve repetition: Iteration explicitly uses a repetition
structure; recursion achieves repetition through repeated function calls
• Iteration and recursion each involve a termination test: Iteration terminates when
the loop-continuation condition fails; recursion terminates when a base case is
recognized
86

Recursion vs. Iteration


• Iteration with counter-controlled repetition and recursion both gradually approach
termination:
▫ Iteration modifies a counter until the counter assumes a value that makes the loop-continuation condition
fail;
▫ recursion produces simpler versions of the original problem until the base case is reached
• Both iteration and recursion can occur infinitely: An infinite loop occurs with iteration if the
loop-continuation test never becomes false; infinite recursion occurs if the recursion step
does not reduce the problem during each recursive call in a manner that converges on the
base case
• To illustrate the differences between iteration and recursion, let’s examine an iterative
solution to the factorial problem in the following:
87
88
89
90

Exercise 1: What is the output?


#include <iostream> int main()
#include <cmath> {
using namespace std; double radiusValue;

// define global constant PI // prompt user for radius


const double PI = 3.14159; cout << "Enter the length of the radius of
your sphere: ";
// calculates volume of a sphere cin >> radiusValue; // input radius
double sphereVolume( const double radius )
{ // use radiusValue to calculate volume of
return 4.0/3.0 * PI * pow( radius, 3 ); sphere and display result
} // end function sphereVolume cout << "Volume of sphere with radius " <<
radiusValue << " is " << sphereVolume(
radiusValue ) << endl;
OUTPUT: } // end main
Enter the length of the radius of your sphere 5
Volume of sphere with radius 5 is 523.598
91

Exercise 2: Write a program


Write a program that prompts the user to input an integer number. The main function then passes
the number to a function isEven, which uses the modulus operator to determine whether the
integer number is even. The program will repeat this process 5 times (FOR loop). The function
isEven should display EVEN when the integer number is even and ODD otherwise.
#include <iostream> int main()
using namespace std; {
int x;
void isEven( int num )
{ for (int counter =1; counter <= 5;
if (num % 2 == 0) counter++)
cout << "EVEN" << endl; {
else cout << "Enter an integer number " <<
cout << "ODD" << endl; endl;
} cin >> x;
isEven(x);
} // end for
} // end main
92

Exercise 3: What is the output


#include <iostream>
using namespace std; // Parameter b must be a positive integer to
prevent infinite recursion
// function prototype int mystery( int a, int b )
int mystery( int, int ); {
if ( b == 1 ) // base case
int main() return a;
{ else // recursion step
int x, y; return a + mystery( a, b - 1 );
} // end function mystery
cout << "Enter two integers: ";
cin >> x >> y;
cout << "The result is " << mystery( x,y)
<< endl; Sample outputs:
} // end main x=3 y=1: OUTPUT=3 x=2 y=3: OUTPUT=6
x=2 y=2: OUTPUT=4 x=3 y=3: OUTPUT=9
93

Exercise 4: Write a program (recursion)


Write a recursive function power( base, exponent ) that, when invoked, returns:
base exponent
For example, power( 3, 4 ) = 3 * 3 * 3 * 3. Assume that exponent is an integer greater
than or equal to 1.
Hint: The recursion step would use the relationship:

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

Exercise 5: Write a program


Write a program that asks the user to input an integer number then passes this number
to a function check that uses switch statement to check the following:
If the number is 1, display OK
If the number is 5, display NOT OK
Otherwise, display InValid
96

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;
}

You might also like