Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Chapter Four - Computer Programming

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 15

Chapter Four

Functions
4. What is a function?
􀂾 A function provides a convenient way of packaging a computational recipe, so that it can
be used as often as required.
􀂾 Therefore, a function is a block of code designed to tackle a specific problem.

4.1. Function Basics


􀂾 One of the best ways to tackle a problem 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.
􀂾 If your program does a lot, break it into several functions. Each function should do
only one primary task.

4.2. Summarized function basics.


􀂾 C++ functions generally adhere to the following rules.
1. Every function must have a name.
2. Function names are made up and assigned by the programmer following the
same rules that apply to naming 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.
3. All function names have one set of parenthesis immediately following them.
This helps you (and C++ compiler) differentiate them from variables.
4. The body of each function, starting immediately after parenthesis of the
function name, must be enclosed by braces.

4.3. Declaring, defining and calling functions

4.3.1. Declaring function:


o The interface of a function (also called its prototype) specifies how it may be used.
It consists of three entities:
o The function return type. This specifies the type of value the function returns. A
function which returns nothing should have a return type void.
o The function name. this is simply a unique identifier
o The function parameters (also called its signature). This is a set of zero or more
typed identifiers used for passing values to and from the function.

4.3.2. Defining a function:


o A function definition consists of two parts: interface (prototype) & body. The brace
of a function contains the computational steps (statements) that computerize the
function. The definition consists of a line called the decelerator.
o If function definition is done before the main function, then there is no need to put
the prototype, otherwise the prototype should be scripted before the main function
starts.

1
4.3.3. Calling the function:
o Using a function involves ‘calling’ it.
o Calling a function means making the instruction of the function to be executed.
o A function call consists of the function name followed by the call operator brackets
‘()’, inside which zero or more comma-separated arguments appear. The number
and type of arguments should match the number of function parameters. Each
argument is an expression whose type should match the type of the corresponding
parameter in the function interface.
o When a function call is executed, the arguments are first evaluated and their
resulting values are assigned to the corresponding parameters. The function body
is then executed. Finally the return value (if any) is passed to the caller.
􀂾 A function call in C++ is like a detour on a highway. Imagine that you are traveling
along the “road” of the primary function called main(). When you run into a function-
calling statement, you must temporarily leave the main() function and execute the
function that was called. After that function finishes (its return statement is reached),
program control returns to main(). In other words, when you finish a detour, you return
to the “main” route and continue the trip. Control continues as main() calls other
functions.
􀂾 Lets have a simple example:

void func1(); prototype of function definition


void main()
{ no return type as it is void in the definition.
---------------
func1(); function call (notice the semicolon)
---------------
}
Return type is void
void func1() no semicolon. Decelerator
{
-------------- function body definition
} no semicolon.
􀂾 Lets have another very simple function example:
// function example
#include <iostream.h>
int addition (int a, int b)
{
int r;
r=a+b;
return (r);
} The result is 8
int main ()
{
int z;
z = addition (5,3);
cout << "The result is " << z;
return 0;
}

2
In order to examine this code, first of all remember something said at the beginning of this
tutorial: a C++ program always begins its execution by the main function. So we will begin
there.

We can see how the main function begins by declaring the variable z of type int. Right after that,
we see a call to a function called addition. Paying attention we will be able to see the similarity
between the structure of the call to the function and the declaration of the function itself some
code lines above:

The parameters and arguments have a clear correspondence. Within the main function we called
to addition passing two values: 5 and 3, that correspond to the int a and int b parameters declared
for function addition.

At the point at which the function is called from within main, the control is lost by main and
passed to function addition. The value of both arguments passed in the call (5 and 3) are copied
to the local variables int a and int b within the function.

Function addition declares another local variable (int r), and by means of the expression r=a+b, it
assigns to r the result of a plus b. Because the actual parameters passed for a and b are 5 and 3
respectively, the result is 8.
The following line of code:

return (r);
finalizes function addition, and returns the control back to the function that called it in the first
place (in this case, main). At this moment the program follows its regular course from the same
point at which it was interrupted by the call to addition. But additionally, because the return
statement in function addition specified a value: the content of variable r (return (r);), which at
that moment had a value of 8. This value becomes the value of evaluating the function call.

So being the value returned by a function the value given to the function call itself when it is
evaluated, the variable z will be set to the value returned by addition (5, 3), that is 8. To explain
it another way, you can imagine that the call to a function (addition (5,3)) is literally replaced by
the value it returns (8).

3
The following line of code in main is:

cout << "The result is " << z;


That, as you may already expect, produces the printing of the result on the screen.

Another example

#include<iostream.h>
#include<conio.h>
void starLine(); //prototype of the function with a name starLine
int main()
{
starLine(); //Calling the function with a name starLine
cout<< “Data type Range” << endl;
starLine();
cout<< “char -128 to 127” <<endl
<< “short -32,768 to 32,767” <<endl
<< “ int system dependent” <<endl
<< “long -2,147,483,648 to 2,147,483,647” << endl;
starLine();
return 0;
}
void starLine()
{
for(int j=0;j<45;j++) definition of the function with a
cout<< “*”; name starLine
cout<<endl;
}

􀂾 Given the next program, which function is the calling function and which is the called
function?
#include<iostream.h>
#include<conio.h>
void nextMsg()
int main()
{
cout<< “Hello!\n”;
nextMsg();
return 0;
}
void nextMsg()
{
cout<< “GoodBye!\n”;
return;
}

4
4.4. Global versus local variables
􀂾 Everything defined at the program scope level (outside functions) is said to have a
global scope, meaning that the entire program knows each variable and has the
capability to change any of them.

Eg.
int year = 1994;//global variable
int max(int,int);//gloabal funcrion
int main(void)
{
//…
}
􀂾 Global variables are visible (“known”) from their point of definition down to the end
of the program.
􀂾 Each block in a program defines a local scope. Thus the body of a function represents a
local scope. The parameters of a function have the same scope as the function body.
􀂾 Variables defined within a local scope are visible to that scope only. Hence, a variable
need only be unique within its own scope. Local scopes may be nested, in which case
the inner scope overrides the outer scopes. Eg:
int xyz;//xyz is global
void Foo(int xyz)//xyz is local to the body of Foo
{
if(xyz > 0)
{
Double xyz;//xyz is local to this block

}
}

4.5. Scope Operator


􀂾 Because a local scope overrides the global scope, having a local variable with the same
name as a global variable makes the latter inaccessible to the local scope.

5
􀂾 Eg
int num1;
void fun1(int num1)
{
//…
}
􀂾 The global num1 is inaccessible inside fun1(), because it is overridden by the local
num1 parameter.
􀂾 This problem is overcome using the scope operator ‘::’ which takes a global entity as
argument.
int num1 = 2;
void fun1(int num1)
{
//…
num1=33;
cout<<num1; // the out put will be 33
cout<<::num1; //the out put will be 2 which is the global
if(::num1 != 0)//refers to global num1
//…
}

4.6. Automatic versus static variables


􀂾 The terms automatic and static describe what happens to local variables when a
function returns to the calling procedure. By default, all local variables are automatic,
meaning that they are erased when their function ends. You can designate a variable
as automatic by prefixing its definition with the term auto.
􀂾 Eg. The two statements after main()’s opening brace declared automatic local
variables:
main()
{
int i;
auto float x;

}
􀂾 The opposite of an automatic is a static variable. All global variables are static and, as
mentioned, all static variables retain their values. Therefore, if a local variable is
static, it too retains its value when its function ends-in case this function is called a
second time.
􀂾 To declare a variable as static, place the static keyword in front of the variable when
you define it.
􀂾 Static variables can be declared and initialized within the function, but the initialization
will be executed only once during the first call.

􀂾 If static variables are not declared explicitly, they will be declared to 0 automatically.
Eg. void my_fun()
{
static int num;
static int count = 2;

6
count=count*5;
num=num+4;
}

􀂾 In the above example:


o During the first call of the function my_fun(), the static variable count will be
initialized to 2 and will be multiplied by 5 at line three to have the value 10.
During the second call of the same function count will have 10 and will be
multiplied by 5.
o During the first call of the function my_fun(), the static variable num will be
initialized to 0 (as it is not explicitly initialized) and 4 will be added to it at line
four to have the value 4. During the second call of the same function num will
have 4 and 4 will be add to it again.
􀂾 N.B. if local variables are static, their values remain in case the function is
called again.

4.7. Function Parameters and arguments


􀂾 The parameters of a function are list of variables used by the function to perform its
task and the arguments passed to the function during calling of a function are values
sent to the function.
􀂾 The arguments of function calling can be using either of the two supported styles in C+
+: passing by value or passing by reference.

4.7.1. Passing by value:


o A value parameter receives a copy of only the value of the argument passed to it. As
a result, if the function makes any changes to the parameters, this will not affect
the argument. For instance:
#.....
void Foo(int num)
{ Num = 0;
cout<< “num = ” << num << “ \n”;
}
int main( )
{ int x = 10;
Foo(x);
cout<< “x = ”<<x<< “\n”;
getch();
return 0;
}
o The single parameter of Foo is a value parameter. As far as this function is
concerned, num behaves just like a local variable inside the function. When the
function is called and x passed to it, num receives a copy of the value of x. As a
result, although num is set to 0 by the function, this does not affect x. the program
produces the following output:
Num = 0
x = 10
o Passing arguments in this way, where the function creates copies of the arguments
passed to it is called passing by value.

7
4.7.2. Passing by Reference:
o A reference parameter, on the other hand, receives the argument passed to it and
works on it directly. Any change made by the function to a reference parameter is
in effect directly applied to the argument.
o Passing parameters in this way is called pass-by-reference.
o Taking the same example above:
#.....
#.....
void Foo(int & num)
{
num = 0;
cout<< “num = ” << num << “ \n”;
}
int main(void)
{
int x = 10;
Foo(x);
cout<< “x = ”<<x<< “\n”;
getch();
return 0; ;
}
o The parameter of Foo is a reference parameter. Num will correspond to x for this
specific program as it x is sent by its reference and not its value. Any change
made on num will be effected to x. Thus, the program produces the following
output:
num = 0
x=0

o Suppose you have pairs of numbers in your program and you want to be sure that
the smaller one always precedes the larger one. To do this, you call a function,
order(), which checks two numbers passed to it by reference and swaps the
originals if the first is larger than the second.

#.......
#.......
void order(int &, int &);
int main()
{
int n1 = 99, n2=11;
int n3 = 22, n4=88;
order(n1,n2);
order(n3,n4);
cout<< “n1=”<<n1<<endl;
cout<< “n2=”<<n2<<endl;
cout<< “n3=”<<n3<<endl;
cout<< “n4=”<<n4<<endl;
return 0;
}

8
void order(int & num1,int & num2)
{
if(num1 > num2)
{
int temp=num1;
num1 = num2;
num2 = temp;
}
}
o In main() there are two pairs of numbers-the first pair is not ordered and the second
pair is ordered. The order() function is called once for each pair, and then all the
numbers are printed out. The output reveals that the first pair has been swapped
while the second pair has not. Here it is:
N1 = 11
N2 = 99
N3 = 22
N4 = 88
o In the order() function the first variable is called num1 and the second is num2. If
num1 is greater than num2, the function stores num1 in temp, puts num2 in num1,
and finally puts temp back in num2.
o Using reference arguments in this way is a sort of remote control operation. The
calling program tells the function what variables in the calling program to operate on, and the
function modifies these variables without ever knowing their real names.

4.8. Inline functions


􀂾 Suppose that a program frequently requires finding the absolute value of an integer
quantity. For a value denoted by n, this may be expressed as:
(n > 0 ? n : -n)
􀂾 However, instead of replicating this expression in many places in the program, it is
better to define it as a function:
int Abs(int n)
{
return n > 0 ? n : -n;
}
􀂾 The function version has a number of advantages.
􀂃 It leads to a more readable program.
􀂃 It is reusable.
􀂾 The disadvantage of the function version, however is that
􀂃 Its frequent use can lead to considerable performance penalty due to
overheads associated with calling a function.
􀂾 The overhead can be avoided by defining Abs as an inline function.
inline int Abs(int n)
{

Return n > 0 ? n : -n;


}
􀂾 The effect of this is that when Abs is called, the compiler, instead of generating code to
call Abs, expands the program body and substitutes the body of Abs in place of the

9
call. While essentially the same computation is performed, no function call is
involved and hence no stack frame is allocated.
􀂾 The "inline" keyword is merely a hint to the compiler or development environment.
􀂾 Not every function can be inlined. Some typical reasons why inlining is sometimes not
done include:
􀂃 the function calls itself, that is, is recursive
􀂃 the function contains loops such as for(;;) or while()
􀂃 the function size is too large
􀂾 Another good reason to inline is that you can sometimes speed up your program by
inlining the right function. Instead of calling the function every time it is invoked, the
compiler will replace the function call with a copy of the function body. If it's a small
function which gets called a lot, this can sometimes speed things up.
􀂾 Most of the advantage of inline functions comes from avoiding the overhead of calling
an actual function. Such overhead includes saving registers, setting up stack frames,
and so on. But with large functions the overhead becomes less important.
􀂾 Concerning inline functions, the compiler is free to decide whether a function qualifies
to be an inline function. If the inline function is found to have larger chunk (amount)
of code, it will not be treated as an inline function, but as like other normal functions.
􀂾 Then, Why not inline everything? :Since the compiler will copy the entire function
body every time the function is called, if it is a large function (more than three or four
lines), inlining can increase the size of your executable program significantly.

4.9. Default arguments and function overloading


􀂾 C++ has two capabilities that regular C doesn’t have. Default arguments and function
overloading.

4.9.1. Default arguments


􀃖 Default argument is a programming convenience which removes the burden of
having to specify argument values for all function parameters.
Eg. You might pass a function an error message that is stored in a character array, and
the function displays the error for a certain period of time. The prototype for
such a function can be this:
Void pr_msg(char note[]);
􀃖 Therefore, to request that pr_msg() display the line ‘Turn printer on’, you call it
this way:
Pr_msg(“Turn printer on”);
􀃖 As you write more of the program, you begin to realize that you are displaying one
message-for instance, the ‘Turn printer on’ msg-more often than any other
message.
􀃖 Instead of calling the function over and over, typing the same message each time,
you can set up the prototype for pr_msg() so that it defaults to the ‘turn printer on’
message in this way:
Void pr_msg(char note[] = “Turn printr on”);
􀃖 This makes your programming job easier. Because you would usually want
pr_msg() to display ‘turn printer on’, the default argument list takes care of the
message and you don’t have to pass the message when you call the function.

10
􀃖 For functions having more than one argument with default, the parameters with
possible default value should be declared in the right side of the function
definition and prototype.
E.g.: Let us develop part of the program with default arguments.
#include…..
void Add_Display(int x=10, int y=20, int z=30)
{
cout<< (x+y+z);
}
void Mult_Dispaly (int x, int y=70)
{
cout<< (x*y);
}
void main()
{
int a=40, b=50, c=60;
Add_Display(a,b,c); //will print 150 (ie 40+50+60)
Add_Display(a,b); //will print 120 (ie 40+50+30)
Add_Display(a); //will print 90 (ie 40+20+30)
Add_Display(); //will print 60 (ie 10+20+30)
Mult_Display(a,b) //will print 2000 (40*50)
Mult_Display(a) //will print 2800 (40*70)
//Mult_Display() //is invalid as there is no default for x
getch();
}
//the following function definition is invalid as z is
//a parameter without a default and written after y
//parameters with default should always be at the
//right side of function declaration
void Mult_Dispaly (int x, int y=70, int z)
{
cout<< (x*y*z);
}
//thus the following function definition will be correct
void Mult_Dispaly (int x, int z, int y=70)
{
cout<< (x*y*z);
}

4.9.2. Overloaded Functions


􀃖 Unlike C, C++ lets you have more than one function with the same name. In other
words, you can have three functions called abs() in the same program.
􀃖 Functions with the same name are called overloaded functions. C++ requires that
each overloaded functions differ in its argument list. Overloaded functions enable
you to have similar functions that work on different types of data.
􀃖 Suppose that you wrote a function that returned the absolute value of what ever
number you passed to it:
int iabs(int i)

11
{ if(i<0)
Return (i*-1);
else
Return (i);
}
float fabs(float x)
{ if(x<0.0)
Return (x * -1.0);
else
Return (x);
}
􀃖 Without using overloading, you have to call the function as:
int ans = iabs(weight);//for int arguments
float ans = fabs(weight);//for float arguments
􀃖 But with overloading, the above code can be used as:
int abs(int i);
float abs(float x);
int main()
{

ians = abs(i);//calling abs with int arguments
fans = abs(p);//calling abs with float arguments

}
int abs(int i)
{
if(i<0)
Return i*-1;
else
Return I;
}
float abs(flaot x)
{
if(x<0.0)
Return x*-1.0;
else
Return x;
}
􀃖 N.B: if two or more functions differ only in their return types, C++ can’t overload
them. Two or more functions that differ only in their return types must have
different names and can’t be overloaded

12
4.10. Recursion
􀂾 A function which calls itself is said to be recursive. Recursion is a general
programming technique applicable to problems which can be defined interms of
themselves. Take the factorial problem, for instance which is defined as:
- factorial of 0 is 1
- factorial of a positive number n is n time the factorial of n-1.
􀂾 The second line clearly indicates that factorial is defined in terms of itself and hence
can be expressed as a recursive function.
int Factorial(unsigned int n )
{
return n = = 0 ? 1 : n * factrial(n-1);
}
􀂾 For n set to 4, the following figure shows the recursive call:

Factorial(4)

24
4 * Factorial(3)

6 3 * Factorial(2)

2 2* Factorial(1)

1 1
􀂾 The stack frames for these calls appear sequentially on the runtime stack, one after the
other.
􀂾 A recursive function must have at least one termination condition which can be
satisfied. Otherwise, the function will call itself indefinitely until the runtime stack
overflows.

􀂾 The three necessary components in a recursive method are:


1. A test to stop or continue the recursion
2. An end case that terminates the recursion
3. A recursive call(s) that continues the recursion
􀂾 let us implement two more mathematical functions using recursion
􀂾 e.g the following function computes the sum of the first N positive integers 1,2,…,N.
Notice how the function includes the three necessary components of a recursive
method.
int sum(int N)
{
if(N==1)
return 1;
else
return N+sum(N);
}
􀂾 The last method computes the exponentiation A n where A is a real number and N is a
positive integer. This time, we have to pass two arguments. A and N. the value of A

13
will not change in the calls, but the value of N is decremented after each recursive
call.
float expo(float A, int N)
{
if(N==1)
return A;
else
return A * expo(A,N-1);
}
 Try to use a recursive function call to solve the Fibonacci series. The Fibonacci series is :
0,1,1,2,3,5,8,13,21,…
 the recursive definition of the Fibonacci series is as follows:
Fibonacci (0) =0
Fibonacci (1) =1
Fibonacci (n) =Fibonacci (n-1) +Fibonacci (n-2);
4.11. Recursion versus iteration

 Both iteration and recursion are based on control structure. Iteration uses a
repetition structure (such as for, while, do…while) and recursive uses a
selection structure (if, if else or switch).
 Both iteration and recursive can execute infinitely-an infinite loop occurs with
iteration if the loop continuation test become false and infinite recursion
occurs id the recursion step doesn’t reduce the problem in a manner that
coverage on a base case.
 Recursion has disadvantage as well. It repeatedly invokes the mechanism,
and consequently the overhead of method calls. This can be costly in both
processor time and memory space. Each recursive call creates another copy of
the method (actually, only the function’s variables); this consumes
considerable memory.
 N.B: Use recursion if:
1. A recursive solution is natural and easy to understand
2. A recursive solution doesn’t result in excessive duplicate computation.
3. the equivalent iterative solution is too complex and
4. of course, when you are asked to use one in the exam!!

Worksheet 4.

14
1. Write an int function cube () that returns the cube of its single int formal parameter.

2. Write a float function triangle() that computes the area of a triangle using its two formal
parameters h and w, where h is the height and w is the length of the bases of the triangle.

3. Write a float function rectangle() that computes and returns the area of a rectangle using its
two float formal parameters h and w, where h is the height and w is the width of the rectangle

4. The formula for a line is normally given as y = mx + b. Write a function Line() that expects
three float parameters, a slop m, a y-intercept b, and an x-coordinate x. the function computes
the y-coordinate associated with the line specified by m and b at x-coordinate.

5. Write a function Intersect() with four float parameters m1,b1,m2,b2. The parameters come
conceptually in two pairs. The first pair contains the coefficients describing one line; the
second pair contains coefficients describing a second line. The function returns 1 if the two
lines intersect. Otherwise, it should return 0;

6. Write a program that accepts a positive integer from the user and displays the factorial of the
given number. You should use a recursive function called factorial() to calculate the factorial
of the number.

7. Write another program that accepts a number from the user and returns the Fibonacci value of
that number. You should use recursion in here.

8. Develop a program that uses the function factorial() of exercise 6 to compute an approximation
of e (Euler’s number). Base your approximation on the following formula for e:
1 + 1/1! + 1/2! + 1/3! + …
9. Write a function called isPrime() that accepts a number and determine whether the number is
prime or not.

10. Write a function called isEven() that uses the remainder operator(%) to determine whether an
integer is even or not.

11. Modify our calculator problem of worksheet-3 using four functions


sum(),product(),quotient() and difference().

15

You might also like