8 Functions

Download as pdf or txt
Download as pdf or txt
You are on page 1of 17

CS100 : Computer Programming

Chapter 8 - Functions

Narasimhan T.

8.1 Introduction
Most of the programs that solve real-world problems are much bigger and complex than the
programs presented in the earlier chapters. Python allows a large program to be broken down
into a number of smaller modules or components. Such components are called functions. A
function is a named, self-contained block of statements that carries out some specific, well-de-
fined task. A program can be seen as a collection of functions, each of which has some unique,
identifiable purpose. This way of dividing a program into code fragments (functions) is called
modular programming. There are several advantages to this modular approach to program
development:
1. Functions eliminate redundancy: Many programs require that a particular group of
instructions be accessed repeatedly, from several different places within the program. The
repeated instructions can be placed within a single function, which can then be accessed
whenever it is needed. The use of a function avoids the need for redundant (repeated)
programming of the same instructions.
2. Functions enables the re-use of code: A function may be used by many other pro-
grams. Thus a programmer can build on what others have already done instead of starting
from scratch. Thus functions facilitates re-use of code.
3. Functions hide complexity: Functions can simplify a program by hiding a complex
computation from other parts of the program that don’t need to know about them. A
function will carry out its intended action whenever it is accessed. If you want to use the
function in your program, you don’t have to know how it works inside! This mechanism
is called abstraction. Thus a function hides unnecessary details from the users.
4. Functions support the division of labour: Functions can enforce a division of labour.
Ideally, each function performs a single coherent task. A complex task could be divided
into simpler sub-tasks. Each of these sub-tasks can be assigned to separate functions.
5. Functions enhance the readability of programs: Dividing a long program into
functions allows you to separate parts of the program. This makes the program easier to
design and understand.
6. Functions enable improved debugging and testing: When a program is divided
into functions, it is possible to isolate a function and investigate it separately which helps
in easily locating and pin-pointing errors. Thus functions aid in easy debugging.

1
Based on who develops a function, there are two categories of functions:

1. Library functions – These are built-in functions in C to handle tasks such as mathematical
computations, I/O processing, string handling etc. These functions are defined in various
header files. When you include the header file, these functions are available for use.
printf(), sqrt() are some examples.

2. User defined functions – C allows programmers to define functions. Such functions created
by the user are called user-defined functions. There is no limit on the number of user
functions that you can create.

8.2 Elements of user defined function


There are three aspects of working with user defined functions:

1. Function declaration – also known as function prototype or function signature.

2. Function definition – implementation of function

3. Function use – known as function call or function invocation.

8.2.1 Function declaration


When users develop their own functions, the compilers should be informed about the existence
of these new functions. This is done through function declaration. It contains the following
elements.

→ function name

→ return type – data type of the result produced by the function

→ list of argument types – data types of the input values to the function

For example, the statement

Example 8.1. Assume you have the following statement in a program


int ABC(char,float);
This declares a function:

⋆ with name ABC

⋆ that takes two input values of type char and float

⋆ that produces a result of type int

8.2.2 Function definition


Each function has its own purpose in the program. The logic required to implement the task
performed by the function is specified in the function definition. It has two parts:

→ function header – specifies the name of the function along with the input values to it. It
also indicates the return type [See function declaration]

2
→ function body – this contains the statements that implement the task to be performed.
The statements are to be enclosed in a pair of braces.
Example 8.2. The following defines a function ABC.
int ABC(char c, float f)
{
......
......Statements that make the function body
......
}

8.2.3 Function call


Just defining a function is not sufficient. In order to use it, we need to access it. This is
known as calling the function. The statements inside the function do not get executed until
the function is called. A function can be called by specifying its name, followed by the list of
arguments in parentheses and separated by commas. If the function call does not require any
arguments, an empty pair of parentheses must follow the name of the function.
Example 8.3. The statement
ABC(m,n);
calls a function ABC and supplies two input values m and n to it. 

Assume a function ABC is called from another function XYZ, then


→ ABC is known as the called function or callee.

→ XYZ is known as the calling function or caller.

R If a function is defined before it is called, there is no need to declare the function.

8.3 How a function works?


1. When a function call is encountered, the control passes to the called function.

2. The called function will process the information that it is supplied with, and produces a
result.

3. The data supplied to the function are called arguments or parameters and the result
produced is known as return value. In other words, arguments are those values that are
passed (supplied) from the caller to the callee and return value is the result sent back to
the caller from callee.

4. The parameters in the function definition are called formal parameters and those in
the function call are called actual parameters. The values that the caller needs to pass
to callee are packed as actual arguments. These values are received by the called function
as formal arguments.

5. The called function operates on the formal arguments and produces the result.

3
6. When the called function finishes its execution, control is passed back to the statement
immediately following the function call in the calling function. When it gets to the end
of the program, it terminates.

Which category should I choose?


You know there are four categories of user defined functions. Now, given a problem, which
category to choose? Precisely, all the categories are equivalent in the sense that the problem
solved with one category is solvable using any other category. The choice of the category
depends entirely on the programmer. As a rule of thumb, if you input the values in the
calling function and need to process them in the called function, then your function should
have arguments. Thus choose between categories 3 and 4. Similarly if you want the result
of this processing to be available in the calling function, then your function should return
that value. In this case, you should choose between categories 2 and 4.

8.4 Classification of functions


The arguments and the return value are both optional. This results in four categories of
functions as discussed below. To elucidate the differences among the different categories, a
simple function to add two numbers is taken for illustration. (Read the box - Which category
should I choose?)

8.4.1 Function with no arguments and no return value


Example 8.4. Consider the program below:
#include<stdio.h>
void sum();
main()
{
sum();
}
void sum()
{
int a,b;
printf("Enter two values to add\n");
scanf("%d %d",&a,&b);
printf("The sum is %d\n",a+b);
}
The main() function calls sum(). In sum(), the two values are input and their sum is dispalyed.

8.4.2 Function with no arguments but returns a value


Example 8.5. Consider the program below:
#include<stdio.h>
int sum();
main()
{

4
int s;
s=sum();
printf("The sum is %d\n",s);
}
int sum()
{
int a,b;
printf("Enter two values to add\n");
scanf("%d %d",&a,&b);
return (a+b);
}
main() function calls the sum() function which inputs the values and finds their sum. The
result is then returned to main() where it is printed. This is shown in the code below:

8.4.3 Function with arguments but with no return value


Example 8.6. Consider the program below:
#include<stdio.h>
void sum(int,int);
main()
{
int a,b;
printf("Enter two values to add\n");
scanf("%d %d",&a,&b);
sum(a,b);
}
void sum(int x,int y)
{
printf("The sum is %d\n",x+y);
}
The main() function accepts the input from the user and calls the sum() with the input values
as arguments. sum() receives the arguments, adds them and prints the result.

8.4.4 Function with arguments and returns a value


Example 8.7. Consider the program below: main() accepts input from user and passes them
as arguments while calling sum(). The called function adds the received arguments and returns
their sum. This return value is accepted by main() which is then printed. See the program
below.
#include<stdio.h>
int sum(int,int);
main()
{
int a,b,s;
printf("Enter two values to add\n");
scanf("%d %d",&a,&b);
s=sum(a,b);

5
printf("The sum is %d\n",s);
}
int sum(int x,int y)
{
return (x+y);
}

8.5 Parameter passing schemes


There are two ways to pass data items to function in C language: call by value and call by
reference.

8.5.1 Call by value


The first is call by value. This method copies the value of an actual parameter into the formal
parameter of the called function. In this case, changes made to the formal parameters are not
reflected in the calling function. The changes are made only to the local copy of the formal
parameters.

Example 8.8. This program illustrates call by value method of parameter passing.
#include<stdio.h>
void updateVar(int);
main()
{
int var=10;
printf("In calling function: Old value was %d\n",var);
updateVar(var);
printf("In calling function: New value is %d\n",var);
}
void updateVar(int var)
{
printf("In called function: Old value was %d\n",var);
var+=5;
printf("In called function: New value is %d\n",var);
}
Here the value of the variable var is copied to the formal parameter. Thus any changes made
on this copy will be available only in the called function. The program outputs:
In calling function: Old value was 10
In called function: Old value was 10
In called function: New value is 15
In calling function: New value is 10

8.5.2 Call by reference


Call by reference is the second way of passing arguments to a function. In this method, the
address of an actual parameter is copied into the formal parameter. The contents of that address
can be accessed within the called function. Thus, any change that is made to the data item

6
(i.e., to the contents of the address) will be recognized in both the called function and in the
calling function.
Example 8.9. This program illustrates call by reference.
#include<stdio.h>
void updateVar(int *);
main()
{
int var=10;
printf("In calling function: Old value was %d\n",var);
updateVar(&var);
printf("In calling function: New value is %d\n",var);
}
void updateVar(int *var)
{
printf("In called function: Old value was %d\n",*var);
*var+=5;
printf("In called function: New value is %d\n",*var);
}
Here the address of the variable var is passed to the function. So any changes made in the
function will also get reflected in main(). This program prints
In calling function: Old value was 10
In called function: Old value was 10
In called function: New value is 15
In calling function: New value is 15


The two parameter passing schemes are compared in Table 8.1.

Table 8.1: Comparison of call by value and call by reference

Call by value Call by reference


A copy of actual parameter’s value is The address of actual parameter is
passed to the function passed to the function
Changes made inside the function is not Changes made inside the function is re-
reflected in other functions flected outside the function also
Actual and formal arguments will be Actual and formal arguments share the
stored in different memory locations same memory location

8.6 Passing arrays to a function


An entire array can be passed to a function as an argument. The manner in which the array is
passed differs from that of an ordinary variable.

8.6.1 Passing 1D array to function


To pass an 1D array to a function, you need to specify the array name (without any subscripts)
and the size of the array in the function call. See the example below:

7
Example 8.10. This program illustrates the passing of 1D array to a function. This inputs
and prints the elements of an 1D array.
#include<stdio.h>
void printArray(int [],int);
main()
{
int a[10],n,i;
printf("How many elements you want?\n");
scanf("%d",&n);
printf("Enter %d elements\n",n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
printArray(a,n);
}
void printArray(int a[],int n)
{
int i;
printf("The array elements are\n");
for(i=0;i<n;i++)
printf("%d ",a[i]);
}
See how the function is declared. An empty pair of square brackets must follow the data type
of each array argument, thus indicating that the argument is an array. The size of the array is
not specified within the declaration.

8.6.2 Passing 2D arrays to a function


To pass 2D array to a function, you specify the array name (just as you do in the case of
passing 1D array) followed by number of rows and columns. In the function declaration, the
array data type is followed by two pairs of brackets, the first of which is empty because the
number of rows need not be specified explicitly. The second pair of brackets provides an explicit
size specification for the number of columns. See the example below:
Example 8.11. This program inputs and displays the elements of a matrix.
#include<stdio.h>
void printMatrix(int [][5],int,int);
main()
{
int a[5][5],m,n,i,j;
printf("How many rows and columns you want?\n");
scanf("%d %d",&m,&n);
printf("Enter the elements\n");
for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
printMatrix(a,m,n);
}
void printMatrix(int a[][5],int m,int n)
{

8
int i,j;
printf("The array elements are\n");
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
printf("%d ",a[i][j]);
printf("\n");
}
}

8.6.3 Passing string to a function


Recall that strings are one dimensional char arrays. So strings can be passed to a function in
the same way as an 1D array.

Example 8.12. This example inputs a string and toggles (changes) the case of its individual
characters, i.e., lower case characters are changed to upper case and vice versa. The ASCII
range of upper case letters is from 65 to 90 and that of lower case characters is from 97 to 122.
Thus to convert lower case to upper case, you need to subtract 32 from the ASCII value and
to convert upper case to lower case, you need to add 32. This results in the code below:
#include<stdio.h>
#include<string.h>
void toggleCase(char str[],int n)
{
int i;
printf("The original string is %s\n",str);
for(i=0;i<n;i++)
{
if(str[i]>=’A’&&str[i]<=’Z’)
str[i]+=32;
else if(str[i]>=’a’&&str[i]<=’z’)
str[i]-=32;
}
printf("The string after toggling case is: %s",str);
}
main()
{
char str[20];
printf("Please enter a string\n");
gets(str);
toggleCase(str,strlen(str));
}

8.7 Recursion
You can call any function inside any other function. Thus, a function can call itself too. In
such a case, the function is said to be recursive. Recursion is a process by which a function
calls itself repeatedly, until some specified condition has been satisfied. The process is used

9
for repetitive computations in which each action is stated in terms of a previous result. Many
iterative (i.e., repetitive) problems can be written in this form. A classic application of recursion
is in calculating the factorial of a number. Recall that factorial of a number is the product of
all the integers between 1 and that number. For example, 4 factorial is 4 × 3 × 2 × 1. This
can also be expressed as 4! = 4 × 3!. Thus in general, n! = n × (n − 1)!. This idea is illustrated
below:

Example 8.13. This program calculates the factorial of a number in a recursive manner. Notice
that since the function is defined before it is called, the declaration is omitted.
#include<stdio.h>
int fact(int n)
{
if(n == 1)
return 1;
else
return n * fact (n-1);
}
main()
{
int n;
printf("Enter a number\n");
scanf("%d",&n);
printf("The factorial of %d is %d\n",n,fact(n));
}
Suppose user inputs a value 5. Thus main() calls fact(5). Now what happens is
fact(5) executes 5 * fact(4)
fact(4) executes 4 * fact(3)
fact(3) executes 3 * fact(2)
fact(2) executes 2 * fact(1)
fact(1) returns 1 to its calling function fact(2)
fact(2) returns 2 * 1 = 2 to its calling function fact(3)
fact(3) returns 3 * 2 = 6 to its calling function fact(4)
fact(4) returns 4 * 6 = 24 to its calling function fact(5)
fact(5) returns 5 * 24 = 120 to its calling function main()

While writing recursive functions, you must have a conditional statement, such as an if,
somewhere to force the function to return without the recursive call being executed. If you
don’t, the function will never return once you call it. For example, the code
main()
{
printf("Will this stop?");
main();
}
will never stop. This is known as infinite recursion, and is generally not considered a good
practice.

10
The condition used to stop the recursion is called base case or anchor condition and it does
not make a recursive call. For the code in Example 8.13, n = 1 is the base case.

8.8 Function Pointers


A function pointer is a pointer that holds the address of a function. The ability of pointers to
point to functions turns out to be an important and useful feature of C. This provides you with
another way of executing functions instead of calling them with their names.

8.8.1 Declaring a function pointer


Declaring a function pointer is pretty easy. This is how you declare a pointer to a function.
return-type (*fpName)(data type list of arguments);
where

→ return-type denotes the return the type of the function whose address, the pointer stores.

→ fpName denotes the name of function pointer.

→ data type list of arguments denotes the list of data types of the arguments. The list
is empty if the function receives no arguments.

Example 8.14. Assume a program contains the following statement


void (*fp)();
This declares a function pointer fp that can point to a function that takes no arguments and
which returns no value. 

More examples of function pointer declarations are illustrated in Table 8.2.

Table 8.2: Declaring function pointers

Arguments
Declaration Pointer Return type
Count Type
int (*fp1)(double); fp1 int 1 double
void (*fp2)(char *); fp2 void 1 char *
double (*fp3)(int, int); fp3 double 2 int and int

8.8.2 Using a function pointer


Once a function pointer is declared, you can make it point to some function and call it through
the function pointer. Just as with arrays, the name of the function denotes its address. Thus
if you have a function declared as
void func();
you can assign the address of func() to the pointer fp declared in Example 8.14. This can be
done as
fp = func; //Beware, there is no parenthesis after function name.

11
Once this is done, you can call the function with the pointer as follows:
(*fp)();
Even if you omit the * like this:
fp();
the function func() will be called and executed.

Example 8.15. This program finds the square of an input number. The function square()
does this. A pointer is declared to point to this function. square() is called using this pointer
and the output is printed.
#include<stdio.h>
int square(int x)
{
return x*x;
}
main()
{
int a,s;
int (*fptr)(int);
printf("Enter a value\n");
scanf("%d",&a);
fptr=square;
s=fptr(a);
printf("%d squared is %d\n",a,s);
}

8.9 Programming examples


Program 8.1. To find the absolute value of an integer.

#include<stdio.h>
int abs(int x)
{
if(x<0)
return -x;
else
return x;
}
main()
{
int num;
printf("Enter a number\n");
scanf("%d",&num);
printf("The absolute value of %d is %d",num,abs(num));
}
Program 8.2. To implement a menu driven calculator

12
#include<stdio.h>
int add(int x,int y)
{
return x+y;
}
int sub(int x,int y)
{
return x-y;
}
int mul(int x,int y)
{
return x*y;
}
float div(int x,int y)
{
return (float)x/y;
}
int mod(int x,int y)
{
return x%y;
}
main()
{
int a,b,ch;
printf("Choose the operation\n");
printf("1 - Addition\n 2 - Subtraction\n 3 - Multiplication\n 4 -
Division\n 5 - Remainder\n");
scanf("%d",&ch);
printf("Enter the two operands\n");
scanf("%d %d",&a,&b);
switch(ch)
{
case 1:
printf("%d + %d = %d",a,b,add(a,b));
break;
case 2:
printf("%d - %d = %d",a,b,sub(a,b));
break;
case 3:
printf("%d * %d = %d",a,b,mul(a,b));
break;
case 4:
printf("%d / %d = %f",a,b,div(a,b));
break;
case 5:
printf("%d mod %d = %d",a,b,mod(a,b));
break;
default:
printf("Enter the correct choice\n");
}

13
}
Program 8.3. To print the perfect numbers in a range.

#include<stdio.h>
int isPerfect(int x)
{
int i,sum=0;
for(i=1;i<=x/2;i++)
if(x%i==0)
sum+=i;
if(sum==x)
return 1;
else
return 0;
}
void printPerfect(int lb,int ub)
{
int i;
printf("The perfect numbers lying between %d and %d is\n",lb,ub);
for(i=lb;i<=ub;i++)
if(isPerfect(i)==1)
printf("%d ",i);
}
main()
{
int lb,ub;
printf("Enter the lower and upper bounds of the range\n");
scanf("%d %d",&lb,&ub);
printPerfect(lb,ub);
}
Program 8.4. To compute the value of ex as the sum of the following series upto n terms:

x2 x3 x4
x
e =1+x+ + + + ······
2! 3! 4!

#include<stdio.h>
#include<math.h>
int fact(int n)
{
if(n == 0)
return 1;
else
return n * fact(n-1);
}
main()
{
int n,i,x;
float sum=0.0;
printf("How many terms in the series you want to add?\n");

14
scanf("%d",&n);
printf("Value of x please..\n");
scanf("%d",&x);
for(i=0;i<n;i++)
sum+=pow(x,i)/fact(i);
printf("The sum of %d terms in the series is %f\n",n,sum);
}
Program 8.5. To compute the value of e−x as the sum of the following series upto n terms:

−x x2 x3 x4
e =1−x+ − + + ······
2! 3! 4!

#include<stdio.h>
#include<math.h>
int fact(int n)
{
if(n == 0)
return 1;
else
return n * fact(n-1);
}
main()
{
int n,i,x;
float sum=0.0;
printf("How many terms in the series you want to add?\n");
scanf("%d",&n);
printf("Value of x please..\n");
scanf("%d",&x);
for(i=0;i<n;i++)
sum+=pow(-x,i)/fact(i);
printf("The sum of %d terms in the series is %f\n",n,sum);
}
Program 8.6. To print the nth Fibonacci number.

#include<stdio.h>
int fib(int x)
{
if(x==0)
return 0;
else if(x==1)
return 1;
else
return fib(x-1) + fib(x-2);
}
main()
{
int n;
printf("Enter the value of n\n");

15
scanf("%d",&n);
printf("The required Fibonacci number is %d",fib(n));
}
Program 8.7. To print the first n terms of Fibonacci series.

#include<stdio.h>
int fib(int x)
{
if(x==0)
return 0;
else if(x==1)
return 1;
else
return fib(x-1) + fib(x-2);
}
main()
{
int i,n;
printf("Enter the value of n\n");
scanf("%d",&n);
for(i=0;i<n;i++)
printf("%d ",fib(i));
}
Program 8.8. To recursively find the sum of a range of numbers.

#include<stdio.h>
int sumRange(int low,int high)
{
if(low>high)
return 0;
else
return low + sumRange(low+1,high);
}
main()
{
int lb,ub;
printf("Enter the limits of the range\n");
scanf("%d %d",&lb,&ub);
printf("Sum of numbers lying between %d and %d is
%d\n",lb,ub,sumRange(lb,ub));
}
Program 8.9. To print the nth prime number.

#include<stdio.h>
int isPrime(int num)
{
int i,flag=1;
for(i=2;i<=num/2;i++)
{

16
if(num%i==0)
{
flag=0;
break;
}
}
if(flag==0)
return 0;
else
return 1;
}
main()
{
int n,i,count=0,num=2;
printf("Enter the value of n\n");
scanf("%d",&n);
while(count<n)
{
if(isPrime(num)==1)
{
count++;
if(count==n)
{
printf("The required prime number is %d",num);
break;
}
}
num++;
}
}
Program 8.10. To recursively find the sum of digits of a number.

#include<stdio.h>
int sumDigits(int n)
{
if(n==0)
return 0;
else
return n%10 + sumDigits(n/10);
}
main()
{
int n;
printf("Enter a number\n");
scanf("%d",&n);
printf("Sum of digits of %d is %d\n",n,sumDigits(n));
}

17

You might also like