Pop Module 3
Pop Module 3
Module – III
Course Instructor
Ms. Vishnupriya G M
Assistant Professor,
Dept. of CSE, EPCET
MODULE 3
Functions
Introduction
C enables its programmers to break up a program into segments commonly known as functions,
each of which can be written more or less independently of the others.
Every function in the program is supposed to perform a well-defined task.
Therefore, the program code of one function is completely insulated from the other functions.
Definition
“The set of instructions that performs some specific, well-defined task is called as a Function.”
Or
“Function is a small program or program segment that carryout some specific well-defined
tasks”.
Fig. 1.9 explains how the main() function calls another function to perform a well-defined task.
In the figure, we can see that main() calls a function named func1(). Therefore, main() is known as the
calling function and func1() is known as the called function.
The moment the compiler encounters a function call, the control jumps to the statements that are a
part of the called function.
After the called function is executed, the control is returned to the calling program.
Using Functions
While using functions, we will be using the following terminologies:
A function f that uses another function g is known as the calling function, and g is known as the
called function.
The inputs that a function takes are known as arguments.
When a called function returns some result back to the calling function, it is said to return that
result.
The calling function may or may not pass parameters to the called function. If the called function
accepts arguments, the calling function will pass parameters, else not.
Function declaration is a declaration statement that identifies a function’s name, a list of
arguments that it accepts, and the type of data it returns.
Function definition consists of a function header that identifies the function, followed by the body
of the function containing the executable code for that function.
Types of Functions
i. Library Functions/Pre-Defined/ Built-in Functions
C Library of C Compiler has a collection of various functions which perform some standard and pre-
defined tasks.
These functions written by designers of C Compilers are called as Library functions/Pre-Defined/Built-in
functions.
Ex: sqrt(n)- computes square root of n.
pow(x,y)- computes 𝑥 𝑦 .
printf()- used to print the data on the screen.
scanf()- used to read the data from the keyboard.
abs(x)- computes absolute value of x.
Function Definition
When a function is defined, space is allocated for that function in the memory.
A function definition comprises of two parts:
Function header
Function body
The syntax of a function definition can be given as:
return_data_type function_name(data_type variable1, data_type variable2,..)
{
.............
statements
.............
return(variable);
}
The number of arguments and the order of arguments in the function header must be the same as
that given in the function declaration statement.
While return_data_type function_name(data_type variable1, data_type variable2,...) is known as
the function header, the rest of the portion comprising of program statements within the curly
brackets { } is the function body which contains the code to perform the specific task.
Note that the function header is same as the function declaration. The only difference between the two
is that a function header is not followed by a semi-colon.
Ex: int add(int a,int b)
{
int sum;
sum=a+b;
return sum;
}
Function Call
The function call statement invokes the function.
When a function is invoked, the compiler jumps to the called function to execute the statements
that are a part of that function.
Once the called function is executed, the program control passes back to the calling function. A
function call statement has the following syntax:
function_name(variable1, variable2, ...);
The following points are to be noted while calling a function:
Function name and the number and the type of arguments in the function call must be same
as that given in the function declaration and the function header of the function definition.
Names (and not the types) of variables in function declaration, function call, and header of
function definition may vary.
Arguments may be passed in the form of expressions to the called function. In such a case,
arguments are first evaluated and converted to the type of formal parameter and then the body
of the function gets executed.
If the return type of the function is not void, then the value returned by the called function may
be assigned to some variable as given below.
variable_name = function_name(variable1, variable2, ...);
Ex: add(a,b);
return STATEMENT
The return statement terminates the execution of the called function and returns control to the
calling function.
When the return statement is encountered, the program execution resumes in the calling function at
the point immediately following the function call.
A return statement may or may not return a value to the calling function.
The syntax of return state can be given as
return <expression>;
Here expression is placed in between angular brackets because specifying an expression is
optional.
A function that has void return type cannot return any value to the calling function.
1. Call by Value
In this method, the called function creates new variables to store the value of the arguments
passed to it. Therefore, the called function uses a copy of the actual arguments to perform its
intended task.
If the called function is supposed to modify the value of the parameters passed to it, then the
change will be reflected only in the called function. In the calling function, no change will be
made to the value of the variables. This is because all the changes are made to the copy of the
variables and not to the actual variables.
void main()
{
int a,b, res;
printf(“Enter the values of a and b:”);
scanf(“%d%d”,&a,&b);
res = add(a,b);
printf(“result =%d\n”, res);
}
Following are the points to remember while passing arguments to a function using the call-by value
method:
When arguments are passed by value, the called function creates new variables of the same
data type as the arguments passed to it.
The values of the arguments passed by the calling function are copied into the newly created
variables.
Values of the variables in the calling functions remain unaffected when the arguments are
passed using the call-by-value technique.
2. Call by Reference
When the calling function passes arguments to the called function using the call-by-value
method, the only way to return the modified value of the argument to the caller is explicitly
using the return statement. A better option is to pass arguments using the call-by-reference
technique.
In this method, we declare the function parameters as references rather than normal variables.
When this is done, any changes made by the function to the arguments it received are also
visible in the calling function.
To indicate that an argument is passed using call by reference, an asterisk (*) is placed after the type
in the parameter list. Hence, in the call-by-reference method, a function receives an implicit
reference to the argument, rather than a copy of its value. Therefore, the function can modify the
value of the variable and that change will be reflected in the calling function as well.
Example:
1. Write a C program to add two numbers using call by reference.
#include<stdio.h>
void main()
{
int a,b, res;
printf(“Enter the values of a and b:”);
scanf(“%d%d”,&a,&b);
res = add(&a,&b);
printf(“result =%d\n”, res);
}
2. Write a C program to swap two numbers using call by reference.
#include<stdio.h>
void swap(int *a,int *b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void main()
{
int a,b;
printf(“Enter the values of a and b:”);
scanf(“%d%d”,&a,&b);
printf(“Before swapping: a=%d\tb=%d”, a, b); After swapping: a=20 b=10
swap(&a,&b);
printf(“After swapping: a=%d\tb=%d”, a, b)
}
Output:
Enter the values of a and b: 10 20
Before swapping: a=10 b=20
After swapping: a=20 b=10
Advantages
Since arguments are not copied into the new variables, it provides greater time and space efficiency.
The function can change the value of the argument and the change is reflected in the calling
function.
A function can return only one value. In case we need to return multiple values, we can pass those
arguments by reference, so that the modified values are visible in the calling function.
Disadvantages
However, the drawback of using this technique is that if inadvertent changes are caused to variables
in called function then these changes would be reflected in calling function as original values
would have been overwritten.
Scope of Variables
In C, all constants and variables have a defined scope.
By scope we mean the accessibility and visibility of the variables at different points in the
program.
A variable or a constant in C has four types of scope: block, function, program, and file.
i) Block Scope
We have studied that a statement block is a group of statements enclosed within opening and
closing curly brackets { }.
If a variable is declared within a statement block then as soon as the control exits that block, the
variable will cease to exist.
Such a variable also known as a local variable is said to have a block scope.
So far we had been using local variables.
For example, if we declare an integer x inside a function, then that variable is unknown to the rest of
the program (i.e., outside that function).
Variables declared with same names as those in outer block mask the outer block variables while
executing the inner block.
In nested blocks, variables declared outside the inner blocks are accessible to the nested blocks,
provided these variables are not re-declared within the inner block.
Place of Declaration: The Global variables are declared outside all the functions including main(). It
is always recommended to declare them on top of the program code.
Name conflict: If we have a variable declared in a function that has same name as that of the global
variable, then the function will use the local variable declared within it and ignore the global variable.
Consider the following program,
#include <stdio.h >
int x = 10;
void print();
void main()
{
printf(“\n The value of x in the main() = %d”, x);
int x = 2;
printf(“\n The value of local variable x in the main() = %d", x);
print();
}
void print()
{
printf(“\n The value of x in the print() = %d”, x);
}
Output:
The value of x in the main() = 10
The value of local variable x in the main()= 2
The value of x in the print () = 10
Storage Classes
Storage class defines the scope (visibility) and lifetime of variables and/or functions declared
within a C program.
In addition to this, the storage class gives the following information about the variable or the function.
The storage class of a function or a variable determines the part of memory where storage space
will be allocated for that variable or function (whether the variable function will be stored in a
register or in RAM).
It specifies how long the storage allocation will continue to exist for that function or variable.
It specifies the scope of the variable or function.
It specifies whether the variable or function has internal, external, or no linkage.
It specifies whether the variable will be automatically initialized to zero or to any
indeterminate value.
C supports four storage classes: automatic, register, external, and static.
The general syntax for specifying the storage class of a variable can be given as:
<storage_class_specifier> <data type > <variable name>
Recursion
“The process in which a function calls itself again and again is called as Recursion”.
A recursive function is defined as a function that calls itself to solve a smaller version of its task
until a final call is made which does not require a call to itself.
Since a recursive function repeatedly calls itself, it makes use of the system stack to temporarily store
the return address and local variables of the calling function. Every recursive solution has two major
cases. They are:
Base case, in which the problem is simple enough to be solved directly without making any
further calls to the same function.
Recursive case, in which first the problem at hand is divided into simpler sub-parts. Second the
function calls itself but with sub-parts of the problem obtained in the first step. Third, the result is
obtained by combining the solutions of simpler sub-parts.
Ex: To calculate n!, we multiply the number with factorial of the number that is 1 less than that number.
In other words, n! = n × (n–1)!
Every recursive function must have a base case and a recursive case. For the factorial function,
Base case is when n = 1, because if n = 1, the result will be 1 as 1! = 1.
Recursive case of the factorial function will call itself but with a smaller value of n, this case can
be given as:
factorial(n) = n × factorial (n–1)
Example:
1. Write a C program to calculate factorial of a given number.
#include<stdio.h>
int factorial(int n)
{
if(n==1)
return 1;
else
return (n*fact(n-1));
}
void main()
{
int n,fact;
printf(“Enter a number:”);
scanf(“%d”,&n);
fact=factorial(n);
printf(“\nFactorial of given number=%d”,fact);
}
void main()
{
int x, y, res;
printf("\n Enter the two numbers: ");
scanf("%d %d", &x, &y);
res = GCD(x, y);
printf("\n GCD = %d", x, y, res);
}
Function Parameters
“The list of variables defined in the function header within the parenthesis are called Function
parameters”.
There are 2 types of parameters in ‘C’ functions.
i. Actual parameters
ii. Formal parameters
Declaration of Arrays
An array must be declared before being used.
Arrays are declared using the following syntax:
type name[size];
Declaring an array means specifying the following:
Data type—the kind of values it can store, for example, int, char, float, double, or any other valid
data type..
Name—to identify the array.
Size—the maximum number of values that the array can hold. i.e., the maximum number of
elements that can be stored in the array.
For example, if we write,
int marks[10];
then the statement declares marks to be an array containing 10 elements. In C, the array index starts
from zero. The first element will be stored in marks[0], second element in marks[1], and so on. Therefore,
the last element, that is the 10th element, will be stored in marks[9]. Note that 0, 1, 2, 3 written within
square brackets are the subscripts. In the memory, the array will be
stored as shown in Fig. 3.2.
Figure 3.5 shows the result of the code shown in Fig. 3.4. The code accesses every individual element
of the array and sets its value to –1. In the for loop, first the value of marks[0] is set to –1, then the
value of the index (i) is incremented and the next value, that is, marks[1] is set to –1. The procedure
continues until all the 10 elements of the array are set to –1.
While initializing the array at the time of declaration, the programmer may omit the size of the array.
For example,
int marks[ ]= {98, 97, 90};
The above statement is absolutely legal. Here, the compiler will allocate enough space for all the
initialized elements. Note that if the number of values provided is less than the number of elements in
the array, the un-assigned elements are filled with zeros. Figure 3.8 shows the initialization of arrays.
In the code, we start at the index i at 0 and input the value for the first element of the array. Since the
array has 10 elements, we must input values for elements whose index varies from 0 to 9.
3. Assigning Values to Individual Elements
The third way is to assign values to individual elements of the array by using the assignment
operator.
Any value that evaluates to the data type as that of the array can be assigned to the individual array
element.
A simple assignment statement can be written as
marks[3] = 100;
Here, 100 is assigned to the fourth element of the array which is specified as marks[3].
To copy an array, you must copy the value of every element of the first array into the elements of the
second array. Figure 3.10 illustrates the code to copy an array. In Fig. 3.10, the loop accesses each
element of the first array and simultaneously assigns its value to the corresponding element of the
second array. The index value i is incremented to access the next element in succession. Therefore,
when this code is executed, arr2[0] = arr1[0], arr2[1] = arr1[1], arr2[2] = arr1[2], and so on.
For example, if we want to fill an array with even integers (starting from 0), then we will write the code
as shown in Fig. 3.11. In the code, we assign to each element a value equal to twice of its index, where
the index starts from 0. So after executing this code, we will have arr[0] = 0, arr[1] = 2, arr[2] = 4, and
so on.
Operations on Arrays
There are a number of operations that can be performed on arrays.
These operations include:
Traversing an array
Inserting an element in an array
Searching an element in an array
Deleting an element from an array
Merging two arrays
Sorting an array in ascending or descending order
Traversing an Array
Traversing an array means accessing each and every element of the array for a specific purpose.
Traversing the data elements of an array A can include printing every element, counting the total
number of elements, or performing any process on these elements.
The algorithm for array traversal is given in Fig. 3.12.
In Step 1, we initialize the index to the lower bound of the array. In Step 2, a while loop is executed.
Step 3 processes the individual array element as specified by the array name and index value. Step 4
increments the index value so that the next array element could be processed. The while loop in Step 2
is executed until all the elements in the array are processed, i.e., until I is less than or equal to the upper
bound of the array.
Examples:
Write a program to read and display n numbers using an array.
#include <stdio.h>
void main()
{
int i, n, a[10];
printf("Enter the number of elements in the array : ");
scanf("%d", &n);
printf(“Enter the array elements:\n”);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
printf("The array elements are:\n ");
for(i=0;i<n;i++)
printf("%d\n", a[i]);
}
Output
Enter the number of elements in the array: 5
Enter the array elements:
1
2
3
4
5
The array elements are:
1
2
3
4
5
If we have two sorted arrays and the resultant merged array also needs to be a sorted one, then the task
of merging the arrays becomes a little difficult. The task of merging can be explained using Fig. 3.19.
1. Linear Search
Linear search, also called as sequential search, is a very simple method used for searching an array
for a particular value.
It works by comparing the value to be searched with every element of the array one by one in a
sequence until a match is found.
Linear search is mostly used to search an unordered list of elements (array in which data elements are
not sorted).
For example, if an array A[] is declared and initialized as, int A[ ] = {10, 8, 2, 7, 3, 4, 9, 1, 6, 5}; and
the value to be searched is VAL = 7, then searching means to find whether the value ‘7’ is present in
the array or not. If yes, then it returns the position of its occurrence. Here, POS = 3 (index starting from
0).
Figure 14.1 shows the algorithm for linear search. In Steps 1 and 2 of the algorithm, we initialize the
value of POS and I. In Step 3, a while loop is executed that would be executed till I is less than N (total
number of elements in the array). In Step 4, a check is made to see if a match is found between the
current array element and VAL. If a match is found, then the position of the array element is printed,
else the value of I is incremented to match the next element with VAL. However, if all the array
elements have been compared with VAL and no match is found, then it means that VAL is not present
in the array.
Example:
Write a program to search an element in an array using the linear search technique.
#include <stdio.h>
Like C libraries, programmers can also write their own functions and use them from different
points in the main program or any other program that needs its functionalities.
When a big program is broken into comparatively smaller functions, then different programmers
working on that project can divide the workload by writing different functions.
Using Functions
While using functions, we will be using the following terminologies:
A function f that uses another function g is known as the calling function, and g is known as the
called function.
The inputs that a function takes are known as arguments.
When a called function returns some result back to the calling function, it is said to return that
result.
The calling function may or may not pass parameters to the called function. If the called function
accepts arguments, the calling function will pass parameters, else not.
Function declaration is a declaration statement that identifies a function’s name, a list of
arguments that it accepts, and the type of data it returns.
Function definition consists of a function header that identifies the function, followed by the body
of the function containing the executable code for that function.
Types of Functions
i. Library Functions/Pre-Defined/ Built-in Functions
C Library of C Compiler has a collection of various functions which perform some standard and pre-
defined tasks.
These functions written by designers of C Compilers are called as Library functions/Pre-Defined/Built-in
functions.
Ex: sqrt(n)- computes square root of n.
pow(x,y)- computes 𝑥 𝑦 .
printf()- used to print the data on the screen.
scanf()- used to read the data from the keyboard.
abs(x)- computes absolute value of x.
low high
First, we shall determine middle position of the array by using this formula −
mid = (low + high) / 2
Here it is, mid=(0 + 9) / 2 = 4 (integer value of 4.5). So, 4 is the mid of the array.
Now we compare the value stored at location 4, with the value being searched, i.e. 31. We find that the
value at location 4 is 27, which is not a match. Since the key element is greater than the middle element,
we should search the key element in the upper part of the array
low high
We change our low to mid + 1 and find the new mid value again.
low = mid + 1=4+1=5
mid = (low + high) /2= (5+9)/2 =7
Our new mid is 7 now. We compare the value stored at location 7 with our key value 31.
mid
low high
The value stored at location 7 is not a match; rather it is more than what we are looking for. Since the
key element is less than the middle element, we should search the key element in the lower part of the
array.
We change our high to mid - 1 and find the new mid value again.
high=mid-1 = mid -1=7-1=6
low high
mid = (low + high) / 2 = (5+6)/2 =5
low high
We compare the value stored at location 5 with our key value. We find that it is a match.
Example: C Program to search key elements in array using binary search algorithms.
#include <stdio.h>
#include<stdlib.h>
void main()
{
int i, low, high, mid, n, key, a[100];
printf("Enter number of elements in array:\n");
scanf("%d",&n);
printf("Enter integer numbers in ascending order:\n");
for (i = 0; i< n; i++)
scanf("%d",&a[i]);
printf("Enter value to Search\n");
scanf("%d", &key);
low = 0; Enter integer numbers in
high = n - 1; ascending order:
while (low <= high)
{
mid = (low+high)/2;
if (key == a[mid])
{
printf("%d found at location %d.\n", key, mid+1);
exit(0);
}
if (key > a[mid] )
low = mid + 1;
if (key < a[mid])
high = mid - 1;
}
printf(" %d is Not found! \n", key);
In the above example, only one element of the array is passed to the called function. This is done by
using the index expression. Here, arr[3] evaluates to a single integer value.
2. Passing Addresses
Like ordinary variables, we can pass the address of an individual array element by preceding the
indexed array element with the address operator.
Therefore, to pass the address of the fourth element of the array to the called function, we will write
&arr[3].
However, in the called function, the value of the array element must be accessed using the indirection
(*) operator. Look at the code shown in Fig. 3.21(b).
Hence, we see that a 2D array is treated as a collection of 1D arrays. Each row of a 2D array corresponds
to a 1D array consisting of n elements, where n is the number of columns. To understand this, we can
also see the representation of a two-dimensional array as shown in Fig. 3.28.
There are two ways of storing a two-dimensional array in the memory. The first way is the row major
order and the second is the column major order.
In a row major order, the elements of the first row are stored before the elements of the second
and third rows. That is, the elements of the array are stored row by row where n elements of the first
row will occupy the first n locations. This is illustrated in Fig. 3.29.
However, when we store the elements in a column major order, the elements of the first column
are stored before the elements of the second and third column. That is, the elements of the array
are stored column by column where m elements of the first column will occupy the first m locations.
This is illustrated in Fig. 3.30.
Example:
Write a C program to read and print the elements of a 2D array.
#include <stdio.h>
void main()
{
int arr[2][2], i, j, m, n;
printf(“Enter the size of the array:”);
scanf(“%d%d”,&m,&n);
printf(“Enter the elements of the array:\n);
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
scanf("%d", &arr[i][j]);
}
}
printf(“The elements of the array are:\n);
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
printf("%d\t", arr[i][j]);
}
printf("\n");
}
}
Operations on Two-Dimensional Arrays
Two-dimensional arrays can be used to implement the mathematical concept of matrices.
In mathematics, a matrix is a grid of numbers, arranged in rows and columns.
Thus, using two dimensional arrays, we can perform the following operations on an m×n matrix:
1. Transpose
Transpose of an m × n matrix A is given as a n × m matrix B, where
Bi,j = Aj,i.
2. Sum
Two matrices that are compatible with each other can be added together, storing the result in the third
matrix. Two matrices are said to be compatible when they have the same number of rows and columns.
The elements of two matrices can be added by writing:
Ci,j = Ai,j + Bi,j
3. Difference
Two matrices that are compatible with each other can be subtracted, storing the result in the third
matrix. Two matrices are said to be compatible when they have the same number of rows and columns.
The elements of two matrices can be subtracted by writing:
Ci,j = Ai,j – Bi,j
4. Product
Two matrices can be multiplied with each other if the number of columns in the first matrix is equal to
the number of rows in the second matrix. Therefore, m × n matrix A can be multiplied with a p × q
matrix B if n=p. The dimension of the product matrix is m × q. The elements of two matrices can be
multiplied by writing:
Ci,j = Ʃ Ai,k B k,j for k = 1 to n
Example:
1. Write a C program to transpose a 3 × 3 matrix.
#include <stdio.h>
void main()
{
int i, j, mat[3][3], transposed_mat[3][3];
printf("\n Enter the elements of the matrix ");
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
scanf("%d", &mat[i][j]);
}
}
printf("\n The elements of the matrix are ");
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%d\t", mat[i][j]);
}
printf("\n");
}
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
transposed_mat[i][j] = mat[j][i];
}
2. Write a program to input two m × n matrices and then calculate the sum of their corresponding
elements and store it in a third m × n matrix.
#include <stdio.h>
#include<stdlib.h>
void main()
{
int i, j, m, n, p, q, a[5][5], b[5][5], c[5][5];
printf("\n Enter the number of rows and columns in the first matrix : ");
scanf("%d%d",&m,&n);
printf("\n Enter the number of rows and columns in the second matrix : ");
scanf("%d%d",&p,&q);
if(m != p || n != q)
{
printf("\n Number of rows and columns of both matrices must be equal");
exit(0);
}
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
c[i][j] = a[i][j] + b[i][j];
}
Passing Addresses
Calling function Called function
main() void func(int *num)
{ {
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}}; printf("%d", *num);
func(&arr[1][1]); }
}
2. Passing a Row
A row of a two-dimensional array can be passed by indexing the array name with the row number.
Look at Fig. 3.32 which illustrates how a single row of a two-dimensional array can be passed to the
called function.
Calling function Called function
main() void func(int arr[])
{ {
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}}; int i;
func(arr[1]); for(i=0;i<5;i++)
} printf("%d", arr[i]);
}
Multi-Dimensional Arrays
A multi-dimensional array in simple terms is an array of arrays.
As we have one index in a one-dimensional array, two indices in a two-dimensional array, in the
same way, we have n indices in an n-dimensional array or multi-dimensional array.
Conversely, an n–dimensional array is specified using n indices.
An n-dimensional m1 × m2 ×m3 × ... × mn array is a collection of m1 × m2 × m3 × ...× m n elements. In
a multi-dimensional array, a particular element is specified by using n subscripts as A[I1 ][I2 ][I3 ]...[In],
Figure 3.33 shows a three-dimensional array. The array has three pages, four rows, and two columns.
Example:
1. Write a program to read and display a 2 × 2 × 2 array.
#include <stdio.h>
void main()
{
int array[2][2][2], i, j, k;
Applications of Arrays
• Storing and Accessing Sequential Data