Uploaded by akulahuja2784

Lect 09-30 combined

advertisement
1-D Arrays
Click to add text
1
Array

Many applications require multiple data items that
have common characteristics

In mathematics, we often express such groups of data
items in indexed form:


x1, x2, x3, …, xn
Array is a data structure which can represent a
collection of data items which have the same data
type (float/int/char/…)
2
Example: Printing Numbers in
Reverse
4 numbers
3 numbers
int a, b, c;
scanf(“%d”, &a);
scanf(“%d”, &b);
scanf(“%d”, &c);
printf(“%d ”, c);
printf(“%d ”, b);
printf(“%d \n”, a);
int a, b, c, d;
scanf(“%d”, &a);
scanf(“%d”, &b);
scanf(“%d”, &c);
scanf(“%d”, &d);
printf(“%d ”, d);
printf(“%d ”, c);
printf(“%d ”, b);
printf(“%d \n”, a);
3
The Problem






Suppose we have 10 numbers to handle
Or 20
Or 100
Where do we store the numbers ? Use 100 variables
??
How to tackle this problem?
Solution:

Use arrays
4
Printing in Reverse Using Arrays
int main()
{
int n, A[100], i;
printf(“How many numbers to read? “);
scanf(“%d”, &n);
for (i = 0; i < n; ++i)
scanf(“%d”, &A[i]);
for (i = n -1; i >= 0; --i)
printf(“%d ”, A[i]);
printf(“\n”);
return 0;
}
Using Arrays


All the data items constituting the group share the
same name
int x[10];
Individual elements are accessed by specifying
the index
x[0] x[1] x[2]
x[9]
X is a 10-element one
dimensional array
6
First example
“data refers to a block of 10
int main()
integer variables, data[0], data[1],
{
…, data[9]
int i;
int data[10];
for (i=0; i<10; i++) data[i]= i;
i=0;
while (i<10)
{
printf("Data[%d] = %d\n", i, data[i]);
i++;
}
return 0;
}
7
The result
Array size should be a constant
int main()
{
int i;
int data[10];
for (i=0; i<10; i++) data[i]= i;
i=0;
while (i<10)
{
printf("Data[%d] = %d\n", i, data[i]);
i++;
}
return 0;
}
Output
Data[0] = 0
Data[1] = 1
Data[2] = 2
Data[3] = 3
Data[4] = 4
Data[5] = 5
Data[6] = 6
Data[7] = 7
Data[8] = 8
Data[9] = 9
8
Declaring Arrays


Like variables, the arrays used in a program must be
declared before they are used
General syntax:
type array-name [size];
 type specifies the type of element that will be
contained in the array (int, float, char, etc.)
 size is an integer constant which indicates the
maximum number of elements that can be stored
inside the array
int marks[5];
 marks
is an array that can store a maximum of 5
integers
9

Examples:
int x[10];
char line[80];
float points[150];
char name[35];

If we are not sure of the exact size of the array,
we can define an array of a large size
int marks[50];
though in a particular run we may only be using,
say, 10 elements
10
Accessing Array Elements

A particular element of the array can be accessed by
specifying two things:
Name of the array
 Index (relative position) of the element in the array



Important to remember: In C, the index of an array
starts from 0, not 1
Example:
An array is defined as int x[10];
 The first element of the array x can be accessed as
x[0], fourth element as x[3], tenth element as x[9], etc.

11
Contd.


The array index can be any expression that evaluates
to an integer between 0 and n-1 where n is the
maximum number of elements possible in the array
a[x+2] = 25;
b[3*x-y] = a[10-x] + 5;
Remember that each array element is a variable in
itself, and can be used anywhere a variable can be
used (in expressions, assignments, conditions,…)
12
How is an array stored in memory?

Starting from a given memory location, the
successive array elements are allocated space in
consecutive memory locations
Array A



x: starting address of the array in memory
k: number of bytes allocated per array element
A[i]  is allocated memory location at address x + i*k
13
A Special Operator: AddressOf (&)



Remember that each variable is stored at a memory
location with an unique address
Putting & before a variable name gives the starting
address of the variable (where it is stored, not the
value)
Can be put before any variable (with no blank in
between)
int a =10;
printf(“Value of a is %d, and address of a is
%d\n”, a, &a);
14
Example
Output
&Data[0] = 3221224480
&Data[1] = 3221224484
int main()
{
int i;
int data[10];
for(i=0; i<10; i++)
printf("&Data[%d] = %u\n", i, &data[i]);
return 0;
}
&Data[2] = 3221224488
&Data[3] = 3221224492
&Data[4] = 3221224496
&Data[5] = 3221224500
&Data[6] = 3221224504
&Data[7] = 3221224508
&Data[8] = 3221224512
&Data[9] = 3221224516
15
Initialization of Arrays



General form:
type array_name[size] = { list of values };
Examples:
int marks[5] = {72, 83, 65, 80, 76};
char name[4] = {‘A’, ‘m’, ‘i’, ‘t’};
The size may be omitted. In such cases the
compiler automatically allocates enough space
for all initialized elements
int flag[ ] = {1, 1, 1, 0};
char name[ ] = {‘A’, ‘m’, ‘i’, ‘t’};
16
How to read the elements of an
array?



By reading them one element at a time
for (j=0; j<25; j++)
scanf (“%f”, &a[j]);
The ampersand (&) is necessary
The elements can be entered all in one line or in
different lines
17
A Warning


In C, while accessing array elements, array bounds
are not checked
Example:
int marks[5];
:
:
marks[8] = 75;
The above assignment would not necessarily cause an
error
 Rather, it may result in unpredictable program results,
which are very hard to debug

18
Reading into an array
int main() {
const int MAX_SIZE = 100;
int i, size;
float marks[MAX_SIZE];
float total;
scanf("%d",&size);
for (i=0, total=0; i<size; i++)
{
scanf("%f",&marks[i]);
total = total + marks[i];
}
printf("Total = %f \n Avg = %f\n", total,
total/size);
return 0;
}
Output
4
2.5
3.5
4.5
5
Total = 15.500000
Avg = 3.875000
19
How to print the elements of an
array?

By printing them one element at a time
for (j=0; j<25; j++)
printf (“\n %f”, a[j]);
 The elements are printed one per line
printf (“\n”);
for (j=0; j<25; j++)
printf (“ %f”, a[j]);
 The elements are printed all in one line (starting with a
new line)
20
How to copy the elements of one
array to another?

By copying individual elements
for (j=0; j<25; j++)
a[j] = b[j];

The element assignments will follow the rules
of assignment expressions

Destination array must have sufficient size
21
Example 1: Find the minimum of a
set of 10 numbers
int main()
{
int a[10], i, min;
for (i=0; i<10; i++)
scanf (“%d”, &a[i]);
min = a[0];
for (i=1; i<10; i++)
{
if (a[i] < min)
min = a[i];
}
printf (“\n Minimum is %d”, min);
return 0;
}
22
Alternate Version 1
const int size = 10;
int main()
{
int a[size], i, min;
for (i=0; i<size; i++)
scanf (“%d”, &a[i]);
Change only one
line to change the
problem size
min = a[0];
for (i=1; i<size; i++)
{
if (a[i] < min)
min = a[i];
}
printf (“\n Minimum is %d”, min);
return 0;
}
23
Alternate Version 2
#define size 10
int main()
{
int a[size], i, min;
for (i=0; i<size; i++)
scanf (“%d”, &a[i]);
Change only one
line to change the
problem size
min = a[0];
for (i=1; i<size; i++)
{
if (a[i] < min)
min = a[i];
}
printf (“\n Minimum is %d”, min);
return 0;
Used #define macro
}
24
#define macro


#define X Y
Preprocessor directive
 The
#include you have been using is also a
preprocessor directive


Compiler will first replace all occurrences of
string X with string Y in the program, then
compile the program
Similar effect as read-only variables (const), but
no storage allocated
25
Alternate Version 3
int main()
{
int a[100], i, min, n;
scanf (“%d”, &n); /* Number of elements */
for (i=0; i<n; i++)
scanf (“%d”, &a[i]);
Define an array of
large size and use
only the required
number of elements
min = a[0];
for (i=1; i<n; i++)
{
if (a[i] < min)
min = a[i];
}
printf (“\n Minimum is %d”, min);
return 0;
}
26
const int nsub = 6;
Example 2:
Computing
cgpa
int main()
{
int grade_pt[nsub], cred[nsub], i, gp_sum=0,
cred_sum=0;
double gpa;
for (i=0; i<nsub; i++)
scanf (“%d %d”, &grade_pt[i], &cred[i]);
Handling two arrays
at the same time
for (i=0; i<nsub; i++)
{
gp_sum += grade_pt[i] * cred[i];
cred_sum += cred[i];
}
gpa = ((float) gp_sum) / cred_sum;
printf (“\n Grade point average: is %.2lf”, gpa);
return 0;
}
27
Things you cannot do

You cannot

use = to assign one array variable to another
a = b; /* a and b are arrays */

use == to directly compare array variables
if (a = = b) ………..

directly scanf or printf arrays
printf (“……”, a);
28
Character Arrays and Strings
char C[8] = { 'a', 'b', 'h', 'i', 'j', 'i', 't', '\0' };





C[0] gets the value 'a', C[1] the value 'b', and so on.
The last (7th) location receives the null character ‘\0’
Null-terminated (last character is ‘\0’) character arrays
are also called null-terminated strings or just strings.
Strings can be initialized in an alternative way. The
last declaration is equivalent to:
char C[8] = "abhijit";
The trailing null character is missing here. C
automatically puts it at the end if you define it like this
Note also that for individual characters, C uses single
quotes, whereas for strings, it uses double quotes
29
Reading strings: %s format
int main()
{
char name[25];
scanf("%s", name);
printf("Name = %s \n", name);
return 0;
}
%s reads a string into a character array
given the array name or start address.
It ends the string with the special “null” character ‘\0’.
30
Example: Finding length of a string
#define SIZE 25
int main()
{
int i, length=0;
char name[SIZE];
scanf("%s", name);
printf("Name = %s \n", name);
for (i=0; name[i]!='\0'; i++)
length++;
printf(“Length = %d\n", length);
return 0;
}
Output
Satyanarayana
Name = Satyanarayana
Length = 13
Note that character strings read
in %s format end with ‘\0’
31
Example: Counting the number of a’s
#define SIZE 25
int main()
{
int i, count=0;
char name[SIZE];
scanf("%s", name);
printf("Name = %s \n", name);
for (i=0; name[i]!='\0'; i++)
if (name[i] == 'a') count++;
printf("Total a's = %d\n", count);
return 0;
}
Output
Satyanarayana
Name = Satyanarayana
Total a's = 6
Note that character strings read
in %s format end with ‘\0’
32
Example: Palindrome Checking
int main()
{
int i, flag, count=0;
char name[25];
scanf("%s", name);
/* Read Name */
for (i=0; name[i]!='\0'; i++); /* Find Length of String */
count=i; flag = 0;
/* Loop below checks for palindrome by comparison*/
for(i=0; i<count; i++)
if (name[i]!=name[count-i-1])
flag = 1;
if (flag ==0) printf ("%s is a Palindrome\n", name);
else printf("%s is NOT a Palindrome\n", name);
return 0;
}
33
Use of 1D Arrays in
Sorting
34
Sorting Data Items

A Sorting technique is used to rearrange a given array
elements according to a comparison operator on the
elements.

Consider a set of data items

Each item may have more than one field


Example: a student record with name, roll no, CGPA,…
Sort the set in ascending/descending order of some key value
(some value of the data)

Sort a set of integers (the key value is the value of the integer)

Sort a set of student records according to roll no (the key value is roll
no, though a student record has other values too)
35
Assumptions



For the sorting techniques, we will take the input as
an array of integers
The sorting technique will reposition the elements in
the array such that they are sorted in ascending order
Same technique can be used to sort any other data
type or sort in descending order
36
Different Sorting Techniques








Selection sort
Bubble sort
Insertion sort
Mergesort
Quicksort
Heapsort
Bucket sort
….
Will be discussed later
in this course
37
Selection Sort
38
Selection sort

Step 1 − Set MIN to location 0

Step 2 − Search the minimum element in the list

Step 3 − Swap with value at location MIN

Step 4 − Increment MIN to point to next element

Step 5 − Repeat until list is sorted
39
Selection sort
Input: 64 25 12 22 11
11 25 12 22 64
11 12 25 22 64
11 12 22 25 64
11 12 22 25 64
40
Selection sort
int main()
{
int i, j, min_indx, data[100], n, t;
scanf(“%d”, &n);
for (i = 0; i < n; i++) scanf(“%d”, &data[i]);
for (i = 0; i < n-1; i++)
{
min_indx = i;
for (j = i+1; j < n; j++) {
if (data[j] < data[min_indx]) min_indx = j;}
t = data[i]; data[i] = data[min_indx]; data[min_indx] = t;
}
}
41
Bubble Sort
42
Bubble sort
Bubble Sort is the simplest sorting algorithm that works by repeatedly swapping the
adjacent elements if they are in wrong order.
Example: Input: 5 1 4 2 8
First Pass:
( 5 1 4 2 8 ) –> ( 1 5 4 2 8 )
( 1 5 4 2 8 ) –> ( 1 4 5 2 8 )
( 1 4 5 2 8 ) –> ( 1 4 2 5 8 )
( 1 4 2 5 8 ) –> ( 1 4 2 5 8 )
Second Pass:
( 1 4 2 5 8 ) –> ( 1 4 2 5 8 )
( 1 4 2 5 8 ) –> ( 1 2 4 5 8 )
( 1 2 4 5 8 ) –> ( 1 2 4 5 8 )
( 1 2 4 5 8 ) –> ( 1 2 4 5 8 )
Third Pass:
( 1 2 4 5 8 ) –> ( 1 2 4 5 8 )
( 1 2 4 5 8 ) –> ( 1 2 4 5 8 )
( 1 2 4 5 8 ) –> ( 1 2 4 5 8 )
( 1 2 4 5 8 ) –> ( 1 2 4 5 8 )
43
Bubble sort
int main()
{
int i, j, data[100], n;
scanf(“%d”, &n);
for (i = 0; i < n; i++) scanf(“%d”, &data[i]);
for (i = 0; i < n-1; i++) {
for (j = 0; j < n-i-1; j++) {
if (data[j] > data[j+1]) {
t = data[j]; data[j] = data[j+1]; data[j+1] = t;}
}
}
}
44
Practice Problems
1.
2.
3.
4.
Read in an integer n (n < 25). Read n integers in an array A. Then do the following
(write separate programs for each, only the reading part is common).
1.
find the sum of the absolute values of the integers.
2.
Copy the positive and negative integers in the array into two additional arrays
B and C respectively. Print A, B, and C.
3.
Exchange the values of every pair of values from the start (so exchange A[0]
and A[1], A[2] and A[3] and so on). If the number of elements is odd, the last
value should stay the same.
Read in two integers n and m (n, m < 50). Read n integers in an array A. Read m
integers in an array B. Then do the following (write separate programs for each,
only the reading part is common).
1.
Find if there are any two elements x, y in A and an element z in B, such that x
+y=z
2.
Copy in another array C all elements that are in both A and B (intersection)
3.
Copy in another array C all elements that are in either A and B (union)
4.
Copy in another array C all elements that are in A but not in B (difference)
Read in two null-terminated strings A and B (using %s. Assume max characters <
25 in each). Create another string C that is the concatenation of A and B (A
followed by B). Print A, B, C using %s
Read in two null-terminated strings A and B. Check if A is lexicographically smaller,
45
larger, or equal to B and print appropriate messages in each case.
Functions
1
Function



A program segment that carries out some specific,
well-defined task
Example
 A function to add two numbers
 A function to find the largest of n numbers
A function will carry out its intended task whenever it
is called or invoked
 Can be called multiple times
2


A function is a block of statements that performs a
specific task.
Say you are writing a C program and you need to
perform a same task in that program more than once.
In such case you have two options:
a) Use the same set of statements every time you want
to perform the task
b) Write a function to perform that task, and just call it
every time you need to perform that task.
3




Every C program consists of one or more functions
One of these functions must be called main
Execution of the program always begins by carrying
out the instructions in main
Functions call other functions as instructions
4
Function Control Flow
void print_banner ()
{
printf(“************\n”);
}
int main ()
{
...
print_banner ();
...
print_banner ();
}
int main ()
{
print_banner ();
print_banner {
}
print_banner {
print_banner ();
}
}
5

Calling function (caller) may pass information to the
called function (callee) as parameters/arguments


For example, the numbers to add
The callee may return a single value to the caller

Some functions may not return anything
6
Calling function (Caller)
Called function (Callee)
int main()
{
float cent, fahr;
scanf(“%f”,&cent);
fahr = cent2fahr(cent);
printf(“%fC = %fF\n”,
cent, fahr);
return 0;
}
Parameter
float cent2fahr(float data)
{
float result;
result = data*9/5 + 32;
return result;
}
Parameter passed
Returning value
Calling/Invoking the cent2fahr function
7
How it runs
float cent2fahr(float data)
{
float result;
printf(“data = %f\n”, data);
result = data*9/5 + 32;
printf(“result = %f\n”, result);
return result;
}
int main()
{ float cent, fahr;
scanf(“%f”,&cent);
printf(“Input is %f\n”, cent);
fahr = cent2fahr(cent);
printf(“%fC = %fF\n”, cent, fahr);
return 0;
}
Outputs
32
Input is 32.000000
data = 32.000000
result = 89.599998
32.000000C = 89.599998F
-45.6
Input is -45.599998
data = -45.599998
result = -50.079998
-45.599998C = -50.079998F
8
What will be the output?
float cent2fahr(float data)
{
float result;
printf(“data = %f\n”, data);
result = data*9/5 + 32;
return result;
printf(“result = %f\n”, result);
}
int main()
{ float cent, fahr;
scanf(“%f”,&cent);
printf(“Input is %f\n”, cent);
fahr = cent2fahr(cent);
printf(“%fC = %fF\n”, cent, fahr);
return 0;
}
Outputs
32
Input is 32.000000
data = 32.000000
32.000000C = 89.599998F
-45.6
Input is -45.599998
data = -45.599998
-45.599998C = -50.079998F
9
Another Example
int factorial (int m)
{
int i, temp=1;
for (i=1; i<=m; i++)
temp = temp * i;
return (temp);
}
int main()
{
int n;
for (n=1; n<=5; n++)
printf (“%d! = %d \n”,
n, factorial (n) );
return 0;
}
Output
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
10
Why Functions?

Allows one to develop a program in a modular
fashion







Divide-and-conquer approach
Construct a program from small pieces or components
Use existing functions as building blocks for new
programs - reusability of the code
Abstraction: hide internal details (library functions)
To improve the readability of code.
Debugging of the code would be easier
Reduces the size of the code, duplicate set of
statements are replaced by function calls.
11
Defining a Function

A function definition has two parts:
 The first line, called header
 The body of the function
return-value-type function-name ( parameter-list )
{
declarations and statements
}
12


The first line contains the return-value-type, the
function name, and optionally a set of commaseparated arguments enclosed in parentheses
 Each argument has an associated type
declaration
 The arguments are called formal arguments or
formal parameters
The body of the function is actually a block of
statement that defines the action to be taken by the
function
13
Return-value type
Formal parameters
int gcd (int A, int B)
{
int temp;
while ((B % A) != 0) {
temp = B % A;
B = A;
A = temp;
}
Value returned
return (A);
}
BODY
14
Return value

A function can return a value



Using return statement
Like all values in C, a function return value has a type
The return value can be assigned to a variable in the
caller
int x, y, z;
scanf(“%d%d”, &x, &y);
z = gcd(x,y);
printf(“GCD of %d and %d is %d\n”, x, y, z);
15
Function Not Returning Any Value

Example: A function which prints if a number is
divisible by 7 or not
void div7 (int n)
{
Return type is void
if ((n % 7) == 0)
printf (“%d is divisible by 7”, n);
else
printf (“%d is not divisible by 7”, n);
return;
Optional
}
16
return statement



In a value-returning function (result type is not void), return
does two distinct things
 specify the value returned by the execution of the
function
 terminate that execution of the callee and transfer control
back to the caller
A function can only return one value
 The value can be any expression matching the return
type
 but it might contain more than one return statement.
In a void function
 return is optional at the end of the function body.
 return may also be used to terminate execution of the
function explicitly.
17
 No return value should appear following return.
void compute_and_print_itax ()
{
float income;
scanf (“%f”, &income);
Terminate function
if (income < 50000) {
execution before
printf (“Income tax = Nil\n”);
reaching the end
return;
}
if (income < 60000) {
printf (“Income tax = %f\n”, 0.1*(income-50000));
return;
}
if (income < 150000)
{
printf (“Income tax = %f\n”, 0.2*(income-60000)+1000);
return ;
}
printf (“Income tax = %f\n”, 0.3*(income-150000)+19000);
}
18
Calling a function


Called by specifying the function name and parameters
in an instruction in the calling function
When a function is called from some other function, the
corresponding arguments in the function call are called
actual arguments or actual parameters



The function call must include a matching actual parameter
for each formal parameter
Position of an actual parameters in the parameter list in the
call must match the position of the corresponding formal
parameter in the function definition
The formal and actual arguments must match in their data
types
19
Functions
(Contd…)
20
Example
Formal parameters
double operate (double x, double y, char op)
{
int main ()
switch (op) {
{
case ‘+’ : return x+y+0.5 ;
double x, y, z;
case ‘~’ : if (x>y)
char op;
return x-y + 0.5;
...
return y-x+0.5;
z = operate (x, y, op);
case ‘x’ : return x*y + 0.5;
...
default : return –1;
}
}
}
Actual parameters
21

When the function is executed, the value of the actual
parameter is copied to the formal parameter
parameter passing
int main ()
{
...
double circum;
...
area1 = area(circum/2.0);
...
}
double area (double r)
{
return (3.14*r*r);
}
22
Another Example
/* Compute the GCD of four numbers */
int main()
{
int n1, n2, n3, n4, result;
scanf (“%d %d %d %d”, &n1, &n2, &n3, &n4);
result = gcd ( gcd (n1, n2), gcd (n3, n4) );
printf (“The GCD of %d, %d, %d and %d is %d \n”,
n1, n2, n3, n4, result);
return 0;
}
func-gcd.c
23
Another Example
int main()
{
int numb, flag, j=3;
scanf(“%d”,&numb);
while (j <=numb)
{
flag = prime(j);
if (flag==0)
printf(“%d is prime\n”,j);
j++;
}
return 0;
}
int prime(int x)
{
int i, test;
i=2, test =0;
while ((i <= sqrt(x)) && (test
==0))
{
if (x%i==0) test = 1;
i++;
}
return test;
}
24
Tracking the flow of control
int main()
{
int numb, flag, j=3;
scanf(“%d”,&numb);
printf(“numb = %d \n”,numb);
while (j <= numb)
{ printf(“Main, j = %d\n”,j);
flag = prime(j);
printf(“Main, flag = %d\n”,flag);
if (flag == 0)
printf(“%d is prime\n”,j);
j++;
}
return 0;
}
int prime(int x)
{
int i, test;
i = 2; test = 0;
printf(“In function, x = %d \n”,x);
while ((i <= sqrt(x)) && (test == 0))
{
if (x%i == 0) test = 1;
i++;
}
printf(“Returning, test = %d \n”,test);
return test;
}
25
The output
5
numb = 5
Main, j = 3
In function, x = 3
Returning, test = 0
Main, flag = 0
3 is prime
Main, j = 4
In function, x = 4
Returning, test = 1
Main, flag = 1
Main, j = 5
In function, x = 5
Returning, test = 0
Main, flag = 0
5 is prime
26
Points to note


The identifiers used as formal parameters are “local”.
 Not recognized outside the function
 Names of formal and actual arguments may differ
A value-returning function is called by including it in
an expression
 A function with return type T (≠ void) can be used
anywhere an expression of type T can be used
27

Returning control back to the caller
 If nothing returned
 return;
 or, until reaches the last right brace ending the
function body
 If something returned
 return expression;
28
Function Prototypes

Usually, a function is defined before it is called
 main() is the last function in the program written
 Easy for the compiler to identify function definitions
in a single scan through the file

However, many programmers prefer a top-down
approach, where the functions are written after main()
 Must be some way to tell the compiler
 Function prototypes are used for this purpose
 Only needed if function definition comes after
use
29
 Function
prototypes are usually written at the
beginning of a program, ahead of any functions
(including main())
 Prototypes can specify parameter names or just
types (more common)
 Examples:
int gcd (int , int );
void div7 (int number);
 Note the semicolon at the end of the line.
 The parameter name, if specifed, can be
anything; but it is a good practice to use the
same names as in the function definition
30
Example:
#include <stdio.h>
int sum(int, int);
int main()
{
int x, y;
scanf(“%d%d”, &x, &y);
printf(“Sum = %d\n”, sum(x, y));
}
int sum (int a, int b)
{
return(a + b);
}
31
Example:
#include <stdio.h>
int sum (int a, int b)
{
return(a + b);
}
int main()
{
int x, y;
scanf(“%d%d”, &x, &y);
printf(“Sum = %d\n”, sum(x, y));
}
32
Some more points

A function cannot be defined within another
function


All function definitions must be disjoint
Nested function calls are allowed
A calls B, B calls C, C calls D, etc.
 The function called last will be the first to return


A function can also call itself, either directly or in a
cycle
A calls B, B calls C, C calls back A.
 Called recursive call or recursion

33
Example: main calls ncr, ncr calls fact
int ncr (int n, int r);
int fact (int n);
int main()
{
int i, m, n, sum=0;
scanf (“%d %d”, &m, &n);
for (i=1; i<=m; i+=2)
sum = sum + ncr (n, i);
printf (“Result: %d \n”,
sum);
return 0;
}
int ncr (int n, int r)
{
return (fact(n) / fact(r) /
fact(n-r));
}
int fact (int n)
{
int i, temp=1;
for (i=1; i<=n; i++)
temp *= i;
return (temp);
}
34
Local variables


A function can define its own local variables
The locals have meaning only within the function
 Each
execution of the function uses a new set of
locals
 Local variables cease to exist when the function
returns

Parameters are also local
35
Local variables
/* Find the area of a circle with diameter d */
double circle_area (double d)
{
double radius, area;
radius = d/2.0;
area = 3.14*radius*radius;
return (area);
}
parameter
local
variables
36
Revisiting nCr
int fact(int x)
{ int i,fact=1;
for(i=2; i<=x; ++i) fact=fact*i;
return fact;
}
int ncr(int x,int y)
{
int p,q,r;
p=fact(x);
q=fact (y);
r = fact(x-y);
return p/(q*r);
}
int main()
{
int n, r;
scanf(“%d%d”,&n,&r);
printf(“n=%d, r=%d,
nCr=%d\n”,n, r, ncr(n,r));
return 0;
}
The variable x in function fact and
x in function ncr are different.
The values computed from the
arguments at the point of call are
copied on to the corresponding
parameters of the called function
before it starts execution.
37
Scope of a variable




Part of the program from which the value of the variable
can be used (seen)
Scope of a variable - Within the block in which the variable
is defined
 Block = group of statements enclosed within { }
Local variable – scope is usually the function in which it is
defined
 So two local variables of two functions can have the
same name, but they are different variables
Global variables – declared outside all functions (even
main)
 scope is entire program by default, but can be hidden in
a block if local variable of same name defined
38
#include <stdio.h>
int A = 1;
int main()
Global variable
{
myProc();
printf ( "A = %d\n", A);
}
void myProc()
{ int A = 2;
if ( A==2 )
{
int A = 3;
printf ( "A = %d\n", A);
}
printf ( "A = %d\n", A);
}
Variable
Scope
Hides the global A
Output:
A= 3
A= 2
A= 1
39
Functions
(Contd…)
40
Parameter Passing: by Value and
by Reference


Used when invoking functions
Call by value
 Passes the value of the argument to the function
 Execution of the function does not change the
actual parameters



All changes to a parameter done inside the function are
done on a copy of the actual parameter
The copy is removed when the function returns to the
caller
The value of the actual parameter in the caller is not
affected
 Avoids
accidental changes
41

Call by reference
 Passes the address to the original argument.
 Execution of the function may affect the original
 Not directly supported in C except for arrays
42
Parameter passing & return: 1
int main()
{
int a=10, b;
printf (“Initially a = %d\n”, a);
b = change (a);
printf (“a = %d, b = %d\n”, a, b);
return 0;
}
int change (int x)
{
printf (“Before x = %d\n”,x);
x = x / 2;
printf (“After x = %d\n”, x);
return (x);
}
Output
Initially a = 10
Before x = 10
After x = 5
a = 10, b = 5
43
Parameter passing & return: 2
int main()
{
int x=10, b;
printf (“M: Initially x = %d\n”, x);
b = change (x);
printf (“M: x = %d, b = %d\n”, x, b);
return 0;
}
int change (int x)
{
printf (“F: Before x = %d\n”,x);
x = x / 2;
printf (“F: After x = %d\n”, x);
return (x);
}
Output
M: Initially x = 10
F: Before x = 10
F: After x = 5
M: x = 10, b = 5
44
Parameter passing & return: 3
int main()
{
int x=10, b;
printf (“M: Initially x = %d\n”, x);
x = change (x); b = x;
printf (“M: x = %d, b = %d\n”, x, x);
return 0;
}
int change (int x)
{
printf (“F: Before x = %d\n”,x);
x = x / 2;
printf (“F: After x = %d\n”, x);
return (x);
}
Output
M: Initially x = 10
F: Before x = 10
F: After x = 5
M: x = 5, b = 5
45
Parameter passing & return: 4
int main()
{
int x=10, y=5;
printf (“M1: x = %d, y = %d\n”, x, y);
interchange (x, y);
printf (“M2: x = %d, y = %d\n”, x, y);
return 0;
}
void interchange (int x, int y)
{ int temp;
printf (“F1: x = %d, y = %d\n”, x, y);
temp= x; x = y; y = temp;
printf (“F2: x = %d, y = %d\n”, x, y);
}
Output
M1: x = 10, y = 5
F1: x = 10, y = 5
F2: x = 5, y = 10
M2: x = 10, y = 5
How do we write an
interchange function?
(will see later)
46
Passing Arrays to Function

Array element can be passed to functions as ordinary
arguments
 IsFactor (x[i], x[0])
 sin (x[5])
47
Passing Entire Array to a Function


An array name can be used as an argument to a
function
 Permits the entire array to be passed to the function
 The way it is passed differs from that for ordinary
variables
Rules:
 The array name must appear by itself as argument,
without brackets or subscripts
 The corresponding formal argument is written in the
same manner
 Declared by writing the array name with a pair of
empty brackets
48
Whole Array as Parameters
const int ASIZE = 5;
float average (int B[ ])
Only Array Name/address passed.
{
[ ] mentioned to indicate that
int i, total=0;
is an array.
for (i=0; i<ASIZE; i++)
total = total + B[i];
return ((float) total / (float) ASIZE);
}
int main ( ) {
int x[ASIZE] ; float x_avg;
x = {10, 20, 30, 40, 50};
x_avg = average (x) ;
return 0;
}
Called only with actual array name
49
Contd.
We don’t need to
write the array size.
It works with arrays
of any size.
int main()
{
int n;
float list[100], avg;
:
avg = average (n, list);
:
}
float average (int a, float x[])
{
:
sum = sum + x[i];
}
50
Arrays used as Output Parameters
void VectorSum (int a[ ], int b[ ], int vsum[ ], int length) {
int i;
for (i=0; i<length; i=i+1)
vsum[i] = a[i] + b[i] ;
}
void PrintVector (int a[ ], int length) {
int i;
for (i=0; i<length; i++) printf (“%d “, a[i]);
}
int main () {
int x[3] = {1,2,3}, y[3] = {4,5,6}, z[3];
VectorSum (x, y, z, 3) ;
PrintVector (z, 3) ;
return 0;
}
51
The Actual Mechanism

When an array is passed to a function, the values
of the array elements are not passed to the
function
 The array name is interpreted as the address of
the first array element
 The formal argument therefore becomes a
pointer to the first array element
 When an array element is accessed inside the
function, the address is calculated using the
formula stated before
 Changes made inside the function are thus also
reflected in the calling program
52
Contd.



Passing parameters in this way is called
call-by-reference
Normally parameters are passed in C using
call-by-value
Basically what it means?
 If a function changes the values of array elements,
then these changes will be made to the original
array that is passed to the function
 This does not apply when an individual element is
passed on as argument
53
Library Functions
54
Library Functions





Set of functions already written for you, and bundled
in a “library”
Example: printf, scanf, getchar,
C library provides a large number of functions for
many things
Already seen math library functions earlier
Will look at string library functions
55
String Library Functions


String library functions
 perform common operations on null terminated
strings
 Must include a special header file
#include <string.h>
Example
 printf ("%f", strlen(C));
 C is a null-terminated string
 Calls function strlen, which returns the
number of characters in C (not counting the
‘\0’ character)
56
Common string library functions





strlen – returns the length of a string
strcmp – compares two strings (lexicographic)
 Returns 0 if the two strings are equal, < 0 if first string is
less than the second string, > 0 if the first string is greater
than the second string
 Commonly used for sorting strings
strcat – concatenates two strings
strcpy – copy one string to another
 we will need some basic knowledge of pointers to
understand how to use strcat and strcpy
Many others, but these are the ones you will know in this
course
57
#include <stdio.h>
#include <string.h>
Example
int main()
{
char A[20], B[20];
int n, m, val;
scanf(“%s%s”, A, B);
n = strlen(A);
m = strlen(B);
printf(“The lengths of the strings are %d and %d\n”, n, m);
val = strcmp(A, B);
if (val == 0)
printf(“The strings are the same\n”);
else if (val < 0)
printf(“%s is smaller than %s\n”, A, B);
else
printf(“%s is greater than %s\n”, A, B);
}
58
Outputs
program program
The lengths of the strings are 7 and 7
The strings are the same
arobinda abhijit
The lengths of the strings are 8 and 7
arobinda is larger than abhijit
iit-kgp iit-mandi
The lengths of the strings are 7 and 9
iit-kgp is smaller than iit-mandi
arobinda Arobinda
The lengths of the strings are 8 and 8
arobinda is larger than Arobinda
59
Practice Problems

No separate problems needed. Look at everything
that you did so far, such as finding sum, finding
average, counting something, checking if something
is true or false (“ Is there an element in array A such
that….) etc. in which the final answer is one thing only
(like sum, count, 0 or 1,…). Then for each of them,
rather than doing it inside main (as you have done so
far), write it as a function with appropriate
parameters, and call from main() to find and print.

Normally, read and print everything from main(). Do
not read or print anything inside the function. This will
give you better practice. However, you can write
simple functions for printing an array.
60
Recursion
Click to add text
Part I (Lecture 15)
1
Recursion
■
A function calls itself:
◻ Either directly.
■ f1 calls f1. f1(){f1();}
◻ Or cyclically.
■
f1 calls f2, and f2 calls f1
f1(){f2();} f2(){f1();}
■
f1
f1
f2
Used for repetitive computations in
which each action is stated in terms of a
previous result (recurrence).
fact(n) = n * fact (n-1)
2
Why Use Recursion?
■
Pro:
◻
◻
◻
■
Allows us to write elegant and simple code
for certain complex problems
Small, compact code, less effort
Easy to modify, debug???
Con:
◻
◻
Higher overhead: Large number of recursive
calls
Confusing for beginners
Recursion: Basics
■
For a problem to be written in recursive form, two
conditions are to be satisfied:
◻
It should be possible to express the problem in recursive
form
■
◻
Solution of the problem in terms of solution of the
same problem on smaller sized data
The problem statement must include a stopping condition
fact(n) = 1,
if n = 0
Stopping condition
= n * fact(n-1), if n > 0
Recursive definition
4
■
Examples:
◻
Factorial:
fact(0) = 1
fact(n) = n * fact(n-1), if n > 0
◻
GCD:
gcd (m, m) = m
gcd (m, n) = gcd (m%n, n), if m > n
gcd (m, n) = gcd (n, n%m), if m < n
◻
Fibonacci series (1,1,2,3,5,8,13,21,….)
fib (0) = 1
fib (1) = 1
fib (n) = fib (n-1) + fib (n-2), if n > 1
5
Factorial
fact(1) = 1
fact(n) = n * fact(n-1), if n > 1
long int fact (int n){
if (n == 1)
Stopping condition
return (1);
else
return (n * fact(n-1));
}
Recursive call
6
Factorial Execution
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
7
Factorial Execution
fact(4)
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
8
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
9
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
if (3 = = 1) return (1);
else return (3 * fact(2));
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
10
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
if (3 = = 1) return (1);
else return (3 * fact(2));
if (2 = = 1) return (1);
else return (2 * fact(1));
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
11
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
if (3 = = 1) return (1);
else return (3 * fact(2));
if (2 = = 1) return (1);
else return (2 * fact(1));
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
if (1 = = 1) return (1);
12
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
if (3 = = 1) return (1);
else return (3 * fact(2));
if (2 = = 1) return (1);
else return (2 * fact(1));
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
1
if (1 = = 1) return (1);
13
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
if (3 = = 1) return (1);
else return (3 * fact(2));
2
if (2 = = 1) return (1);
else return (2 * fact(1));
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
1
if (1 = = 1) return (1);
14
Factorial Execution
fact(4)
if (4 = = 1) return (1);
else return (4 * fact(3));
6
if (3 = = 1) return (1);
else return (3 * fact(2));
2
if (2 = = 1) return (1);
else return (2 * fact(1));
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
1
if (1 = = 1) return (1);
15
Factorial Execution
fact(4)
24
if (4 = = 1) return (1);
else return (4 * fact(3));
6
if (3 = = 1) return (1);
else return (3 * fact(2));
2
if (2 = = 1) return (1);
else return (2 * fact(1));
long int fact (int n)
{
if (n = = 1) return (1);
else return (n * fact(n-1));
}
1
if (1 = = 1) return (1);
16
Example: Finding max in an array
int findMax(int A[ ], int n)
{
int temp;
if (n==1)
{
return A[0];
}
temp = findMax(A, n-1);
if (A[n-1] > temp)
return A[n-1];
else return temp;
}
Terminating condition. Small
size problem that you know
how to solve directly without
calling any functions
Recursive call. Find the max
in the first n-1 elements
(exact same problem, just
solved on a smaller array).
Important things to remember
■
■
Think how the whole problem (finding max of n
elements in A) can be solved by solving the exact
same problem on a smaller problem (finding max of
first n-1 elements of the array). But then, do NOT
think how the smaller problem will be solved, just
call the function recursively and assume it will be
solved.
When you write a recursive function
■
■
■
First write the terminating/base condition
Then write the rest of the function
Always double-check that you have both
Back to Factorial: Look at the variable
addresses (a slightly different program) !
int main()
{
int x,y;
scanf("%d",&x);
y = fact(x);
printf ("M: x= %d, y = %d\n", x,y);
return 0;
}
int fact(int data)
{ int val = 1;
printf("F: data = %d, &data = %u \n
&val = %u\n", data, &data, &val);
if (data>1) val = data*fact(data-1);
return val;
}
Output
4
F: data = 4, &data = 3221224528
&val = 3221224516
F: data = 3, &data = 3221224480
&val = 3221224468
F: data = 2, &data = 3221224432
&val = 3221224420
F: data = 1, &data = 3221224384
&val = 3221224372
M: x= 4, y = 24
19
■ The memory addresses for the variable data are
different in different calls!
■ They are not the same variable.
■ Each function call will have its own set of variables,
even if the name of the variable is the same as it is the
same function being called
■ Changes made to one will not be seen by the calling
function on return
20
int main()
{
int x,y;
scanf("%d",&x);
y = fact(x);
printf ("M: x= %d, y = %d\n", x,y);
return 0;
}
int fact(int data)
{
int val = 1, count = 0;
if (data>1) val = data*fact(data-1);
count++;
printf(“count = %d, data = %d\n”,
count, data);
return val;
}
Output
4
count = 1, data = 1
count = 1, data = 2
count = 1, data = 3
count = 1, data = 4
M: x= 4, y = 24
• Count did not change
even though ++ done!
• Each call does it on its
own copy, lost on return
21
Recursion
Part II (Lecture 16)
22
Fibonacci Numbers
0,1, 1, 2, 3, 5, 8, 13, 21, …
◻
◻
F0 = 0 , F1 = 1 (Base Cases)
Rest are sum of preceding two
Fn = Fn-1 + Fn-2 (n > 1)
Leonardo Pisano
Fibonacci (11701250)
Fibonacci’s Problem: Multiplying Mice
Month 1
Month 2
Quite difficult to keep track of the
population explosion.
Month 3
Month 4
Month 5
Month 6
Month 7
Babies
Recursive relation:
#babies in Month 7= #mice in Month 5
#adults in Month 7 = #mice in Month 6
24
The Fibonacci numbers
■f(0)
= 0, f(1) = 1
■f(n) = f(n – 1) + f(n - 2)
■f(0)
=0
■f(1) = 1
■f(2) = f(1) + f(0) = 1 + 0 = 1
■f(3) = f(2) + f(1) = 1 + 1 = 2
■f(4) = f(3) + f(2) = 2 + 1 = 3
■f(5) = f(4) + f(3) = 3 + 2 = 5
■f(6) = f(5) + f(4) = 5 + 3 = 8
25
Fibonacci Numbers
Fibonacci recurrence:
fib(n) = 1 if n = 0 or 1;
= fib(n – 2) + fib(n – 1)
otherwise;
int fib (int n)
{
if (n == 0 or n == 1)
return 1; [BASE]
return fib(n-2) + fib(n-1) ;
[Recursive]
}
26
int fib (int n) {
if (n == 0 || n == 1)
return 1;
return fib(n-2) + fib(n-1) ;
}
Fibonacci recurrence:
fib(n) = 1 if n = 0 or 1;
= fib(n – 2) + fib(n – 1)
otherwise;
fib (5)
fib (3)
fib (1)
fib (0)
fib (4)
fib (2)
fib (1)
fib (2)
fib (0) fib (1)
fib (3)
fib (1)
fib (2)
fib (0)
27
fib (1)
int fib (int n) {
if (n == 0 || n == 1)
return 1;
return fib(n-2) + fib(n-1) ;
}
Fibonacci recurrence:
fib(n) = 1 if n = 0 or 1;
= fib(n – 2) + fib(n – 1)
otherwise;
fib (5)
fib (3)
fib (1)
1
fib (0)
1
fib (4)
fib (2)
fib (1)
1
fib (2)
fib (3)
fib (0) fib (1) fib (1)
1
1
1
fib (2)
fib (0)
1
28
fib (1)
1
fib.c
int fib (int n) {
if (n==0 || n==1)
return 1;
return fib(n-2) + fib(n-1) ;
}
8
fib (5)
Fibonacci recurrence:
fib(n) = 1 if n = 0 or 1;
= fib(n – 2) + fib(n – 1)
otherwise;
3
5
fib (4)
fib (3)
2
1
fib (1)
fib (2)
1
1
1
fib (0) fib (1)
1
1
2
fib (2)
3
fib (3)
2
1
1
1
fib (0) fib (1) fib (1)
1
1
1
29
fib (2)
1
1
fib (0)
fib (1)
1
1
Exercise
■
Write recursive function to compute the sum of
squares of the numbers between two given numbers
m and n.
int sumSquares (int m, int n);
■
First form the recurrence relation:
S(m,n)= m*n if m=n
= S(m,mid)+S(mid+1,n)
30
Sum of Squares
int sumSquares (int m, int n){
int middle ;
if (m == n) return m*m;
else
{
middle = (m+n)/2;
return sumSquares(m,middle)
+ sumSquares(middle+1,n);
}
}
31
Annotated Call Tree
355
sumSquares(5,10)
245
sumSquares(8,10)
110
sumSquares(5,7)
49
61
sumSquares(5,6)
sumSquares(7,7) sumSquares(8,9) sumSquares(10,10)
36
25
sumSquares(5,5) sumSquares(6,6)
25
100
145
36
49
81
64
sumSquares(8,8) sumSquares(9,9)
64
100
81
32
Example: Printing the digits of an Integer in
Reverse
■
Print the last digit, then print the remaining number
in reverse
◻
Ex: If integer is 743, then reversed is print 3 first,
then print the reverse of 74
void printReversed(int i)
{
if (i < 10) {
printf(“%d\n”, i); return;
}
else {
printf(“%d”, i%10);
printReversed(i/10);
}
}
33
Exercise: How to print the numer as it is with
hyphen between digits
■
■
12345  1—2—3—4—5
Head recursion versus tail recursion
void printReversed(int i)
{
if (i < 10) {
printf(“%d---”, i); return;
}
else {
printReversed(i/10);
printf(“%d ---”, i%10);
}
}
34
■
Counting Zeros in a Positive Integer
Check last digit from right
◻
If it is 0, number of zeros = 1 + number of zeroes
in remaining part of the number
◻
If it is non-0, number of zeros = number of zeroes
in remaining part of the number
int zeros(int number)
{
if(number<10) return 0;
if (number%10 == 0)
return(1+zeros(number/10));
else
return(zeros(number/10));
}
35
Example: Binary Search
■
■
Searching for an element k in a sorted array A with n
elements
12
11
22
25
64
Idea:
Choose the middle element A[n/2]
◻ If k == A[n/2], we are done
◻ If k < A[n/2], search for k between A[0] and A[n/2 -1]
◻ If k > A[n/2], search for k between A[n/2 + 1] and A[n-1]
◻ Repeat until either k is found, or no more elements to
search
◻
■
Requires less number of comparisons than linear
search in the worst case (log2n instead of n)
36
int binsearch(int A[ ], int low, int high, int k)
{
12
11
22
25
64
int mid;
printf(“low = %d, high = %d\n”, low, high);
if (low >= high)
return 0;
mid = (low + high)/2;
printf(“mid = %d, A[%d] = %d\n\n”, mid, mid, A[mid]);
if (A[mid] == k)
return 1;
else {
if (A[mid] > k)
return (binsearch(A, low, mid-1, k));
else
return(binsearch(A, mid+1, high, k));
}
}
37
38
int main()
{
int A[25], n, k, i, found;
scanf(“%d”, &n);
for (i=0; i<n; i++) scanf(“%d”, &A[i]);
scanf(“%d”, &k);
found = binsearch(A, 0, n-1, k);
if (found == 1)
printf(“%d is present in the array\n”, k);
else
printf(“%d is not present in the array\n”, k);
}
39
Output
8
9 11 14 17 19 20 23 27
21
low = 0, high = 7
mid = 3, A[3] = 17
8
9 11 14 17 19 20 23 27
14
low = 0, high = 7
mid = 3, A[3] = 17
low = 4, high = 7
mid = 5, A[5] = 20
low = 0, high = 2
mid = 1, A[1] = 11
low = 6, high = 7
mid = 6, A[6] = 23
low = 2, high = 2
mid = 2, A[2] = 14
14 is present in the array
low = 6, high = 5
21 is not present in the array
40
Static Variables
int Fib(int n, int i)
{
int Fib (int, int);
int main()
{
int n;
scanf("%d", &n);
if (n == 0 || n ==1)
printf("F(%d) = %d \n", n, 1);
else
printf("F(%d) = %d \n", n,
Fib(n,2));
return 0;
}
static int m1, m2;
int res, temp;
if (i==2) {m1 =1; m2=1;}
if (n == i) res = m1+ m2;
else
{ temp = m1;
m1 = m1+m2;
m2 = temp;
res = Fib(n, i+1);
}
return res;
}
Static variables remain in existence rather than coming and
going each time a function is activated
41
Static Variables: See the addresses!
int Fib(int n, int i)
{
static int m1, m2;
int res, temp;
if (i==2) {m1 =1; m2=1;}
printf("F: m1=%d, m2=%d, n=%d,
i=%d\n", m1,m2,n,i);
printf("F: &m1=%u, &m2=%u\n",
&m1,&m2);
printf("F: &res=%u, &temp=%u\n",
&res,&temp);
if (n == i) res = m1+ m2;
else { temp = m1; m1 = m1+m2;
m2 = temp;
res = Fib(n, i+1); }
return res;
}
Output
5
F: m1=1, m2=1, n=5, i=2
F: &m1=134518656, &m2=134518660
F: &res=3221224516, &temp=3221224512
F: m1=2, m2=1, n=5, i=3
F: &m1=134518656, &m2=134518660
F: &res=3221224468, &temp=3221224464
F: m1=3, m2=2, n=5, i=4
F: &m1=134518656, &m2=134518660
F: &res=3221224420, &temp=3221224416
F: m1=5, m2=3, n=5, i=5
F: &m1=134518656, &m2=134518660
F: &res=3221224372, &temp=3221224368
F(5) = 8
42
Common Errors in Writing Recursive Methods
■
Non-terminating Recursive Methods (Infinite
recursion):
a)
No base case.
int badFactorial(int x) {
return x * badFactorial(x-1);
}
The base case is never reached for some
parameter values. x) {
int anotherBadFactorial(int
b)
}
if(x == 0)
return 1;
else
return x*(x-1)*anotherBadFactorial(x -2);
// When x is odd, base case never reached!!
Common Errors in Writing Recursive Functions
int badSum1(int x) {
if(x==1) return 1;
return(badSum2(x--));
}
Common Errors in Writing Recursive Functions
■
Mixing up loops and recursion
int anotherBadFactorial(int x) {
int i, fact = 0;
if (x == 0)
return 1;
else {
for (i=x; i>0; i=i-1) {
fact = fact + x*anotherBadFactorial(x-1);
}
return fact;
}
}
■
In general, if you have recursive function calls within a
loop, think carefully if you need it. Most recursive
functions you will see in this course will not need this
Recursion vs. Iteration
■
■
Repetition
◻
Iteration: explicit loop
◻
Recursion: repeated function calls
Termination
◻
Iteration: loop condition fails
◻
Recursion: base case recognized
■
Both can have infinite loops
■
Balance
◻
Choice between performance (iteration) and good
software engineering (recursion).
46
■
Every recursive program can also be written
without recursion
■
Recursion is used for programming
convenience, not for performance
enhancement
■
Sometimes, if the function being computed
has a nice recursive form, then a recursive
code may be more readable
47
Recursion
Part III (Lecture 17)
48
How are function calls implemented?
■
The following applies in general, with minor variations
that are implementation dependent
◻
◻
The system maintains a stack in memory
■
Stack is a last-in first-out structure
■
Two operations on stack, push and pop
Whenever there is a function call, the activation
record gets pushed into the stack
■
Activation record consists of the return address
in the calling program, the return value from the
function, and the local variables inside the
function
49
STACK
int main()
{
……..
x = gcd (a, b);
……..
}
Activation
record
Before call
int gcd (int x, int y)
{
……..
……..
return (result);
}
Local
Variables
Return
Value
Return Addr
After call
After return
50
int main()
{
……..
x = ncr (a, b);
……..
}
int ncr (int n, int r)
{
return (fact(n)/
fact(r)/fact(n-r));
}
3 times
int fact (int n)
{
………
return (result);
}
3 times
LV2, RV2,
RA2
Before call
LV1, RV1,
RA1
LV1, RV1,
RA1
LV1, RV1,
RA1
Call ncr
Call fact
fact returns
ncr returns
51
What happens for recursive calls?
■
■
What we have seen ….
◻
Space for activation record is allocated on the stack
when a function call is made
◻
Space allocated for activation record is de-allocated
on the stack when the function returns
In recursion, a function calls itself
◻
Several function calls going on, with none of the
function calls returning back
■
Space for activation records allocated on the stack
increases continuously
■
Large stack space required
52
◻
■
Space for activation records are de-allocated, when
the termination condition of recursion is reached
We shall illustrate the process by an example of
computing factorial
◻
Activation record looks like:
Local
Variables
Return
Value
Return Addr
53
Example:: main() calls fact(3)
int main()
{
int n;
n = 3;
printf (“%d \n”, fact(n) );
return 0;
}
int fact (int n)
{
if (n = = 0)
return (1);
else
return (n * fact(n-1));
}
54
TRACE OF THE STACK DURING EXECUTION
n=0
1
RA .. fact
fact
returns
to main
n=1
-
n=1
-
n=1
1*1 = 1
RA .. fact
RA .. fact
RA .. fact
n=2
-
n=2
-
n=2
-
n=2
-
n=2
2*1 = 2
RA .. fact
RA .. fact
RA .. fact
RA .. fact
RA .. fact
n=3
-
n=3
-
n=3
-
n=3
-
n=3
-
n=3
-
n=3
3*2 = 6
RA .. main
RA .. main
RA .. main
RA .. main
RA .. main
RA .. main
RA .. main
main
calls
fact
55
Do Yourself
Trace the activation records for the following
version of Fibonacci sequence
■
X
Y
main
int f (int n)
{
int a, b;
if (n < 2) return (n);
else {
a = f(n-1);
b = f(n-2);
return (a+b);
}
}
void main() {
printf(“Fib(4) is: %d \n”, f(4));
}
Local
Variables
(n, a, b)
Return
Value
Return Addr
(either
main,
or X, or Y)
56
Additional Example
57
Towers of Hanoi Problem
1
2
3
4
5
LEFT
CENTER
RIGHT
58
■
Initially all the disks are stacked on the LEFT
pole
■
Required to transfer all the disks to the
RIGHT pole
■
◻
Only one disk can be moved at a time.
◻
A larger disk cannot be placed on a smaller disk
CENTER pole is used for temporary storage
of disks
59
60
■
Recursive statement of the general problem of n
disks
◻
Step 1:
■
◻
Step 2:
■
◻
Move the top (n-1) disks from LEFT to CENTER
Move the largest disk from LEFT to RIGHT
Step 3:
■
Move the (n-1) disks from CENTER to RIGHT
61
Tower of Hanoi
A
B
C
62
Tower of Hanoi
A
B
C
63
Tower of Hanoi
A
B
C
64
Tower of Hanoi
A
B
C
65
Towers of Hanoi function
void towers (int n, char from, char to, char aux)
{
/* Base Condition */
if (n==1) {
printf (“Disk 1 : %c -> &c \n”, from, to) ;
return ;
}
/* Recursive Condition */
towers (n-1, from, aux, to) ;
…………………….
…………………….
}
66
Towers of Hanoi function
void towers (int n, char from, char to, char aux)
{
/* Base Condition */
if (n==1) {
printf (“Disk 1 : %c -> &c \n”, from, to) ;
return ;
}
/* Recursive Condition */
towers (n-1, from, aux, to) ;
printf (“Disk %d : %c -> %c\n”, n, from, to) ;
…………………….
}
67
Towers of Hanoi function
void towers (int n, char from, char to, char aux)
{
/* Base Condition */
if (n==1) {
printf (“Disk 1 : %c -> %c \n”, from, to) ;
return ;
}
/* Recursive Condition */
towers (n-1, from, aux, to) ;
printf (“Disk %d : %c -> %c\n”, n, from, to) ;
towers (n-1, aux, to, from) ;
}
68
TOH runs
void towers(int n, char from, char to, char aux)
{ if (n==1)
{ printf ("Disk 1 : %c -> %c \n", from, to) ;
return ;
}
towers (n-1, from, aux, to) ;
printf ("Disk %d : %c -> %c\n", n, from, to) ;
towers (n-1, aux, to, from) ;
}
int main()
{ int n;
scanf("%d", &n);
towers(n,'A',‘C',‘B');
return 0;
}
Output
3
Disk 1 : A -> C
Disk 2 : A -> B
Disk 1 : C -> B
Disk 3 : A -> C
Disk 1 : B -> A
Disk 2 : B -> C
Disk 1 : A -> C
69
More TOH runs
void towers(int n, char from, char to, char aux)
{ if (n==1)
{ printf ("Disk 1 : %c -> %c \n", from, to) ;
return ;
}
towers (n-1, from, aux, to) ;
printf ("Disk %d : %c -> %c\n", n, from, to) ;
towers (n-1, aux, to, from) ;
}
int main()
{ int n;
scanf("%d", &n);
towers(n,'A',‘C',‘B');
return 0;
}
Output
4
Disk 1 : A -> B
Disk 2 : A -> C
Disk 1 : B -> C
Disk 3 : A -> B
Disk 1 : C -> A
Disk 2 : C -> B
Disk 1 : A -> B
Disk 4 : A -> C
Disk 1 : B -> C
Disk 2 : B -> A
Disk 1 : C -> A
Disk 3 : B -> C
Disk 1 : A -> B
Disk 2 : A -> C
Disk 1 : B -> C
70
Exercise 1: count zeros in an Integer
The problem is: given an integer, how many
of its digits are zero?
Insight:
■
How to get least digit?
■
■
71
Check if that is zero  Based on this,
what can we say about the number of
zeros in the integer?
int zeros( int number){
if(number<10) return 0;
if (number%10 == 0)
return(1+zeros(number/10));
else
return(zeros(number/10));
}
zeros(10200)
zeros(1020)
+ zeros(0)
zeros(102)
+ zeros(0) + zeros(0)
zeros(10)
+ zeros(2) + zeros(0) + zeros(0)
zeros(1) + zeros(0) + zeros(2) + zeros(0) + zeros(0)
Another Approach
int zeros(int numb){
if(numb==0)
// 1 digit (zero/non-zero):
return 1;
// bottom out.
else if(numb < 10)
return 0;
else
// > 1 digits: recursion
return (zeros(numb/10) +
zeros(numb%10));
}
73
Exercise 1
■
■
■
Write a recursive function to compute the nth term of
a series given by the following recurrence relation:
F(0)=0
F(n)=2*F(n-1)+3*F(n-2)+n
74
Exercise 2
■
Write a recursive routine that takes an array and its
size as parameters and computes its mean.
75
Practice Problems
1. Write a recursive function to search for an element in an
array
2. Write a recursive function to count the digits of a positive
integer (do also for sum of digits)
3. Write a recursive function to reverse a null-terminated
string
4. Write a recursive function to convert a decimal number to
binary
5. Write a recursive function to check if a string is a
palindrome or not
6. Write a recursive function to copy one array to another
Note:
• For each of the above, write the main functions to call the
recursive function also
• Practice problems are just for practicing recursion, recursion is
not necessarily the most efficient way of doing them
76
77
2-d Arrays
1
Two Dimensional Arrays


We have seen that an array variable can store
a list of values
Many applications require us to store a table
of values
Subject 1 Subject 2
Student 1
Student 2
Student 3
Student 4
75
68
88
50
82
75
74
65
Subject 3
Subject 4
Subject 5
90
80
85
68
65
70
76
40
76
72
80
70
2
Contd.

The table contains a total of 20 values, five
in each line
 The
table can be regarded as a matrix
consisting of four rows and five columns

C allows us to define such tables of items
by using two-dimensional arrays
3
Declaring 2-D Arrays

General form:
type array_name [row_size][column_size];

Examples:
int marks[4][5];
float sales[12][25];
double matrix[100][100];
4
Initializing 2-d arrays



int a[2][3] = {1,2,3,4,5,6};
int a[2][3] = {{1,2,3}, {4,5,6}};
int a[][3] = {{1,2,3}, {4,5,6}};
All of the above will give the 2x3 array
1
4
2 3
5 6
5
Accessing Elements of a 2-d
Array


Similar to that for 1-d array, but use two indices
 First indicates row, second indicates column
 Both the indices should be expressions which
evaluate to integer values (within range of the
sizes mentioned in the array declaration)
Examples:
x[m][n] = 0;
c[i][k] += a[i][j] * b[j][k];
a = sqrt (a[j*3][k]);
6
Example
int a[3][5];
A two-dimensional array of 15 elements
Can be looked upon as a table of 3 rows and 5 columns
col0
col1
col2
col3
col4
row0
a[0][0]
a[0][1]
a[0][2]
a[0][3]
a[0][4]
row1
a[1][0]
a[1][1]
a[1][2]
a[1][3]
a[1][4]
row2
a[2][0]
a[2][1]
a[2][2]
a[2][3]
a[2][4]
7
How is a 2-d array is stored in
memory?

Starting from a given memory location, the elements
are stored row-wise in consecutive memory locations
(row-major order)



x: starting address of the array in memory
c: number of columns
k: number of bytes allocated per array element
 a[i][j]
 is allocated memory location at
address x + (i * c + j) * k
a[0]0] a[0][1] a[0]2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3]
Row 0
Row 1
Row 2
8
Array Addresses
int main()
{
int a[3][5];
int i,j;
for (i=0; i<3;i++)
{
for (j=0; j<5; j++) printf("%u\n", &a[i][j]);
printf("\n");
}
return 0;
}
Output
3221224480
3221224484
3221224488
3221224492
3221224496
3221224500
3221224504
3221224508
3221224512
3221224516
3221224520
3221224524
3221224528
3221224532
3221224536
9
How to read the elements of a
2-d array?

By reading them one element at a time
for (i=0; i<nrow; i++)
for (j=0; j<ncol; j++)
scanf (“%f”, &a[i][j]);
The ampersand (&) is necessary
 The elements can be entered all in one
line or in different lines

10
How to print the elements of a
2-d array?

By printing them one element at a time
for (i=0; i<nrow; i++)
for (j=0; j<ncol; j++)
printf (“\n %f”, a[i][j]);
 The elements are printed one per line
for (i=0; i<nrow; i++)
for (j=0; j<ncol; j++)
printf (“%f”, a[i][j]);
 The elements are all printed on the same line11
Contd.
for (i=0; i<nrow; i++)
{
printf (“\n”);
for (j=0; j<ncol; j++)
printf (“%f ”, a[i][j]);
}
 The elements are printed nicely in matrix form
12
Example: Matrix Addition
int main()
{
int a[100][100], b[100][100],
c[100][100], p, q, m, n;
for (p=0; p<m; p++)
for (q=0; q<n; q++)
c[p][q] = a[p][q] + b[p][q];
scanf (“%d %d”, &m, &n);
for (p=0; p<m; p++)
{
printf (“\n”);
for (q=0; q<n; q++)
printf (“%d ”, c[p][q]);
}
return 0;
for (p=0; p<m; p++)
for (q=0; q<n; q++)
scanf (“%d”, &a[p][q]);
for (p=0; p<m; p++)
for (q=0; q<n; q++)
scanf (“%d”, &b[p][q]);
}
13
Passing 2-d Arrays as Parameters



Similar to that for 1-D arrays
 The array contents are not copied into the function
 Rather, the address of the first element is passed
For calculating the address of an element in a 2-d
array, we need:
 The starting address of the array in memory
 Number of bytes per element
 Number of columns in the array
The above three pieces of information must be known
to the function
14
Example Usage
int main()
{
int a[15][25], b[15]25];
:
:
add (a, b, 15, 25);
:
}
void add (int x[][25], int
y[][25], int rows, int cols)
{
:
}
We can also write
int x[15][25], y[15][25];
But at least 2nd dimension
must be given
15
Example: Matrix Addition with Functions
void ReadMatrix(int A[][100], int x, int y)
{
int i, j;
for (i=0; i<x; i++)
for (j=0; j<y; j++)
scanf (“%d”, &A[i][j]);
}
void AddMatrix( int A[][100], int B[][100], int C[][100], int x, int y)
{
int i , j;
for (i=0; i<x; i++)
for (j=0; j<y; j++)
C[i][j] = A[i][j] + B[i][j];
}
16
int main()
{
void PrintMatrix(int A[][100], int x, int y)
int a[100][100], b[100][100],
{
c[100][100], p, q, m, n;
int i, j;
printf(“\n”);
scanf (“%d%d”, &m, &n);
for (i=0; i<x; i++)
{
ReadMatrix(a, m, n);
for (j=0; j<y; j++)
ReadMatrix(b, m, n);
printf (“ %5d”, A[i][j]);
printf(“\n”);
AddMatrix(a, b, c, m, n);
}
}
PrintMatrix(c, m, n);
return 0;
}
17
Practice Problems
1.
2.
3.
4.
5.
Write a function that takes an n x n square matrix A as parameter (n
< 100) and returns 1 if A is an upper-triangular matrix, 0 otherwise.
Repeat 1 to check for lower-triangular matrix, diagonal matrix,
identity matrix
Write a function that takes as parameter an m x n matrix A (m, n <
100) and returns the transpose of A (modifies in A only).
Consider an n x n matrix containing only 0 or 1. Write a function that
takes such a matrix and returns 1 if the number of 1’s in each row
are the same and the number of 1’s in each column are the same; it
returns 0 otherwise
Write a function that reads in an m x n matrix A and an n x p matrix
B, and returns the product of A and B in another matrix C. Pass
appropriate parameters.
For each of the above, also write a main function that reads the
matrices, calls the function, and prints the results (a message, the
transposed matrix etc.)
18
Structures
19
What is a Structure?

Used for handling a group of logically
related data items
 Examples:
Student name, roll number, and marks
 Real part and complex part of a complex number

Helps in organizing complex data in a
more meaningful way
 The individual structure elements are
called members

20
Defining a Structure
struct tag {
member 1;
member 2;
:
member m;
};
 struct
is the required C keyword
 tag is the name of the structure
 member 1, member 2, … are individual member
declarations
 Do not forget the ; at the end!
21
Contd.

The individual members can be
ordinary variables, pointers, arrays, or
other structures (any data type)
 The
member names within a particular
structure must be distinct from one another
 A member name can be the same as the
name of a variable defined outside of the
structure

Once a structure has been defined,
the individual structure-type variables
can be declared as:
struct tag var_1, var_2, …, var_n;
22
Example

A structure definition
struct student {
char name[30];
int roll_number;
int total_marks;
char dob[10];
};

Defining structure variables:
struct student a1, a2, a3;
A new data-type
23
A Compact Form

It is possible to combine the declaration of the
structure with that of the structure variables:
struct tag {
member 1;
member 2;
:
member m;
} var_1, var_2,…, var_n;


Declares three variables of type struct tag
In this form, tag is optional
24
Accessing a Structure

The members of a structure are processed
individually, as separate entities


Each member is a separate variable
A structure member can be accessed by
writing
variable.member

where variable refers to the name of a
structure-type variable, and member refers to
the name of a member within the structure
Examples:
a1.name, a2.name, a1.roll_number, a3.dob
25
Example: Complex number addition
struct complex
{
float real;
Defines the structure
float img;
};
int main()
Declares 3 variable of type struct complex
{
struct complex a, b, c;
scanf (“%f %f”, &a.real, &a.img);
Accessing the variables is the same
scanf (“%f %f”, &b.real, &b.img);
as any other variable, just have to
follow the syntax to specify which field
c.real = a.real + b.real;
of the Structure you want
c.img = a.img + b.img;
printf (“\n %f + %f j”, c.real, c.img);
return 0;
}
26
Operations on Structure Variables

Unlike arrays, a structure variable can be
directly assigned to another structure variable
of the same type
a1 = a2;
 All the individual members get assigned

Two structure variables cannot be
compared for equality or inequality
if (a1 == a2)……
this cannot be done
27
Arrays of Structures

Once a structure has been defined, we can
declare an array of structures
struct student class[50];
type name
 The
individual members can be accessed as:
class[i].name
class[5].roll_number
28
Example: Reading and Printing Array of Structures
int main()
{
struct complex A[100];
int n;
scanf(“%d”, &n);
for (i=0; i<n; i++)
scanf(“%f%f”, &A[i].real, &A[i].img);
for (i=0; i<n; i++)
printf(“%f + i%f\n”, A[i].real, A[i].img);
}
29
Arrays within Structures

A structure member can be an array
struct student
{
char name[30];
int roll_number;
int marks[5];
char dob[10];
} a1, a2, a3;

The array element within the structure can
be accessed as:
a1.marks[2], a1.dob[3],…
30
Structure Initialization
Structure variables may be initialized
following similar rules of an array. The
values are provided within the second
braces separated by commas
 An example:

struct complex a={1.0,2.0}, b={-3.0,4.0};
a.real=1.0; a.img=2.0;
b.real=-3.0; b.img=4.0;
31
Parameter Passing in a
Function

Structure variables can be passed as
parameters like any other variables. Only
the values will be copied during function
invocation
int chkEqual(struct complex a, struct complex b)
{
if ((a.real==b.real) && (a.img==b.img))
return 1;
else return 0;
}
32
Returning Structures

It is also possible to return structure values
from a function. The return data type of the
function should be as same as the data type of
the structure itself
struct complex add(struct complex a, struct complex b)
{
struct complex tmp;
tmp.real = a.real + b.real;
tmp.img = a.img + b.img;
return(tmp);
}
Direct arithmetic operations are not possible with structure variables
33
Defining Data Type: using typedef

One may define a structure data-type with a single
name
typedef struct newtype {
member-variable1;
member-variable2;
.
member-variableN;
} mytype;

mytype is the name of the new data-type



Also called an alias for struct newtype
Writing the tag name newtype is optional, can be
skipped
Naming follows rules of variable naming
34
typedef : An example
typedef struct {
float real;
float imag;
} _COMPLEX;

Defined a new data type named _COMPLEX.
Now can declare and use variables of this type
_COMPLEX a, b, c;
35
More about typedef


Note: typedef is not restricted to just structures,
can define new types from any existing type
Example:
 typedef
int INTEGER
 Defines a new type named INTEGER from the
known type int
 Can now define variables of type INTEGER which
will have all properties of the int type
INTEGER a, b, c;
36
The earlier program using typedef
typedef struct{
float real;
float img;
} _COMPLEX;
_COMPLEX add(_COMPLEX a, _COMPLEX b)
{
_COMPLEX tmp;
tmp.real = a.real + b.real;
tmp.img = a.img + b.img;
return(tmp);
}
37
Contd.
void print (_COMPLEX a)
{
printf("(%f, %f) \n",a.real,a.img);
}
Output
(4.000000, 5.000000)
(10.000000, 15.000000)
(14.000000, 20.000000)
int main()
{
_COMPLEX x={4.0,5.0}, y={10.0,15.0}, z;
print(x);
print(y);
z = add(x,y);
print(z);
return 0;
}
swap.c
38
Practice Problems
1.
2.
Extend the complex number program to include functions for addition,
subtraction, multiplication, and division
Define a structure for representing a point in two-dimensional Cartesian
co-ordinate system. Using this structure for a point
Write a function to return the distance between
two given points
2. Write a function to return the middle point of the
line segment joining two given points
3. Write a function to compute the area of a triangle
formed by three given points
4. Write a main function and call the functions from
there after reading in appropriate inputs (the
points) from the keyboard
1.
39
3.
Define a structure STUDENT to store the following data for a student: name (nullterminated string of length at most 20 chars), roll no. (integer), CGPA (float). Then
1.
2.
3.
4.
5.
In main, declare an array of 100 STUDENT structures.
Read an integer n and then read in the details of n students
in this array
Write a function to search the array for a student by name.
Returns the structure for the student if found. If not found,
return a special structure with the name field set to empty
string (just a ‘\0’)
Write a function to search the array for a student by roll no.
Write a function to print the details of all students with
CGPA > x for a given x
Call the functions from the main after reading in name/roll
no/CGPA to search
40
Number
Representation
Part I
1
Basics of Number System

We are accustomed to using the so-called
decimal number system



Ten digits :: 0,1,2,3,4,5,6,7,8,9
Every digit position has a weight which is a
power of 10
Base or radix is 10
Example:
234 = 2 x 102 + 3 x 101 + 4 x 100
250.67 = 2 x 102 + 5 x 101 + 0 x 100 + 6 x 10-1
+ 7 x 10-2
2
Binary Number System

Two digits:




0 and 1
Every digit position has a weight which is a
power of 2
Base or radix is 2
Example:
110 = 1 x 22 + 1 x 21 + 0 x 20
101.01 = 1 x 22 + 0 x 21 + 1 x 20 + 0 x 2-1 + 1
x 2-2
3
Positional Number Systems (General)
Decimal Numbers:
 10 Symbols {0,1,2,3,4,5,6,7,8,9}, Base or Radix is 10
 136.25 = 1  102 + 3  101 + 6  100 + 2  10–1 + 3  10–2
4
Positional Number Systems (General)
Decimal Numbers:
 10 Symbols {0,1,2,3,4,5,6,7,8,9}, Base or Radix is 10
 136.25 = 1  102 + 3  101 + 6  100 + 2  10–1 + 3  10–2
Binary Numbers:
 2 Symbols {0,1}, Base or Radix is 2
 101.01 = 1  22 + 0  21 + 1  20 + 0  2–1 + 1  2–2
5
Positional Number Systems (General)
Decimal Numbers:
 10 Symbols {0,1,2,3,4,5,6,7,8,9}, Base or Radix is 10
 136.25 = 1  102 + 3  101 + 6  100 + 2  10–1 + 5  10–2
Binary Numbers:
 2 Symbols {0,1}, Base or Radix is 2
 101.01 = 1  22 + 0  21 + 1  20 + 0  2–1 + 1  2–2
Octal Numbers:
 8 Symbols {0,1,2,3,4,5,6,7}, Base or Radix is 8
 621.03 = 6  82 + 2  81 + 1  80 + 0  8–1 + 3  8–2
6
Positional Number Systems (General)
Decimal Numbers:
 10 Symbols {0,1,2,3,4,5,6,7,8,9}, Base or Radix is 10
 136.25 = 1  102 + 3  101 + 6  100 + 2  10–1 + 3  10–2
Binary Numbers:
 2 Symbols {0,1}, Base or Radix is 2
 101.01 = 1  22 + 0  21 + 1  20 + 0  2–1 + 1  2–2
Octal Numbers:
 8 Symbols {0,1,2,3,4,5,6,7}, Base or Radix is 8
 621.03 = 6  82 + 2  81 + 1  80 + 0  8–1 + 3  8–2
Hexadecimal Numbers:
 16 Symbols {0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F}, Base is 16
6AF.3C = 6  162 + 10  161 + 15  160 + 3  16–1 + 12  16–2
7
Binary-to-Decimal Conversion

Each digit position of a binary number has a
weight
 Some

power of 2
A binary number:
B = bn-1 bn-2 …..b1 b0 . b-1 b-2 ….. b-m
Corresponding value in decimal:
n-1
D =  bi 2i
i = -m
8
Examples
101011  1x25 + 0x24 + 1x23 + 0x22 + 1x21 + 1x20
= 43
(101011)2 = (43)10
.0101
 0x2-1 + 1x2-2 + 0x2-3 + 1x2-4
= .3125
(.0101)2 = (.3125)10
 1x22 + 0x21 + 1x20 + 1x2-1 + 1x2-2
= 5.75
(101.11)2 = (5.75)10
101.11
9
Decimal to Binary: Integer Part
Consider the integer and fractional parts separately.
For the integer part:

Repeatedly divide the given number by 2, and go on
accumulating the remainders, until the number becomes zero.
Arrange the remainders in reverse order.

Base NumbRem
2
2
2
2
2
2
2
89
44
22
11
5
2
1
0
1
0
0
1
1
0
1
(89)10 = (1011001)2
10
Decimal to Binary: Integer Part
Consider the integer and fractional parts separately.
For the integer part:

Repeatedly divide the given number by 2, and go on
accumulating the remainders, until the number becomes zero.
Arrange the remainders in reverse order.

Base NumbRem
2
2
2
2
2
2
2
89
44
22
11
5
2
1
0
1
0
0
1
1
0
1
2
2
2
2
2
2
2
66
33
16
8
4
2
1
0
0
1
0
0
0
0
1
(66)10 = (1000010)2
(89)10 = (1011001)2
11
Decimal to Binary: Integer Part
Consider the integer and fractional parts separately.
For the integer part:

Repeatedly divide the given number by 2, and go on
accumulating the remainders, until the number becomes zero.
Arrange the remainders in reverse order.

Base NumbRem
2
2
2
2
2
2
2
89
44
22
11
5
2
1
0
1
0
0
1
1
0
1
2
2
2
2
2
2
2
66
33
16
8
4
2
1
0
0
1
0
0
0
0
1
(66)10 = (1000010)2
(89)10 = (1011001)2
2
2
2
2
2
2
2
2
239
119
59
29
14
7
3
1
0
1
1
1
1
0
1
1
1
(239)10 = (11101111)2
12
Decimal to Binary: Fraction Part
Repeatedly multiply the given fraction by 2.

Accumulate the integer part (0 or 1).
If the integer part is 1, chop it off.

Arrange the integer parts in the order they are obtained.

Example: 0.634
.634
.268
.536
.072
.144
x
x
x
x
x
2
2
2
2
2
=
=
=
=
=
1.268
0.536
1.072
0.144
0.288
:
:
(.634)10 = (.10100……)2
13
Decimal to Binary: Fraction Part
Repeatedly multiply the given fraction by 2.

Accumulate the integer part (0 or 1).
If the integer part is 1, chop it off.

Arrange the integer parts in the order they are obtained.

Example: 0.634
Example: 0.0625
.634
.268
.536
.072
.144
.0625
.1250
.2500
.5000
x
x
x
x
x
2
2
2
2
2
=
=
=
=
=
1.268
0.536
1.072
0.144
0.288
x
x
x
x
2
2
2
2
=
=
=
=
0.125
0.250
0.500
1.000
(.0625)10 = (.0001)2
:
:
(.634)10 = (.10100……)2
14
Decimal to Binary: Fraction Part
Repeatedly multiply the given fraction by 2.

Accumulate the integer part (0 or 1).
If the integer part is 1, chop it off.

Arrange the integer parts in the order they are obtained.

Example: 0.634
Example: 0.0625
.634
.268
.536
.072
.144
.0625
.1250
.2500
.5000
x
x
x
x
x
2
2
2
2
2
=
=
=
=
=
1.268
0.536
1.072
0.144
0.288
:
:
(.634)10 = (.10100……)2
x
x
x
x
2
2
2
2
=
=
=
=
0.125
0.250
0.500
1.000
(.0625)10 = (.0001)2
(37)10 = (100101)2
(.0625)10 = (.0001)2
(37.0625)10 = (100101.0001)2
15
Hexadecimal Number System


A compact way of representing binary numbers
16 different symbols (radix = 16)
0
1
2
3
4
5
6
7








0000
0001
0010
0011
0100
0101
0110
0111
8
9
A
B
C
D
E
F








1000
1001
1010
1011
1100
1101
1110
1111
16
Binary-to-Hexadecimal
Conversion

For the integer part,
 Scan
the binary number from right to left
 Translate each group of four bits into the
corresponding hexadecimal digit
 Add leading zeros if necessary

For the fractional part,
 Scan
the binary number from left to right
 Translate each group of four bits into the
corresponding hexadecimal digit
 Add trailing zeros if necessary
17
Example
1.
(1011 0100 0011)2 = (B43)16
2.
(10 1010 0001)2
= (2A1)16
3.
(.1000 010)2
= (.84)16
4.
(101 . 0101 111)2
= (5.5E)16
18
Hexadecimal-to-Binary
Conversion

Translate every hexadecimal digit into its 4-bit
binary equivalent

Examples:
(3A5)16
= (0011 1010 0101)2
(12.3D)16 = (0001 0010 . 0011 1101)2
(1.8)16
= (0001 . 1000)2
19
Number
Representation
Part II
20
Unsigned Binary Numbers

An n-bit binary number
B = bn-1bn-2 …. b2b1b0


2n distinct combinations are possible, 0 to 2n-1.
For example, for n = 3, there are 8 distinct
combinations
 000,

001, 010, 011, 100, 101, 110, 111
Range of numbers that can be represented
n=8 
n=16 
n=32 
0 to 28-1 (255)
0 to 216-1 (65535)
0 to 232-1 (4294967295)
21
Signed Integer Representation

Many of the numerical data items that are used
in a program are signed (positive or negative)
 Question::

How to represent sign?
Three possible approaches:
 Sign-magnitude
representation
 One’s complement representation
 Two’s complement representation
22
Sign-magnitude Representation

For an n-bit number representation
 The
most significant bit (MSB) indicates sign
0  positive
1  negative
 The
remaining n-1 bits represent magnitude
bn-1
Sign
bn-2
b1
b0
Magnitude
23
Contd.

Range of numbers that can be represented:
Maximum :: + (2n-1 – 1)
Minimum ::  (2n-1 – 1)

A problem:
Two different representations of zero
+0  0 000….0
-0  1 000….0
24
One’s Complement
Representation


Basic idea:
 Positive numbers are represented exactly as in
sign-magnitude form
 Negative numbers are represented in 1’s
complement form
How to compute the 1’s complement of a number?
 Complement every bit of the number (10 and
01)
 MSB will indicate the sign of the number
0  positive
1  negative
25
Example: n=4
0000
0001
0010
0011
0100
0101
0110
0111








+0
+1
+2
+3
+4
+5
+6
+7
1000
1001
1010
1011
1100
1101
1110
1111








-7
-6
-5
-4
-3
-2
-1
-0
To find the representation of, say, -4, first note that
+4 = 0100
-4 = 1’s complement of 0100 = 1011
26
Contd.



Range of numbers that can be represented:
Maximum :: + (2n-1 – 1)
Minimum ::  (2n-1 – 1)
A problem:
Two different representations of zero.
+0  0 000….0
-0  1 111….1
Advantage of 1’s complement representation
 Subtraction can be done using addition
 Leads to substantial saving in circuitry
27
Two’s Complement
Representation


Basic idea:
 Positive numbers are represented exactly as in
sign-magnitude form
 Negative numbers are represented in 2’s
complement form
How to compute the 2’s complement of a number?
 Complement every bit of the number (10 and
01), and then add one to the resulting number
 MSB will indicate the sign of the number
0  positive
1  negative
28
Example: n=4
0000
0001
0010
0011
0100
0101
0110
0111








+0
+1
+2
+3
+4
+5
+6
+7
1000
1001
1010
1011
1100
1101
1110
1111








-8
-7
-6
-5
-4
-3
-2
-1
To find the representation of, say, -4, first note that
+4 = 0100
-4 = 2’s complement of 0100 = 1011+1 = 1100
Rule : Value = – msb*2(n–1) + [unsigned value of rest]
Example: 0110 = 0 + 6 = 6
1110 = – 8 + 6 = – 2
29
Contd.



Range of numbers that can be represented:
Maximum :: + (2n-1 – 1)
Minimum ::  2n-1
Advantage:
 Unique representation of zero
 Subtraction can be done using addition
 Leads to substantial saving in circuitry
Almost all computers today use the 2’s complement
representation for storing negative numbers
30
Adding Binary Numbers

Basic Rules:

Example:
 0+0=0
 0+1=1
 1+0=1
 1+1=0
(carry 1)
01101001
00110100
------------10011101
31
Subtraction Using Addition: 1’s
Complement

How to compute A – B ?
 Compute
the 1’s complement of B (say, B1).
 Compute R = A + B1
 If the carry obtained after addition is ‘1’
Add the carry back to R (called end-around carry)
 That is, R = R + 1
 The result is a positive number

Else

The result is negative, and is in 1’s complement
form
32
Example 1: 6 – 2
1’s complement of 2 = 1101
6 :: 0110
-2 :: 1101
1 0011
1
0100
A
B1
R
Assume 4-bit
representations
Since there is a carry, it is
added back to the result
The result is positive
 +4
End-around
carry
33
Example 2: 3 – 5
1’s complement of 5 = 1010
3 :: 0011
-5 :: 1010
A
B1
1101 R
Assume 4-bit representations
Since there is no carry, the
result is negative
1101 is the 1’s complement of
0010, that is, it represents –2
-2
34
Subtraction Using Addition: 2’s
Complement

How to compute A – B ?
 Compute
the 2’s complement of B (say, B2)
 Compute R = A + B2
 If the carry obtained after addition is ‘1’
Ignore the carry
 The result is a positive number

Else

The result is negative, and is in 2’s complement
form
35
Example 1: 6 – 2
2’s complement of 2 = 1101 + 1 = 1110
6 :: 0110
-2 :: 1110
1 0100
Ignore carry
+4
A
B2
R
Assume 4-bit
representations
Presence of carry indicates
that the result is positive
No need to add the endaround carry like in 1’s
complement
36
Example 2: 3 – 5
2’s complement of 5 = 1010 + 1 = 1011
3 :: 0011
-5 :: 1011
1110
-2
A
B2
R
Assume 4-bit representations
Since there is no carry, the
result is negative
1110 is the 2’s complement of
0010, that is, it represents –2
37
2’s complement arithmetic: More
Examples
 Example 1: 18-11 = ?
 18 is represented as 00010010
 11 is represented as 00001011
 1’s complement of 11 is 11110100
 2’s complement of 11 is 11110101
 Add 18 to 2’s complement of 11
00010010
+ 11110101
---------------00000111 (with a carry of 1
which is ignored)
00000111 is 7
38
 Example 2: 7 - 9 = ?
 7 is represented as 00000111
 9 is represented as 00001001
 1’s complement of 9 is 11110110
 2’s complement of 9 is 11110111
 Add 7 to 2’s complement of 9
00000111
+ 11110111
---------------11111110 (with a carry of 0
which is ignored)
11111110 is -2
39
Number
Representation
Part III
40
Overflow/Underflow:
Adding two +ve (-ve) numbers should not produce a
–ve (+ve) number. If it does, overflow (underflow) occurs
41
Overflow/Underflow:
Adding two +ve (-ve) numbers should not produce a
–ve (+ve) number. If it does, overflow (underflow) occurs
Another equivalent condition : carry in and carry
out from Most Significant Bit (MSB) differ.
42
Overflow/Underflow:
Adding two +ve (-ve) numbers should not produce a
–ve (+ve) number. If it does, overflow (underflow) occurs
Another equivalent condition : carry in and carry
out from Most Significant Bit (MSB) differ.
(64) 01000000
( 4) 00000100
-------------(68) 01000100
carry (out)(in)
0 0
43
Overflow/Underflow:
Adding two +ve (-ve) numbers should not produce a
–ve (+ve) number. If it does, overflow (underflow) occurs
Another equivalent condition : carry in and carry
out from Most Significant Bit (MSB) differ.
(64) 01000000
( 4) 00000100
-------------(68) 01000100
(64) 01000000
(96) 01100000
-------------(-96) 10100000
carry (out)(in)
0 0
carry out in differ:
0 1 overflow
44
Floating-point Numbers



The representations discussed so far applies only to
integers
 Cannot represent numbers with fractional parts
We can assume a decimal point before a signed
number
 In that case, pure fractions (without integer parts)
can be represented
We can also assume the decimal point somewhere in
between
 This lacks flexibility
 Very large and very small numbers cannot be
represented
45
Representation of Floating-Point
Numbers


A floating-point number F is represented by a
doublet <M,E> :
F = M x BE
 B  exponent base (usually 2)
 M  mantissa
 E  exponent
 M is usually represented in 2’s complement
form, with an implied binary point before it
For example,
In decimal, 0.235 x 106
In binary, 0.101011 x 20110
46
Example :: 32-bit representation
M

M
E
24
8
represents a 2’s complement fraction
1 > M > -1
 E represents the exponent (in 2’s complement form)
127 > E > -128
Points to note:
 The number of significant digits depends on the
number of bits in M
 6 significant digits for 24-bit mantissa
 The range of the number depends on the number of
bits in E
38 to 10-38 for 8-bit exponent.
 10
47



Sign bit is added in front to represent both +ve
and –ve numbers
The representation shown for floating-point
numbers as shown is just for illustration
The actual representation is a little more
complex, we will not do here
 Example:
IEEE 754 Floating Point format
48
Pointers: Basics
Lecture 24
What is a pointer?

First of all, it is a variable, just like other
variables you studied
 So


it has type, storage etc.
Difference: it can only store the address
(rather than the value) of a data item
Type of a pointer variable – pointer to the type
of the data whose address it will store
 Example:
int pointer, float pointer,…
 Can be pointer to any user-defined types also like
structure types
2
Usage of Pointers

They have a number of useful applications
 Enables us to access a variable that is defined
outside the function
 Can be used to pass information back and forth
between a function and its reference point
 More efficient in handling data tables
 Reduces the length and complexity of a program
 Sometimes also increases the execution speed
Basic Concept


As seen before, in memory, every stored data item
occupies one or more contiguous memory cells
 The number of memory cells required to store a
data item depends on its type (char, int, double,
etc.).
Whenever we declare a variable, the system
allocates memory location(s) to hold the value of the
variable.
 Since every byte in memory has a unique
address, this location will also have its own
(unique) address.
4
Contd.

Consider the statement
int xyz = 50;
 This statement instructs the compiler to
allocate a location for the integer variable xyz,
and put the value 50 in that location
 Suppose that the address location chosen is
1380
xyz 
variable
50

1380 
value
address
5
Contd.


During execution of the program, the system always
associates the name xyz with the address 1380
 The value 50 can be accessed by using either the
name xyz or the address 1380
Since memory addresses are simply numbers, they
can be assigned to some variables which can be
stored in memory
 Such variables that hold memory addresses are
called pointers
 Since a pointer is a variable, its value is also
stored in some memory location
6
Contd.

Suppose we assign the address of xyz to a
variable p
 p is said to point to the variable xyz
Variable
Value
Address
xyz
50
1380
p
1380
2545
p = &xyz;
7
Address vs. Value

Each memory cell has an address
associated with it
...
101 102 103 104 105 ...
...
8
Address vs. Value
Each memory cell has an address
associated with it
 Each cell also stores some value

...
101 102 103 104 105 ...
23
42
...
9
Address vs. Value
Each memory cell has an address
associated with it
 Each cell also stores some value
 Don’t confuse the address referring to a
memory location with the value stored in that
location

...
101 102 103 104 105 ...
23
42
...
10
Values vs Locations

Variables name memory locations, which hold
values
1024:
address
32
x
value
name
11
Pointers in C
A
pointer is just a C variable whose value can
contain the address of another variable
 Needs to be declared before use just like any other
variable
 General form:
data_type *pointer_name;
 Three
things are specified in the above declaration:
 The asterisk (*) tells that the variable
pointer_name is a pointer variable
 pointer_name needs a memory location
 pointer_name points to a variable of type
data_type
12
Example
int
*count;
float *speed;
char *c;

Once a pointer variable has been declared, it can be made
to point to a variable using an assignment statement like
int *p, xyz;
:
p = &xyz;
13
Structure Pointer


Pointers can be defined for any type, including
user defined types
Example
struct name {
char first[20];
char last[20];
};
struct name *p;
p
is a pointer which can store the address of a struct
name type variable
Accessing the Address of a
Variable



The address of a variable is given by the & operator
 The operator & immediately preceding a variable
returns the address of the variable
Example:
p = &xyz;
 The address of xyz (1380) is assigned to p
The & operator can be used only with a simple variable
(of any type, including user-defined types) or an array
element
&distance
&x[0]
&x[i-2]
15
Illegal Use of &

&235

Pointing at constant

int arr[20];
:
&arr;
 Pointing at array name

&(a+b)
 Pointing at expression
In all these cases, there is no storage,
so no address either
16
Example
#include <stdio.h>
int main()
{
int
a;
float b, c;
double d;
char ch;
a = 10;
b = 2.5; c = 12.36; d = 12345.66; ch = ‘A’;
printf (“%d is stored in location %u \n”, a, &a) ;
printf (“%f is stored in location %u \n”, b, &b) ;
printf (“%f is stored in location %u \n”, c, &c) ;
printf (“%lf is stored in location %u \n”, d, &d) ;
printf (“%c is stored in location %u \n”, ch, &ch) ;
return 0;
}
17
Output
10 is stored in location 3221224908
2.500000 is stored in location 3221224904
12.360000 is stored in location 3221224900
12345.660000 is stored in location 3221224892
A is stored in location 3221224891
18
Accessing a Variable Through
its Pointer

Once a pointer has been assigned the address
of a variable, the value of the variable can be
accessed using the indirection operator (*).
int a, b;
int *p;
p = &a;
b = *p;
Equivalent to
b = a;
19
Example
#include <stdio.h>
int main()
{
int
a, b;
int
c = 5;
int
*p;
a
=
4
*
(c
Equivalent
+
5) ;
p = &c;
b = 4 * (*p + 5) ;
printf (“a=%d b=%d \n”,
return 0;
a, b);
a=40 b=40
}
20
Example
int main()
{
int x, y;
int *ptr;
x = 10 ;
ptr = &x ;
y = *ptr ;
printf (“%d
printf (“%d
printf (“%d
printf (“%d
printf (“%u
printf (“%d
is
is
is
is
is
is
stored
stored
stored
stored
stored
stored
in
in
in
in
in
in
location
location
location
location
location
location
%u
%u
%u
%u
%u
%u
\n”,
\n”,
\n”,
\n”,
\n”,
\n”,
x, &x);
*&x, &x);
*ptr, ptr);
y, &*ptr);
ptr, &ptr);
y, &y);
*ptr = 25;
printf (“\nNow x = %d \n”, x);
return 0;
}
21
Suppose that
Address of x:
3221224908
Address of y:
3221224904
Address of ptr:
3221224900
Then output is
10 is stored in location 3221224908
10 is stored in location 3221224908
10 is stored in location 3221224908
10 is stored in location 3221224908
3221224908 is stored in location 3221224900
10 is stored in location 3221224904
Now x = 25
22
Example
pointer to int
int x;
int  xp ;
1024:
xp = &x ;
32
x
1024
xp
address of x
xp = 0;
/* Assign 0 to x */
xp = xp + 1; /* Add 1 to x */
23
Value of the pointer
 Declaring
a pointer just allocates space to hold the
pointer – it does not allocate something to be
pointed to!
 Local
variables in C are not initialized, they may contain
anything
 After
declaring a pointer:
int *ptr;
ptr doesn’t actually point to anything yet. We can
either:
make it point to something that already exists, or
allocate room in memory for something new that
it will point to… (dynamic allocation, to be done
later)
24
Example
0
Memory and Pointers:
1500
2300
25
0
Memory and Pointers:
int *p, v;
v:
arbitrary value
1500
p:
arbitrary value
2300
26
0
v:
arbitrary value
p:
1500
1500
Memory and Pointers:
int v, *p;
p = &v;
2300
27
0
v:
17
1500
p:
1500
2300
Memory and Pointers:
int v, *p;
p = &v;
v = 17;
28
0
v:
25
1500
p:
1500
2300
Memory and Pointers:
int v, *p;
p = &v;
v = 17;
*p = *p + 4;
v = *p + 4
29
Pointers: More ...
Lecture 25
More Examples of Using Pointers
in Expressions

If p1 and p2 are two pointers, the following
statements are valid:
sum = *p1 + *p2;
prod = *p1 * *p2;
prod = (*p1) * (*p2);
*p1 = *p1 + 2;
x = *p1 / *p2 + 5;

*p1 can appear on
the left hand side
Note that this unary * has higher precedence
than all arithmetic/relational/logical operators
31
Important Things to Remember


Pointer variables must always point to a data item of
the same type
float x;
int *p;
:
p = &x;
will result in wrong output
Never assign an absolute address to a pointer
variable
int *count;
count = 1268;
32

Whenever you use *p to access the value of the location
pointed to by a pointer variable p, always check that p
has been assigned a valid value before by an assignment
statement ( p = …..)

Very common mistake while writing programs with pointers
int main()
{
int *p;
*p = 4;
printf(“*p = %d\n”, *p);
}
Run it and see what happens. p is not
assigned anything. So whatever the content of
p is, when *p is done, it tries to write to that
location. So if p contained 1325 (say), it will try
to write at memory location with address 1325.
This may cause an error (OS does not allow
writes to some addresses) or will overwrite
whatever that location contained, which may
corrupt other variable values. Second case is
very hard to debug, as to the compiler 1325 is
a free location and can be given to other
33
variables later, which will then overwrite again.
Pointer Expressions


Like other variables, pointer variables can
appear in expressions
What are allowed in C?
 Add an integer to a pointer
 Subtract an integer from a pointer
 Subtract one pointer from another (related)

If p1 and p2 are both pointers to the same array,
then p2 – p1 gives the number of elements
between p1 and p2
34
Contd.

What are not allowed?
 Adding
two pointers.
p1 = p1 + p2;
 Multiply
/ divide a pointer in an expression
p1 = p2 / 5;
p1 = p1 – p2 * 10;
35
Scale Factor

We have seen that an integer value can be
added to or subtracted from a pointer variable
int *p1, *p2;
int i, j;
:
p1 = p1 + 1;
p2 = p1 + j;
p2++;
p2 = p2 – (i + j);
 In
reality, it is not the integer value which is
added/subtracted, but rather the scale factor times
the value
36
Contd.
Data Type
char
int
float
double
Scale Factor
1
4
4
8
 If
p1 is an integer pointer, then
p1++
will increment the value of p1 by 4
37

The scale factor indicates the number of bytes
used to store a value of that type
 So
the address of the next element of that type can
only be at the (current pointer value + size of data)


The exact scale factor may vary from one
machine to another
Can be found out using the sizeof function
 Gives

the size of that data type
Syntax:
sizeof (data_type)
38
int main()
{
printf (“No. of bytes in int is %u \n”,
sizeof(int));
printf (“No. of bytes in float is %u \n”, sizeof(float));
printf (“No. of bytes in double is %u \n”, sizeof(double));
printf (“No. of bytes in char is %u \n”, sizeof(char));
printf (“No. of bytes in int * is %u \n”,
printf (“No. of bytes in float * is %u \n”,
printf (“No. of bytes in double * is %u \n”,
printf (“No. of bytes in char * is %u \n”,
return 0;
Example
sizeof(int *));
sizeof(float *));
sizeof(double *));
sizeof(char *));
}
Output on a PC
No. of bytes in int is 4
No. of bytes in float is 4
No. of bytes in double is 8
No. of bytes in char is 1
No. of bytes in int * is 4
No. of bytes in float * is 4
No. of bytes in double * is 4
No. of bytes in char * is 4 39


Note that pointer takes 4 bytes to store,
independent of the type it points to
However, this can vary between machines
 Output
of the same program on a server
No. of bytes in int is 4
No. of bytes in float is 4
No. of bytes in double is 8
No. of bytes in char is 1
No. of bytes in int * is 8
No. of bytes in float * is 8
No. of bytes in double * is 8
No. of bytes in char * is 8


Always use sizeof() to get the correct size`
Should also print pointers using %p (instead of %u
as we have used so far for easy comparison)
Example
int main()
{
int A[5], i;
printf(“The addresses of the array elements are:\n”);
for (i=0; i<5; i++)
printf(“&A[%d]: Using \%p = %p, Using \%u = %u”, i, &A[i], &A[i]);
return 0;
}
Output on a server machine
&A[0]: Using %p = 0x7fffb2ad5930,
&A[1]: Using %p = 0x7fffb2ad5934,
&A[2]: Using %p = 0x7fffb2ad5938,
&A[3]: Using %p = 0x7fffb2ad593c,
&A[4]: Using %p = 0x7fffb2ad5940,
Using %u = 2997705008
Using %u = 2997705012
Using %u = 2997705016
Using %u = 2997705020
Using %u = 2997705024
0x7fffb2ad5930 = 140736191093040 in decimal (NOT 2997705008)
so print with %u prints a wrong value (4 bytes of unsigned int cannot
hold 8 bytes for the pointer value)
41
Pointers: Parameter
Passing and Return
42
Passing Pointers to a Function

Pointers are often passed to a function as
arguments
 Allows
data items within the calling function to be
accessed by the called function, altered, and then
returned to the calling function in altered form
 Useful for returning more than one value from a
function
 Still call-by-value, but now the address is copied,
not the content
43
Example: Swapping
int main()
{
int a, b;
a = 5; b = 20;
swap (a, b);
printf (“\n a=%d, b=%d”, a, b);
return 0;
}
void swap (int x, int y)
{
int t;
t = x;
x = y;
y = t;
}
Output
a=5, b=20
Parameters
passed by
value, so
changes done
on copy, not
returned to
calling
function
44
Example: Swapping using pointers
int main()
{
int a, b;
a = 5; b = 20;
swap (&a, &b);
printf (“\n a=%d, b=%d”, a, b);
return 0;
}
void swap (int *x, int *y)
{
int t;
t = *x;
*x = *y;
*y = t;
}
Output
a=20, b=5
Parameters
passed by
address,
changes done
on the value
stored at that
address,
correctly
swapped
45

While passing a parameter to a function, when
should you pass its address instead of the
value?
 Pass



address if both these conditions are satisfied
The parameter value will be modified inside the function body
The modified value is needed in the calling function after the
called function returns
Consider the swap function to see this
46
Passing Arrays as Pointers
Both the forms below are fine in the function body, as
arrays are passed by passing the address of the first
element. Calling function calls it the same way
int main()
{
int n;
float list[100], avg;
:
avg = average (n, list);
:
}
int main()
{
int n;
float list[100], avg;
:
avg = average (n, list);
:
}
float average (int a, float x[])
{
:
sum = sum + x[i];
}
float average (int a, float *x)
{
:
sum = sum + x[i];
}
47
Returning multiple values from a
function



Return statement can return only one value
What if we want to return more than one value?
Use pointers
 Return
one value as usual with a return statement
 For other return values, pass the address of a
variable in which the value is to be returned
48
Example: Returning max and min
of an array
Both returned through pointers (could have returned one of
them through return value of the function also)
int main()
{
int n, min, max, i, A[100];
scanf(“%d”, &n);
for (i=0; i<n; ++i)
scanf(“%d”, &A[i]);
MinMax(A, n, &min, &max);
printf(“Min and max are %d,
%d”, min, max);
return 0;
}
void MinMax(int A[], int n, int
*min, int *max)
{
int i, x, y;
x = y = A[0];
for (i=1; i<n; ++i) {
if (A[i] < x) x = A[i];
if (A[i] > y) y = A[i];
}
*min = x; *max = y;
}
49
Example: Passing structure pointers
struct complex {
float re;
float im;
};
int main()
{
struct complex a, b, c;
scanf(“%f%f”, &a.re, &a.im);
scanf(“%f%f”, &b.re, &b.im);
add(&a, &b, &c) ;
printf(“\n %f %f”, c.re,
c.im);
return 0;
}
void add (struct complex
*x, struct complex *y,
struct complex *t)
{
t->re = x->re + y->re;
t->im = x->im + y->im;
}
The program will print the
sum of a and b correctly.
Just try passing a, b, c
directly (no pointers in call
or in function declaration)
and see what happens
50
Strings
Lecture 26
51
Strings
•
•
•
1-d arrays of type char
By convention, a string in C is terminated by the
end-of-string sentinel ‘\0’ (null character)
char s[21] - can have variable length string
delimited with \0
•
•
•
Max length of the string that can be stored is 20 as
the size must include storage needed for the ‘\0’
String constants : “hello”, “abc”
“abc” is a character array of size 4
52
String Constant
• A string constant is treated as a pointer
• Its value is the base address of the string
char *p = “abc”;
p
a b c \0
printf (“%s %s\n”,p,p+1); /* abc bc is printed */
53
Differences : array & pointers
char *p = “abcde”;
The compiler allocates
space for p, puts the
string constant “abcde”
in memory somewhere
else, initializes p with
the base address of
the string constant
char s[ ] = “abcde”;
 char s[ ] = {‘a’,’b’,’c’,’d’,’e’.’\0’};
The compiler allocates 6 bytes
of memory for the array s
which are initialized with the
6 characters
p
S
a b c d e \0
a b c d e \0
54
Library Functions for String
Handling



You can write your own C code to do different
operations on strings like finding the length of a
string, copying one string to another, appending
one string to the end of another etc.
C library provides standard functions for these
that you can call, so no need to write your own
code
To use them, you must do
#include <string.h>
At the beginning of your program (after #include
<stdio.h>)
55
String functions we will see




strlen : finds the length of a string
strcat : concatenates one string at the end of
another
strcmp : compares two strings lexicographically
strcpy : copies one string to another
56
strlen()
You cannot change contents
of s in the function
int strlen(const char *s)

Takes a null-terminated
strings (we routinely refer
to the char pointer that
points to a null-terminated
char array as a string)

Returns the length of
the string, not counting
the null (\0) character
int strlen (const char *s) {
int n;
for (n=0; *s!=‘\0’; ++s)
++n;
return n;
}
57
strcat()


char *strcat (char *s1,
const char *s2);
Takes 2 strings as
arguments,
concatenates them,
and puts the result in
s1. Returns s1.
Programmer must
ensure that s1 points
to enough space to
hold the result.
You cannot change contents
of s2 in the function
char *strcat(char *s1, const char
*s2)
{
char *p = s1;
while (*p != ‘\0’) /* go to end */
++p;
while(*s2 != ‘\0’)
*p++ = *s2++; /* copy */
*p = ‘\0’;
return s1;
}
58
Dissection of the strcat() function
char *p = s1;
p is being initialized, not *p. The pointer p is initialized
to the pointer value s1. Thus p and s1 point to the
same memory location
59
Dissection of the strcat() function
char *p = s1;
p is being initialized, not *p. The pointer p is initialized
to the pointer value s1. Thus p and s1 point to the
same memory location
while (*p != ‘\0’) ++p;
As long as the value pointed to by p is not ‘\0’, p is
incremented, causing it to point at the next
character in the string. When p points to \0, the
control exits the while statement
60
Dissection of the strcat() function
char *p = s1;
p is being initialized, not *p. The pointer p is initialized
to the pointer value s1. Thus p and s1 point to the
same memory location
while (*p != ‘\0’) ++p;
As long as the value pointed to by p is not ‘\0’, p is
incremented, causing it to point at the next
character in the string. When p points to \0, the
control exits the while statement
while(*s2 != ‘\0’) *p++ = *s2++; /* copy */
At the beginning, p points to the null character at the
end of string s1. The characters in s2 get copied
one after another until end of s2
61
Dissection of the strcat() function
char *p = s1;
p is being initialized, not *p. The pointer p is initialized
to the pointer value s1. Thus p and s1 point to the
same memory location
while (*p != ‘\0’) ++p;
As long as the value pointed to by p is not ‘\0’, p is
incremented, causing it to point at the next
character in the string. When p points to \0, the
control exits the while statement
while(*s2 != ‘\0’) *p++ = *s2++; /* copy */
At the beginning, p points to the null character at the
end of string s1. The characters in s2 get copied
one after another until end of s2
*p = ‘\0’; put the ‘\0’ at the end of the string
62
strcmp()
int strcmp (const char
*s1, const char *s2);
Two strings are passed
as arguments. An
integer is returned
that is less than,
equal to, or greater
than 0, depending on
whether s1 is
lexicographically less
than, equal to, or
greater than s2.
63
strcmp()
int strcmp(char *s1, const char *s2)
{
for (;*s1!=‘\0’&&*s2!=‘\0’; s1++,s2++)
int strcmp (const char
{
*s1, const char *s2);
if (*s1>*s2) return 1;
Two strings are passed
if (*s2>*s1) return -1;
as arguments. An
}
if (*s1 != ‘\0’) return 1;
integer is returned
if (*s2 != ‘\0’) return -1;
that is less than,
return 0;
equal to, or greater
}
than 0, depending on
whether s1 is
lexicographically less
than, equal to, or
greater than s2.
Important: When you use strcmp() from
the string library, check the return value for
>, < or = 0, not for +1, -1, and 0 (which are
just one possible return value to satisfy the
>, <, and = 0 condition
64
strcpy()
char *strcpy (char *s1, char *s2);
The characters is the string s2 are copied into s1 until
\0 is moved. Whatever exists in s1 is overwritten. It is
assumed that s1 has enough space to hold the
result. The pointer s1 is returned.
65
strcpy()
char *strcpy (char *s1, const char *s2);
The characters is the string s2 are copied into s1 until
‘\0’ is moved. Whatever exists in s1 is overwritten. It
is assumed that s1 has enough space to hold the
result. The pointer s1 is returned.
char * strcpy (char *s1, const char *s2)
{
char *p = s1;
while (*p++ = *s2++) ;
return s1;
}
66
Example: Using string functions
int main()
{
char s1[ ] = "beautiful big sky country",
s2[ ] = "how now brown cow";
printf("%d\n",strlen (s1));
printf("%d\n",strlen (s2+8));
printf("%d\n", strcmp(s1,s2));
printf("%s\n",s1+10);
strcpy(s1+10,s2+8);
strcat(s1,"s!");
printf("%s\n", s1);
return 0;
}
Output
25
9
-1
big sky country
beautiful brown cows!
67
Practice Problems
1.
2.
3.
4.
5.
Write a function to search for an element in an array of integers that
returns 1 if the element is found, 0 otherwise. If found, it also returns the
index in the array where found
Write a function that returns the number of lowercase letters, uppercase
letters, and digit characters in a string
Define a structure POINT to store the coordinates (integer) of a point in 2d plane. Write a function that returns the two farthest (largest distance)
points in an array of POINT structures
Write a function that takes two arrays of integers A and B and returns the
size of the union set and the size of the intersection set of A and B
Write a function that returns the lengths of the largest palindromes formed
by any substring (sequence of consecutive characters) of the string. It
should also return the index in the string from which the palindrome starts.
For all of the above, add suitable main() functions to call the functions. Also,
decide on what parameters you will need; for better practice, for all problems
other than problems 1, assume that the return type of the function is void.
68
Pointers and Arrays
Lecture 27
1
Pointers and Arrays
...
201 202 203 204 205 ...
x
 When an array is declared,
int
x[100];
...
The
compiler allocates sufficient amount of
storage to contain all the elements of the
array in contiguous memory locations…
The
base address is the location of the first
element (index 0) of the array
The
compiler also defines the array name
as a constant pointer to the first element
2
Example




Consider the declaration:
int x[5] = {1, 2, 3, 4, 5};
Suppose each integer requires 4 bytes
Compiler allocates a contiguous storage of size 5x4
= 20 bytes
Assume starting address of that storage x is 2500:
Element
Value Address
x[0]
1
2500
x[1]
2
2504 x
x[2]
3
2508
x[3]
4
2512
3
x[4]
5
2516
Pointer arithmetic

Array name x is the starting address of the
array
 Both x and &x[0] have the value 2500 2500


x is a constant pointer, so cannot be
changed
 X = 3400, x++, x += 2 are all illegal
If int *p is declared, then
p = x;

and
2504
2508
2512
2516
p = &x[0]; are equivalent
We can access successive values of x by
using p++ or p-- to move from one
element to another
4
x

Relationship between p and x:
p
= &x[0] = 2500
p+1 = &x[1] = 2504 How will you get the value
stored at x[i] using p?
p+2 = &x[2] = 2508
p+3 = &x[3] = 2512
p+4 = &x[4] = 2516

In general, *(p+i) gives
the value of x[i]
x
C compiler knows the type of each element 2500
in array x:
2504

so knows how many bytes to move the
pointer to get to the next element
2508
2512
2516
5
Is Array Name a Pointer?
 Pointers
and arrays are not
equivalent in two main ways:
Array
name is a constant pointer, it
cannot be assigned any value.
Are the
Pointer
by itself, does not allocate
memory.
 int
arr[10]; int xyz[20]; arr=xyz;
 int
*iptr;
6
iptr=50;
22 February 2022
following
statements
valid?
iptr=xyz;
Programming and Data
Structure
Would following programs work?
main(){
main(){
int i, arr[100];
int arr[100];
for(i=0;i<100;i++)
print(arr);
printf(“%d\n”,*arr++);
}
}
print(int p[]){
int i;
for(i=0;i<100;i++)
arr
p
7
printf(“%d\n”, *p++);
}
22 February 2022
Programming and Data
Structure
Example: function to find average
int main(){
avg: Use pointer
int x[100], k, n;
arithmetic and not
array indexing.
scanf (“%d”, &n);
for (k=0; k<n; k++)
scanf (“%d”, &x[k]);
printf (“\nAverage is %f”,
avg (x, n));
return 0; float avg (int array[], int size){
}
int *p, i , sum = 0;
p = array;
for (i=0; i<size; i++)
sum = sum + *(p+i);
return ((float) sum / size);
}
8
Pointer p can be indexed also --- just like
an array!
int main()
{
int x[100], k, n;
scanf (“%d”, &n);
float avg (int array[], int size)
{
int *p, i , sum = 0;
for (k=0; k<n; k++)
scanf (“%d”, &x[k]);
p = array;
for (i=0; i<size; i++)
sum = sum + p[i];
printf
(“\nAverage is %f”,
avg (x, n));
return 0;
}
return ((float) sum / size);
}
9
Important to remember
 Pitfall: An array in C does not know its own length, &
bounds not checked!
 Consequence: While traversing the elements of an array (either
using [ ] or pointer arithmetic), we can accidentally access off the
end of an array (access more elements than what is there in the
array)
 Consequence: We must pass the array and its size to a function
which is going to traverse it, or there should be some way of
knowing the end based on the values (Ex., a –ve value ending a
string of +ve values)

Accessing arrays out of bound can cause segmentation
faults:
 Very
hard to debug
 Always be careful when traversing arrays in programs
10
2D Array
A[0][0]
A[0][1]
A[0][2]
A[1][0]
A[1][1]
A[1][2]
A[2][0]
A[2][1]
A[2][2]
11
2D Array
A[0][0]
A[0][1]
A[0][2]
A[1][0]
A[1][1]
A[1][2]
A[2][0]
A[2][1]
A[2][2]
In Memory:
A[0][0]
A[0][1]
A[0][2]
A[1][0]
A[1][1]
A[1][2]
A[2][0]
A[2][1]
A[2][2]
12
2D Array
A[0]
A[0][0]
A[0][1]
A[0][2]
A[1]
A[1][0]
A[1][1]
A[1][2]
A[2]
A[2][0]
A[2][1]
A[2][2]
In Memory:
A[0][0]
A[0][1]
A[0][2]
A[1][0]
A[1][1]
A[1][2]
A[2][0]
A[2][1]
A[2][2]
13
2D Array
A
A[0]
A[0][0]
A[0][1]
A[0][2]
A[1]
A[1][0]
A[1][1]
A[1][2]
A[2]
A[2][0]
A[2][1]
A[2][2]
In Memory:
A[0][0]
A[0][1]
A[0][2]
A[1][0]
A[1][1]
A[1][2]
A[2][0]
A[2][1]
A[2][2]
14
2D Array
A
*(A+0)
*(A+1)
*(A+2)
A[0]
A[0][0]
A[0][1]
A[0][2]
A[1]
A[1][0]
A[1][1]
A[1][2]
A[2]
A[2][0]
A[2][1]
A[2][2]
In Memory:
A[0][0]
A[0][1]
A[0][2]
A[1][0]
A[1][1]
A[1][2]
A[2][0]
A[2][1]
A[2][2]
15
2D Array
A
*(A+0)
*(A+1)
*(A+2)
A[0]
A[0][0]
*(*(A+0)+0)
A[0][1]
*(*(A+0)+1)
A[0][2]
*(*(A+0)+2)
A[1]
A[1][0]
*(*(A+1)+0)
A[1][1]
*(*(A+1)+1)
A[1][2]
*(*(A+1)+2)
A[2]
A[2][0]
*(*(A+2)+0)
A[2][1]
*(*(A+2)+1)
A[2][2]
*(*(A+2)+2)
In Memory:
A[0][0]
A[0][1]
A[0][2]
A[1][0]
A[1][1]
A[1][2]
A[2][0]
A[2][1]
A[2][2]
16
2D Array
In general, A[i][j] = *(*(A+i)+j)
A
*(A+0)
*(A+1)
*(A+2)
A[0]
A[0][0]
*(*(A+0)+0)
A[0][1]
*(*(A+0)+1)
A[0][2]
*(*(A+0)+2)
A[1]
A[1][0]
*(*(A+1)+0)
A[1][1]
*(*(A+1)+1)
A[1][2]
*(*(A+1)+2)
A[2]
A[2][0]
*(*(A+2)+0)
A[2][1]
*(*(A+2)+1)
A[2][2]
*(*(A+2)+2)
In Memory:
A[0][0]
A[0][1]
A[0][2]
A[1][0]
A[1][1]
A[1][2]
A[2][0]
A[2][1]
A[2][2]
17
2D Array
In general, A[i][j] = *(*(A+i)+j)
A
*(A+0)
*(A+1)
*(A+2)
A[0]
A[0][0]
*(*(A+0)+0)
A[0][1]
*(*(A+0)+1)
A[0][2]
*(*(A+0)+2)
A[1]
A[1][0]
*(*(A+1)+0)
A[1][1]
*(*(A+1)+1)
A[1][2]
*(*(A+1)+2)
A[2]
A[2][0]
*(*(A+2)+0)
A[2][1]
*(*(A+2)+1)
A[2][2]
*(*(A+2)+2)
In Memory:
A[0][0]
A[0][1]
*(*(A+0)+0)
A[0][2]
*(*(A+0)+2)
A[1][0]
A[1][1]
A[1][2]
A[2][0]
A[2][1]
A[2][2]
18
2D Array
In general, A[i][j] = *(*(A+i)+j)
A
*(A+0)
*(A+1)
*(A+2)
A[0]
A[0][0]
*(*(A+0)+0)
A[0][1]
*(*(A+0)+1)
A[0][2]
*(*(A+0)+2)
A[1]
A[1][0]
*(*(A+1)+0)
A[1][1]
*(*(A+1)+1)
A[1][2]
*(*(A+1)+2)
A[2]
A[2][0]
*(*(A+2)+0)
A[2][1]
*(*(A+2)+1)
A[2][2]
*(*(A+2)+2)
In Memory:
A[0][0]
A[0][1]
*(*(A+0)+0)
A[0][2]
A[1][0]
*(*(A+0)+3)
A[1][1]
A[1][2]
*(*(A+0)+5)
A[2][0]
A[2][1]
A[2][2]
*(*(A+0)+7)
19
Pointers to
Structures
20
Pointers to Structures
 Pointer variables can be defined to
store the address of structure variables
 Example:
struct student {
int roll;
char dept_code[25];
float cgpa;
};
struct student *p;
21
 Just
like other pointers, p does not point to
anything by itself after declaration
Need
to assign the address of a structure to p
Can
use & operator on a struct student type
variable
Example:
struct student x, *p;
scanf(“%d%s%f”, &x.roll, x.dept_code, &x.cgpa);
p = &x;
22

Once p points to a structure variable, the
members can be accessed in one of two ways:
 (*p).roll,

p
Note the ( ) around *p
–> roll, p –> dept_code, p –> cgpa


(*p).dept_code, (*p).cgpa
The symbol –> is called the arrow operator
Example:
 printf(“Roll
= %d, Dept.= %s, CGPA = %f\n”,
(*p).roll, (*p).dept_code, (*p).cgpa);
 printf(“Roll
= %d, Dept.= %s, CGPA = %f\n”,
p->roll, p->dept_code, p->cgpa);
23
Pointers and Array of Structures

Recall that the name of an array is the
address of its 0-th element
 Also
true for the names of arrays of structure
variables

Consider the declaration:
struct student class[100], *ptr ;
24




The name class represents the address of the 0-th
element of the structure array
 ptr is a pointer to data objects of the type struct student
The assignment
ptr = class;
will assign the address of class[0] to ptr
Now ptr->roll is the same as class[0].roll. Same for other
members
When the pointer ptr is incremented by one (ptr++) :
 The value of ptr is actually increased by sizeof(struct
student)
 It is made to point to the next record
 Note that sizeof operator can be applied on any data
type
25
struct student {
char name[20];
int roll;
}
int main()
{
struct student class[50], *p;
int i, n;
scanf(“%d”, &n);
for (i=0; i<n; i++)
scanf(“%s%d”, class[i].name, &class[i].roll);
p = class;
for (i=0; i<n; i++) {
printf(“%s %d\n”, class[i].name, class[i].roll);
printf(“%s %d\n”, *(p+i).name, *(p+i).roll);
printf(“%s %d\n”, (p+i)->name, (p+i)->roll);
printf(“%s %d\n”, p[i].name, p[i].roll);
}
}
Output
3
Ajit 1001
Abhishek 1005
Riya 1007
Ajit 1001
Ajit 1001
Ajit 1001
Ajit 1001
Abhishek 1005
Abhishek 1005
Abhishek 1005
Abhishek 1005
Riya 1007
Riya 1007
Riya 1007
Riya 1007
26
A Warning

When using structure pointers, be careful of operator
precedence
 Member operator “.” has higher precedence than “*”
 ptr –> roll
and (*ptr).roll mean the same
thing
 *ptr.roll will lead to error
 The operator “–>” enjoys the highest priority
among operators

++ptr –> roll will increment ptr->roll, not ptr
 (++ptr) –> roll
will access (ptr + 1)->roll (for
example, if you want to print the roll no. of all elements of
the class array)

When not sure, use ( and ) to force what you you want
27
Example: Complex Number Addition
#include <stdio.h>
struct complex {
struct complex add
(struct complex x, struct
complex y) {
struct complex t;
float re;
float im;
};
main(){
struct complex a, b, c;
scanf (“%f %f”, &a.re, &a.im);
scanf (“%f %f”, &b.re, &b.im);
c = add (a, b) ;
printf (“\n %f %f”, c.re, c.im);
}
28
t.re = x.re + y.re ;
t.im = x.im + y.im ;
return (t) ;
}
22 February 2022
Programming and Data
Structure
Example: Alternative Way Using Pointers
#include <stdio.h>
struct complex {
float re;
float im;
};
void add (struct complex
*x, *y, *t)
{
t->re = x->re + y->re ;
t->im = x->im + y->im ;
}
main(){
struct complex a, b, c;
scanf (“%f %f”, &a.re, &a.im);
scanf (“%f %f”, &b.re, &b.im);
add (&a, &b, &c) ;
printf (“\n %f %f”, c.re, c.im);
}
29
22 February 2022
Programming and Data
Structure
Example: Sorting by Roll Numbers
#include <stdio.h>
struct stud
{
int
roll;
char dept_code[25];
float cgpa;
};
main()
{
struct stud class[100], t;
int j, k, n;
scanf (“%d”, &n);
/* no. of students */
30
for (k=0; k<n; k++)
scanf (“%d %s %f”, &class[k].roll,
class[k].dept_code, &class[k].cgpa);
for (j=0; j<n-1; j++)
for (k=j+1; k<n; k++)
{
if (class[j].roll > class[k].roll)
{
t = class[j] ;
class[j] = class[k] ;
class[k] = t
}
}
<<<< PRINT THE RECORDS >>>>
}
22 February 2022
Programming and Data
Structure
Practice Problems

Look at all problems you have done earlier on
arrays (including arrays of structures). Now
rewrite all of them using equivalent pointer
notations
 Example:
If you had declared an array
int A[50]
Now do
int A[50], *p;
p = A;
and then write the rest of the program using the
pointer p (without using [ ] notation)
32
Dynamic Memory
Allocation
Lecture 28
33
sizeof with Pointers to Arrays
int array[10];
int *p=array;
What is…
sizeof(array[3])? 4
Sizeof(p)?
4
sizeof(array)? 40
A Problem with Arrays

Sometimes
 Amount of data cannot be predicted beforehand
 Number of data items keeps changing during program
execution

Example: Seach for an element in an array of N elements
One solution: find the maximum possible value of N and
allocate an array of N elements
 Wasteful of memory space, as N may be much smaller
in some executions
 Example: maximum value of N may be 10,000, but a
particular run may need to search only among 100
elements
 Using array of size 10,000 always wastes memory
in most cases

35
Better Solution

Dynamic memory allocation
 Know
how much memory is needed after the
program is run

Example: ask the user to enter from keyboard
 Dynamically
allocate only the amount of
memory needed

C provides functions to dynamically
allocate memory
 malloc,
calloc, realloc
36
Memory Allocation Functions





malloc
 Allocates requested number of bytes and returns a
pointer to the first byte of the allocated space
calloc
 Allocates space for an array of elements, initializes
them to zero and then returns a pointer to the
memory.
free
 Frees previously allocated space.
realloc
 Modifies the size of previously allocated space.
We will only do malloc and free
37
Allocating a Block of Memory

A block of memory can be allocated using
the function malloc
Reserves a block of memory of
specified size and returns a pointer of
type void
The return pointer can be type-casted to
any pointer type

General format:
type *p;
p = (type *) malloc (byte_size);
38
Example
p = (int *) malloc(100 * sizeof(int));

A memory space equivalent to 100 times the
size of an int bytes is reserved
 The address of the first byte of the allocated
memory is assigned to the pointer p of type int
p
400 bytes of space
39
Contd.
 cptr = (char *) malloc (20);
Allocates 20 bytes of space for the pointer cptr
of type char

sptr = (struct stud *) malloc(10*sizeof(struct
stud));
Allocates space for a structure array of 10
elements. sptr points to a structure element of
type struct stud
Always use sizeof operator to find number of bytes for
a data type, as it can vary from machine to machine40
Points to Note

malloc always allocates a block of contiguous
bytes
The allocation can fail if sufficient contiguous
memory space is not available
If it fails, malloc returns NULL
if ((p = (int *) malloc(100 * sizeof(int))) == NULL){
printf (“\n Memory cannot be allocated”);
exit();
}
41
Using the malloc’d Array


Once the memory is allocated, it can be used with
pointers, or with array notation
Example:
int *p, n, i;
scanf(“%d”, &n);
p = (int *) malloc (n * sizeof(int));
for (i=0; i<n; ++i)
scanf(“%d”, &p[i]);
The n integers allocated can be accessed as *p, *(p+1),
*(p+2),…, *(p+n-1) or just as p[0], p[1], p[2], …,p[n-1]
42
Example
#include <stdio.h>
printf("Input heights
Input the number of students.
for %d students \n",N);
5
main(){
for(i=0;i<N;i++)
Input heights for 5 students
int i,N;
scanf("%f",&height[i]);
23 24 25 26 27
float *height;
for(i=0;i<N;i++)
Average height= 25.000000
float sum=0,avg;
sum+=height[i];
printf("Input the number of
avg=sum/(float) N;
students. \n");
printf("Average height=
scanf("%d",&N);
%f \n",avg);
height=(float *) malloc(N * }
sizeof(float));
43
22 February 2022
Programming and Data
Structure
Releasing the Allocated Space:
free



An allocated block can be returned to the
system for future use by using the free function
General syntax:
free (ptr);
where ptr is a pointer to a memory block which
has been previously created using malloc
Note that no size needs to be mentioned for the
allocated block, the system remembers it for
each pointer returned
44
Can we allocate only arrays?

malloc can be used to allocate memory for
single variables also
p
= (int *) malloc (sizeof(int));
 Allocates space for a single int, which can be
accessed as *p

Single variable allocations are just special
case of array allocations
 Array
with only one element
45
malloc( )-ing array of structures
typedef struct{
char name[20];
int roll;
float SGPA[8], CGPA;
} person;
int main() {
person *student;
int i,j,n;
scanf("%d", &n);
student = (person *)malloc(n*sizeof(person));
for (i=0; i<n; i++) {
scanf("%s", student[i].name);
scanf("%d", &student[i].roll);
for(j=0;j<8;j++) scanf("%f", &student[i].SGPA[j]);
scanf("%f", &student[i].CGPA);
}
return 0;
}
46
Static array of pointers
#define N 20
#define M 10
int main()
...
{
char word[N], *w[M];
int i, n;
scanf("%d",&n);
for (i=0; i<n; ++i) {
scanf("%s", word);
w[i] = (char *) malloc ((strlen(word)+1)*sizeof(char));
strcpy (w[i], word) ;
}
for (i=0; i<n; i++) printf("w[%d] = %s \n",i,w[i]);
return 0;
}
w
47
Static array of pointers
Output
#define N 20
#define M 10
int main()
{
char word[N], *w[M];
int i, n;
scanf("%d",&n);
for (i=0; i<n; ++i) {
scanf("%s", word);
w[i] = (char *) malloc ((strlen(word)+1)*sizeof(char));
strcpy (w[i], word) ;
}
for (i=0; i<n; i++) printf("w[%d] = %s \n",i,w[i]);
return 0;
}
4
Tendulkar
Sourav
Khan
India
w[0] = Tendulkar
w[1] = Sourav
w[2] = Khan
w[3] = India
48
How it will look like
w
0
1
2
3
T
e
n
d
u
l
S
o
u
r
a
v \0
K h
a
n \0
I
d
i
n
k
a
r
\0
a \0
9
49
Pointers to Pointers


Pointers are also variables (storing addresses),
so they have a memory location, so they also
have an address
Pointer to pointer – stores the address of a
pointer variable
w
int x = 10, *p, **q;
p = &x;
q = &p;
printf(“%d %d %d”, x, *p, *(*q));
0
1
2
3
will print 10 10 10 (since *q = p)
9
50
Allocating Pointer to Pointer
int **p;
p = (int **) malloc(3 * sizeof(int *));
p[0]
p int **
int *
p[1] int *
p[2] int *
51
Dynamic Arrays of pointers
int main()
{
char word[20], **w; /* “**w” is a pointer to a pointer array */
int i, n;
scanf("%d",&n);
w = (char **) malloc (n * sizeof(char *));
for (i=0; i<n; ++i) {
scanf("%s", word);
w[i] = (char *) malloc ((strlen(word)+1)*sizeof(char));
strcpy (w[i], word) ;
}
for (i=0; i<n; i++) printf("w[%d] = %s \n",i, w[i]);
return 0;
}
52
Dynamic Arrays of pointers
Output
int main()
5
{
char word[20], **w; /* “**w” is a pointer to a pointer array */ India
Australia
int i, n;
Kenya
scanf("%d",&n);
NewZealand
w = (char **) malloc (n * sizeof(char *));
SriLanka
for (i=0; i<n; ++i) {
w[0] = India
scanf("%s", word);
w[1] = Australia
w[i] = (char *) malloc ((strlen(word)+1)*sizeof(char));
w[2] = Kenya
strcpy (w[i], word) ;
w[3] = NewZealand
}
w[4] = SriLanka
for (i=0; i<n; i++) printf("w[%d] = %s \n",i, w[i]);
return 0;
}
53
How this will look like
w
0
1
2
3
4
I
n
d
i
a \0
A u
s
t
r
K
e
n
y
a \0
N
e w Z
e
S
r
a
i
L
a
l
I
a \0
a
l
a
n
n
k
a \0
d \0
54
Dynamic Allocation of 2-d Arrays
int **allocate (int h, int w)
{
int **p;
Allocate array
int i, j;
of pointers
p = (int **) malloc(h*sizeof (int *) );
for (i=0;i<h;i++)
p[i] = (int *) malloc(w * sizeof (int));
return(p);
}
Allocate array of
integers for each
row
void read_data (int **p, int h, int w)
{
int i, j;
for (i=0;i<h;i++)
for (j=0;j<w;j++)
scanf ("%d", &p[i][j]);
}
Elements accessed
like 2-D array elements.
55
Arrays and Pointers: Exercise
int
foo(int array[],
unsigned int size){
…
printf(“%d\n”, sizeof(array));
}
int main(){
int a[10], b[5];
… foo(a, 10)… foo(b, 5) …
printf(“%d\n”, sizeof(a));
}
What does this print?
8
... because array is really
a pointer
What does this print?
40
Contd.
void print_data (int **p, int h, int w)
{
int i, j;
for (i=0;i<h;i++)
{
for (j=0;j<w;j++)
printf ("%5d ", p[i][j]);
printf ("\n");
}
}
int main()
{
int **p;
int M, N;
printf ("Give M and N \n");
scanf ("%d%d", &M, &N);
p = allocate (M, N);
read_data (p, M, N);
printf ("\nThe array read as \n");
print_data (p, M, N);
return 0;
}
57
Contd.
void print_data (int **p, int h, int w)
{
int i, j;
for (i=0;i<h;i++)
{
for (j=0;j<w;j++)
Give M and N
printf ("%5d ", p[i][j]);
33
printf ("\n");
123
}
456
}
789
The array read
as
1 2 3
4 5 6
7 8 9
int main()
{
int **p;
int M, N;
printf ("Give M and N \n");
scanf ("%d%d", &M, &N);
p = allocate (M, N);
read_data (p, M, N);
printf ("\nThe array read as \n");
print_data (p, M, N);
return 0;
}
58
Memory Layout in Dynamic Allocation
int main()
{
int **p;
int M, N, i, j;
printf ("Give M and N \n");
scanf ("%d%d", &M, &N);
p = allocate (M, N);
for (i=0;i<M;i++) {
for (j=0;j<N;j++)
printf ("%u", &p[i][j]);
printf(“\n”);
}
return 0;
}
int **allocate (int h, int w)
{
int **p;
int i, j;
p = (int **)malloc(h*sizeof (int *));
for (i=0; i<h; i++)
printf(“%u”, &p[i]);
printf(“\n\n”);
for (i=0;i<h;i++)
p[i] = (int
*)malloc(w*sizeof(int));
return(p);
}
59
Output
33
31535120 31535128 31535136
31535152 31535156 31535160
31535184 31535188 31535192
31535216 31535220 31535224
Starting address of each
row, contiguous (pointers
are 8 bytes long)
Elements in each
row are contiguous
60
Practice Problems

Take any of the problems you have done
so far using 1-d arrays or 2-d arrays. Now
do them by allocating the arrays
dynamically first instead of declaring then
statically
61
Linked List
1
List

A list refers to a sequence of data items
 Example: An array
 The array index is used for accessing and
manipulation of array elements
 Problems with arrays
 The array size has to be specified at the
beginning (at least during dynamic allocation)
 realloc
can be used to readjust size in middle, but
contiguous chunk of memory may not be available
Deleting an element or inserting an element may
require shifting of elements
 Wasteful of space
2

Linked List

A completely different way to represent a
list
 Make
each data in the list part of a structure
 The structure also contains a pointer or link to
the structure (of the same type) containing the
next data
 This type of list is called a linked list
Structure 1
data
Structure 2
data
Structure 3
data
3
Forming a linked list


Let each structure of the list (lets call it node) have
two fields:
 One containing the data
 The other containing the address of the
structure holding the next data in the list
The structures in the linked list need not be
contiguous in memory
 They are ordered by logical links that are stored
as part of the data in the structure itself
 The link is a pointer to another structure of the
same type
4
Contd.


struct node
{
int data;
struct node *next;
}
data
next
The pointer variable next contains either the
address of the location in memory of the
successor list element or the special value NULL
defined as 0


node
NULL is used to denote the end of the list (no successor
element)
Such structures which contain a member field
pointing to the same structure type are called selfreferential structures
5
Example: nodes of the list
struct node a, b, c;
a.data = 1;
b.data = 2;
c.data = 3;
a.next = b.next = c.next = NULL;
a
b
1
NULL
data next
c
2
NULL
data next
3
NULL
data next
6
Chaining these together
a.next = &b;
b.next = &c;
a
b
1
data next
c
2
data next
3
NULL
data next
What are the values of :
• a.next->data
• a.next->next->data
7
Chaining these together
a.next = &b;
b.next = &c;
a
b
1
data next
c
2
3
data next
What are the values of :
• a.next->data
• a.next->next->data
NULL
data next
2
3
8
Linked Lists


A singly linked list is a
data structure
consisting of a
sequence of nodes
Each node stores
 data
 link to the next node
next
data
node
NULL
9
Contd.



A head pointer addresses the first element of
the list
Each element points at a successor element
The last element has a link value NULL
head
NULL
10
Contd.

In general, a node of the linked list may be
represented as
Name of the type of nodes
struct node_name
{
Data items in each
type member1;
element of the list
type member2;
………
Link to the next
struct node_name *next;
element in the list
};
11
Example: list of student records



Structure for each node
struct stud
{
int roll;
char name[30];
int age;
struct stud *next;
};
Suppose the list has three students’ records
Declare three nodes n1, n2, and n3
struct stud n1, n2, n3;
12
Contd.


Create the links between the nodes
n1.next = &n2 ;
n2.next = &n3 ;
n3.next = NULL ; /* No more nodes follow */
The final list looks like
roll
name
age
next
n1
n2
n3
13
Code for the Example
#include <stdio.h>
struct stud
{
int roll;
char name[30];
int age;
struct stud *next;
};
int main()
{
struct stud
struct stud
scanf (“%d %s
scanf (“%d %s
scanf (“%d %s
n1, n2, n3;
*p;
%d”, &n1.roll, n1.name, &n1.age);
%d”, &n2.roll, n2.name, &n2.age);
%d”, &n3.roll, n3.name, &n3.age);
14
n1.next
n2.next
n3.next
=
=
=
&n2 ;
&n3 ;
NULL ;
/* Now traverse the list and print the
elements */
p = &n1 ;
/* point to 1st element */
while (p != NULL)
{
printf (“\n %d %s %d”,
p->roll, p->name, p->age);
p = p->next;
}
return 0;
}
15
15
Alternative Way

Instead of statically declaring the structures n1,
n2, n3,
 Dynamically
allocate space for the nodes
 Use malloc individually for every node allocated


This is the usual way to work with linked lists, as
number of elements in the list is usually not
known in advance (if known, we could have
used arrays)
See examples next
16
16
Example of dynamic node allocation
Storing a set of elements = {15,18,12,7}
15
18
struct node {
int data ;
struct node * next ;
};
struct node *p, *q;
12
7
NULL
data
int
next
node *
17
Adding 15
and 18 only
struct node {
int data ;
struct node * next ;
};
struct node *p, *q;
p = (struct node *) malloc(sizeof(struct node));
p->data=15;
15
p
q = (struct node *) malloc(sizeof(struct node));
q->data=18; q->next = NULL;
p
15
18
NULL
q
p->next = q;
p
15
18
q
NULL
18
Traversing the elements added
struct node {
int data;
struct node * next;
};
int main() {
struct node *p,*q,*r;
p = (struct node *) malloc(sizeof(struct node));
:
r=p;
while(r!=NULL){
printf("Data = %d \n",r->data);
r=r->next;
}
return 0;
}
Output
Data = 15
Data = 18
We could have
done anything else
other than printing
as we traverse each
element, like
searching for
example. Just like
traversing an array.
19
Contd.


We assumed two elements in the list, so took
two pointers p and q
What if the number of elements are not known?
 Precisely

the reason we use linked list
Solution:
 Remember
the address of the first element in a
special pointer (the head pointer), make sure to not
overwrite it
 Any other pointer can be reused
20
Example: adding n elements read from
keyboard
int main() {
int n, i;
struct node *head = NULL, *p, *prev;
scanf(“%d”, &n);
for (i = 0; i < n; ++i) {
p = (struct node *) malloc(sizeof(struct node));
scanf(“%d”, &p->data);
p->next = NULL;
if (head == NULL) head = p;
else prev->next = p;
prev = p;
}
return 0;
}
head changes only
once, when the first
element is added
prev remembers
the pointer to the
last element added,
p is linked to its
next field
p and prev are
reused as many
times as needed
21
Example: printing an arbitrary sized list
int main()
{
int n, i;
struct node *head = NULL, *p;
:
p = head;
while (p != NULL) {
printf(“%d “, p->data);
p = p->next;
}
return 0;
}
Assumed that the
list is already
created and head
points to the first
element in the list
p is reused to point
to the elements in
the list (initially, to
the first element)
When p points to
the last element, p>next = NULL, so
the loop terminates
after this iteration
22
Important to remember

Store the address of the first element added in a
separate pointer (head in our examples), and
make sure not to change it
 If
you lose the start pointer, you cannot access any
element in the list, as elements are only accessible
from the next pointers in the previous element
 In the print example, we could have reused head,
(head=head->next instead of p=p->next) as we do
not need to remember the start pointer after
printing the list, but this is considered bad practice,
so we used a separate temporary pointer p
23
Function to print a list
The pointer to the
start of the list
(head pointer) is
passed as
parameter
void display (struct node *r)
{
struct node *p = r;
printf(“List = {”);
while(p != NULL) {
printf("%d, ", p->data);
p = p->next;
}
printf(“}\n”);
}
24
Common Operations on Linked
Lists




Creating a linked list (already seen)
Printing a linked list (already seen)
Search for an element in a linked list (can be
easily done by traversing)
Inserting an element in a linked list
 Insert
at front of list
 Insert at end of list
 Insert in sorted order

Delete an element from a linked list
25
Search for an element
Takes the
head pointer
as parameter
struct node *search (struct node *r, int value)
{
struct node *p;
Traverses the
list and
p = r;
compares
while (p!=NULL){
value with
if (p->data == value) return p;
each data
p = p->next;
Returns the
}
node with the
return p;
value if
found, NULL }
otherwise
26
Insertion in a list
 To
insert a data item into a linked list
involves
 creating a new node containing the data
 finding the correct place in the list, and
 linking in the new node at this place
 Correct
place may vary depending on what
is needed
 Front of list
 End of list
 Keep the list
…
in sorted order
27
Takes the
head pointer
and the value
to be inserted
(NULL if list is
empty)
Inserts the
value as the
first element of
the list
Returns the
new head
pointer value
Insert in front of list
struct node *insert(struct node *r, int value)
{
struct node *p;
p = (struct node *) malloc(sizeof(struct node));
p->data = value;
p ->next = r;
return p;
}
28
Contd.
18
…
3
r
15
18
p
…
3
r
15
18
p
3
…
r
29
Using the Insert Function
void display (struct node *);
struct node * insert(struct node * , int);
int main()
{ struct node *head;
head = NULL;
head = insert(head, 10);
display(head);
head = insert(head, 11);
display(head);
head = insert(head, 12);
display(head);
return 0;
}
Output
List = {10, }
List = {11, 10, }
List = {12, 11, 10, }
30
Takes the
head pointer
and the value
to be inserted
(NULL if list is
empty)
Inserts the
value as the
last element of
the list
Returns the
new head
pointer value
Insert at end
struct node *insert_end(struct node *r,
int value)
{ struct node *p,*q;
p = (struct node *) malloc(sizeof(struct node));
p->data = value;
p ->next = NULL;
if (r==NULL) return p; /* list passed is empty */
q=r;
while (q->next!=NULL)
q=q->next; /* find the last element */
q->next =p;
return r;
}
31
Contd.
…
11
r
4
NULL
q
p
…
11
r
4
15
NULL
q
NULL
p
…
11
r
4
15
q
NULL
32
Using the Insert at End Function
void display (struct node *);
struct node * insert(struct node * , int);
struct node * insert_end(struct node * , int);
int main()
{
struct node *start;
start = NULL;
start = insert_end(start, 10);
display(start);
start = insert_end(start, 11);
display(start);
start = insert_end(start, 12);
display(start);
return 0;
}
Output
List = {10, }
List = {10, 11, }
List = {10, 11, 12, }
33
Insertion in Ascending Order
first
prev
3
5
new




ptr
8
12
-
7
Create new node for the 7
Find correct place – when ptr finds the 8 (7 < 8)
Link in new node with previous (even if last) and ptr
nodes
Also check insertion before first node!
34
Insert in ascending order & sort
struct node * insert_asc(struct node * r, int value)
{ struct node *p, *q, *new;
new = (struct node *) malloc(sizeof(struct node));
new->data = value; new ->next = NULL;
p = r; q = p;
while(p!=NULL) {
if (p->data >= value) { /* insert before */
if (p==r) { new->next =r; /* insert at start */
return new; }
new->next = p; /* insert before p */
q->next = new;
return r; }
q = p;
p = p->next; } /* exists loop if > largest */
if (r==NULL) return new; /* first time */
else q->next = new; /* insert at end */
return r; }
int main()
{
struct node *start;
int i,n,value;
start = NULL;
scanf("%d",&n);
for(i=0; i<n; i++) {
printf("Give Data: " );
scanf("%d",&value);
start = insert_asc(start, value);
}
display(start);
return 0;
}
35
Deletion from a list
 To
delete a data item from a linked list
 Find
the data item in the list, and if found
 Delink this node from the list
 Free up the malloc’ed node space
36
Example of Deletion
first
3


prev
5
ptr
8
12
-
When ptr finds the item to be deleted, e.g. 8, we need
the previous node to make the link to the next one
after ptr (i.e. ptr -> next)
Also check whether first node is to be deleted
37
Deleting an element
struct node * delete(struct node * r, int value)
{ struct node *p, *q;
p =r;
11
q = p;
q
while(p!=NULL) {
if (p->data == value){
if (p==r) r = p->next;
else q->next = p->next;
p->next = NULL;
11
free(p);
q
return r;
}
else { q = p;
p = p->next;
11
}
q
}
return r;
}
…
…
…
delete(r,4)
4
15
…
15
…
15
…
p
4
p NULL
38
Practice Problems





Print a list backwards (try a recursive print)
Count the number of elements in a list (both using
and not using recursion)
Concatenate two lists
Reverse a list
Delete the maximum element from a list
For each of the above, first create the linked list by
reading in integers from the keyboard and inserting one
by one to an empty list
39
Stack and Queue
1
Stack
Data structure with Last-In First-Out (LIFO) behavior
In
C
B
A
Out
B
C
2
Typical Operations
on Stack
Pop
Push
isempty: determines if the stack has no elements
isfull: determines if the stack is full in case
of a bounded sized stack
top:
returns the top element in the stack
push: inserts an element into the stack
pop:
removes the top element from the stack
push is like inserting at the front of the list
pop is like deleting from the front of the list
3
Creating and Initializing a Stack
Declaration
#define MAX_STACK_SIZE 100
typedef struct {
int key; /* just an example, can have
any type of fields depending
on what is to be stored */
} element;
typedef struct {
element list[MAX_STACK_SIZE];
int top; /* index of the topmost element */
} stack;
Create and Initialize
stack Z;
Z.top = -1;
4
Operations
int isfull (stack *s)
{
if (s->top >=
MAX_STACK_SIZE – 1)
return 1;
return 0;
}
int isempty (stack *s)
{
if (s->top == -1)
return 1;
return 0;
}
5
Operations
element top( stack *s )
{
return s->list[s->top];
}
void push( stack *s, element e )
{
(s->top)++;
s->list[s->top] = e;
}
void pop( stack *s )
{
(s->top)--;
}
6
Application: Parenthesis Matching

Given a parenthesized expression, test whether the
expression is properly parenthesized
 Examples:
( )( { } [ ( { } { } ( ) ) ] )
is proper
( ){ [ ]
is not proper
({)}
is not proper
)([ ]
is not proper
([]))
is not proper
7

Approach:
 Whenever a left parenthesis is
encountered, it is pushed in the stack
 Whenever a right parenthesis is
encountered, pop from stack and check
if the parentheses match
 Works for multiple types of parentheses
( ), { }, [ ]
8
Parenthesis matching
while (not end of string) do
{
a = get_next_token();
if (a is ‘(‘ or ‘{‘ or ‘[‘) push (a);
if (a is ‘)’ or ‘}’ or ‘]’)
{
if (is_stack_empty( ))
{ print (“Not well formed”); exit(); }
x = top();
pop();
if (a and x do not match)
{ print (“Not well formed”); exit(); }
}
}
if (not is_stack_empty( )) print (“Not well formed”);
9
Recursion can be
implemented as a stack
Fibonacci recurrence:
fib(n) = 1 if n =0 or 1;
= fib(n – 2) + fib(n – 1)
otherwise;
fib (5)
fib (3)
fib (1)
fib (0)
fib (4)
fib (2)
fib (1)
fib (2)
fib (0)
fib (3)
fib (1) fib (1)
fib (0)
fib (2)
fib (1)
10
Fibonacci Recursion Stack
5
3
4
1
2
4
0
0
0
1
3
4
3
1
2
5
5
2
4
0
1
4
1
4
1
1
2
2
0
1
1
6
6
7
4
2
3
0
1
3
3
3
3
8
11
Stack and Queue
1
Queue
Data structure with First-In First-Out (FIFO) behavior
Out
In
C
B
A
B
A
2
Typical Operations
on Queue
REAR
Enqueue
isempty: determines if the queue is empty
isfull: determines if the queue is full
in case of a bounded size queue
front:
returns the element at front of the queue
enqueue: inserts an element at the rear
dequeue: removes the element in front
Dequeue
FRONT
3
Possible Implementations
Linear Arrays:
(static/dynamicaly allocated)
front
Circular Arrays:
(static/dynamically allocated)
rear
front
rear
Linked Lists: Use a linear
linked list with insert_rear
and delete_front operations
Can be implemented by a 1-d
array using modulus operations
4
Circular Queue
[3]
[4]
[2]
[5]
[1]
[6]
[0]
[7]
front=0
rear=0
5
Circular Queue
[4]
[3]
[3]
[4]
C
[5]
[2]
[1]
[6]
[0]
[7]
[2]
[1]
D
[5]
B
A
front=0 [0]
rear = 4
[6]
After insertion
of A, B, C, D
[7]
front=0
rear=0
6
Circular Queue
[4]
[3]
[3]
[4]
C
[2]
[5]
[2]
[1]
[1]
[6]
[0]
[7]
D
rear = 4
[5]
B
A
[6]
front=0 [0]
After insertion
of A, B, C, D
[7]
front=0
rear=0
[4]
[3]
front=2
C
D
rear = 4
[5]
[2]
[1]
[6]
[0]
[7]
After deletion of
of A, B
7
front: index of queue-head (always empty)
rear: index of last element, unless rear = front
[3]
rear = 3
[4]
[3]
[2]
[5]
[1]
[6]
[0]
front=0
rear=0
[7]
Queue Empty
front=4
[4]
[2]
[5]
[1]
[6]
[0]
[7]
Queue Full
Queue Empty Condition: front == rear
Queue Full Condition: front == (rear + 1) % MAX_Q_SIZE
8
Creating and Initializing a Circular
Queue
Declaration
#define MAX_Q_SIZE 100
typedef struct {
int key; /* just an example, can have
any type of fields depending
on what is to be stored */
} element;
typedef struct {
element list[MAX_Q_SIZE];
int front, rear;
} queue;
Create and Initialize
queue Q;
Q.front = 0;
Q.rear = 0;
9
Operations
int isfull (queue *q)
{
if (q->front == ((q->rear + 1) %
MAX_Q_SIZE))
return 1;
return 0;
int isempty (queue *q)
}
{
if (q->front == q->rear)
return 1;
return 0;
}
10
Operations
element front( queue *q )
{
return q->list[(q->front + 1) % MAX_Q_SIZE];
}
void enqueue( queue *q, element e)
{
q->rear = (q->rear + 1)%
void dequeue( queue *q )
MAX_Q_SIZE;
{
q-> front =
q->list[q->rear] = e;
(q-> front + 1)%
}
MAX_Q_SIZE;
}
11
Practice Problems
• Implement the Queue as a linked list.
• Implement a Priority Queue which maintains the
items in an order (ascending/ descending) and
has additional functions like remove_max and
remove_min
• Maintain a Doctor’s appointment list
12
Download