You are on page 1of 47

Data structures through C language

Programming languages like C, C++, Java, .Net, Python… are used to develop
applications.

Where we use software applications?


Ans: In communication.

What application will do?


Ans : Store, Process and Remove data.

Note: We can store and process the data affectively only when we store the data in a
proper structure.

How can we structure the data?


• Using data structures and algorithms.

Is Data structures programming language?


• No.
• DS is a set of algorithms.
• DS is used to arrange the data in the application with proper structure.
• We must implement these algorithms using any programming language.

C lang : We must implement all algorithms manually.


C++ : Manual implementation.
Java: Pre-ready as Collections
Python: Pre-ready as Collections.

List of algorithms:
What all the concepts we use in C to implement algorithms?
1. Functions
2. Arrays
3. Structures
4. Pointers
5. Dynamic Memory Allocation.

Abstract Data type(ADT):


• The technical representation of algorithm as prototype.
• We can implement the prototype using any programming language.

Static v/s Dynamic memory:


• In C application, we can allocate the memory to store the information in 2 ways
o Static – fixed size
o Dynamic – size varies

Static memory:
• All primitive data types having fixed size of memory.
• Using primitive variables we can allocate fixed memory blocks to store the data.

• Derived data types are Array and String


• User defined data types are Structure and Union
• We can allocate the memory to derived types and user defined types in 2 ways.

Static allocation:
• Array can store more than 1 element but of same data type.
• String stores only characters as elements.
• Structure can store different types of data like Emp records, Student records,
Account records and so on.

Dynamic memory:
• Once we allocate the memory, we can increase or decrease the size of memory
block depends on requirement.
• We can allocate memory using pointers.
• Pointer can store a memory block address of any size.

When Static memory allocates?


At Compile time (completely wrong)
At runtime – while programming is running.

When Dynamic memory allocates?


At runtime – while programming is running.
Who will allocate Static memory?
Every application run by OS.
OS allocate required memory to execute the application.

What is Compiler?
• It is a translator(program)
• It will check whether the program is syntactically correct or not.
• If the program follows syntax rules, it converts the source code into machine
code.
• Note that, compiler is not responsible for allocating the memory.

How can we allocate memory dynamically in C language?


• Using the functionality of stdlib.h header file.
• Stdlib.h header file is providing 4 standard methods to allocate and de-allocate
the memory.
o Malloc()
o Calloc()
o Realloc()
o Free()
C - Functions

What is Function?
• A block of instructions that performs a task.
• Function takes input(arguments), process the input and generate output.

main():
• C application execution starts with main() function.
• OS invokes main() function automatically.
• Main() function is pre-defined as

int main( )
{
….
Logic
….
return 0;
}

Every application is a collection of functions:

Every function consist 3 things:


1. Function Prototype: It is a single statement; it represents memory size of function.
2. Function Definition: it is a block which contains logic.
3. Function Call: It is a single statement – used to access the logic.
We must call every function explicitly to execute the logic.
If we don’t call, the logic will not execute.

• C library is a set of header files.


• Header file is a collection of pre-defined functions
• We can use these functions by including the header file into program.
• After inclusion, we must call the function to execute the logic.
Only main() function executes automatically.
Other functions must be called explicitly.

#include<stdio.h>
void fun(void);

int main()
{
printf("Main \n");
return 0;
}

void fun(void)
{
printf("fun \n");
}

• We can call the function from any other function definition.


• Calling function : From which we will call the function.
• Called function: The function which is called.
• Once called function execution completes, the control back to calling function.

#include<stdio.h>
void fun(void);

int main()
{
printf("Main starts\n");
fun();
printf("Main ends \n");
return 0;
}

void fun(void)
{
printf("fun \n");
}
We can define more than 1 function in a program.
We can define functions in any order.

#include<stdio.h>
void m1(void);
void m2(void);

void m2()
{
printf("Say Hi \n");
}

void m1()
{
printf("Say Hello \n");
}

int main()
{
printf("1\n");
m1();
printf("2\n");
m2();
printf("3\n");
return 0;
}

#include<stdio.h>
void m1(void);
void m2(void);
int main()
{
printf("3\n");
m1();
printf("4\n");
m2();
printf("1\n");
return 0;
}

void m1()
{
printf("7 \n");
}

void m2()
{
printf("8 \n");
m1();
printf("5 \n");
}

Function with arguments(input) without return values:


#include<stdio.h>
void even(int);
int main()
{
even(5);
even(12);
return 0;
}

void even(int num)


{
if(num%2==0)
printf("%d is Even num \n", num);
else
printf("%d is Not even num \n", num);
}

Function takes input(arguments) returns output:


#include<stdio.h>
int add(int, int);
int main()
{
int sum;
sum = add(12,34);
printf("sum is : %d \n", sum);
return 0;
}

int add(int x, int y)


{
int c=x+y;
return c;
}

We can write above code without using local variables as follows:


#include<stdio.h>
int add(int, int);
int main()
{
printf("sum is : %d \n", add(12,34));
return 0;
}
int add(int x, int y)
{
return x+y;
}

Perform arithmetic operations using functions:


#include<stdio.h>
int add(int, int);
int subtract(int, int);
int multiply(int, int);

int main()
{
int choice, a, b, res;
while(1)
{
printf("Arithmetic operations :\n");
printf("1. add \n");
printf("2. subtract \n");
printf("3. multiply \n");
printf("4. quit \n");

printf("Enter your choice : ");


scanf("%d", &choice);

if(choice>=1 && choice<=3)


{
printf("Enter 2 numbers : \n");
scanf("%d%d", &a, &b);
}
switch(choice)
{
case 1 : res = add(a, b);
printf("Add result is : %d \n", res);
break;

case 2 : res = subtract(a, b);


printf("Subtraction result is : %d \n", res);
break;

case 3 : res = multiply(a, b);


printf("Multiplication result is : %d \n", res);
break;

case 4 : exit(1);

default : printf("Invalid choice \n");


}
}
return 0;
}

int add(int x, int y)


{
return x+y;
}
int subtract(int x, int y)
{
return x-y;
}
int multiply(int x, int y)
{
return x*y;
}
Arrays

• Using primitive variables, we can store only 1 value at a time


• For example.
o Int a = 10;
o a = 20;
o Print(a);
• To store more than one element such as student marks, mobile numbers,
account numbers we use arrays.

• Array can store more than one element but of same type.
• Array variable stores address(base) where as primitive variable stores value.
• Array elements store in consecutive locations.
• We can access array elements using their index starts with 0

Code to display size of int:


#include<stdio.h>
int main()
{
printf("size of int : %d \n", sizeof(int));
return 0;
}

Program to display size of array and length of array:


#include<stdio.h>
int main()
{
int arr[5];
printf("size of array : %d \n", sizeof(arr));
printf("size of array element : %d \n", sizeof(arr[0]));
printf("Length of array : %d \n", sizeof(arr)/sizeof(arr[0]));
return 0;
}
• It is recommended to use loops(for) to process elements of array.
• We repeat the loop from first index to last index to process element by element.

• Array can be declared either locally or globally.


• If the array is local, all elements become garbage values.
• If the array is global, all elements initializes with default values.

#include<stdio.h>
int arr[5];
int main()
{
int i;
printf("Array elements are : \n");
for(i=0 ; i<5 ; i++)
{
printf("%d \n", arr[i]);
}
return 0;
}

• Pointer default value is null.


• Null is a string – hence we display null value using %s.

#include<stdio.h>
int* arr[5];
int main()
{
int i;
printf("Array elements are : \n");
for(i=0 ; i<5 ; i++)
{
printf("%s \n", arr[i]);
}
return 0;
}

• We can initialize the array directly using assignment operator.


• If we assign the element less than its length, remaining values become default
values.

#include<stdio.h>
int main()
{
int arr[5] = {10,20}, i;
printf("Array elements are : \n");
for(i=0 ; i<5 ; i++)
{
printf("%d \n", arr[i]);
}
return 0;
}

Passing array as parameter to function:


• Array variable stores base address of memory block.
• Passing array is nothing but, passing the address of array to the function.
• Duplicate array will not be created in the called function.

#include<stdio.h>
void display(int[]);
int main()
{
int a[5] = {10,20,30,40,50};
display(a);
return 0;
}
void display(int x[])
{
int i;
printf("Array elements are : \n");
for(i=0 ; i<5 ; i++)
{
printf("%d \n", x[i]);
}
}

#include<stdio.h>
void modify(int[]);
int main()
{
int a[5] = {10,20,30,40,50}, i;
modify(a);
printf("Array elements are : \n");
for(i=0 ; i<5 ; i++)
{
printf("%d \n", a[i]);
}
return 0;
}
void modify(int x[])
{
int i;
for(i=0 ; i<5 ; i++)
{
x[i]=x[i]-5;
}
}

Strings

• String is one dimensional character array.


• We can store n-1 characters into an array of size n
• Last character is null(\0) character.
• All string operations can perform using null character only.

• Character occupies one byte memory.


• Character array variable stores base address of block.
• We can process elements using index.
%s:
• It is string type format specified.
• It is used to read and display the elements of string.

Note: Array elements must be processed one by one using loop.


#include<stdio.h>
int main()
{
int arr[5] = {10,20,30,40,50}, i;
for(i=0 ; i<5 ; i++)
{
printf("%d \n", arr[i]);
}
return 0;
}

String can be displayed all at once using %s specifier.


Printf() function display all elements from first index to null character using %s.

#include<stdio.h>
int main()
{
char name[20] = "Annie";
printf("%s \n", name);
return 0;
}
Reading elements into array:
• We must repeat loop to read elements into array.
• We need to specify every location address to read the element of that location.
• As we know the length of array to read elements, we can use loops.

We can read the string directly into array without using loops.
No need to specify the address of each location.

#include<stdio.h>
int main()
{
char name[20];
printf("Enter your name : ");
scanf("%s", name);
printf("Hello %s, welcome to DS class \n", name);
return 0;
}

Why loop is not required to read the characters into array?


Why & operator not used in scanf function?
• While reading elements into array, we can specify the number of element to
input.
• While reading the string, we cannot specify the number of character to input.
• “%s” is a pre-defined program.
• It takes the base address of memory block.
• It reads character by character and stores from the base address.
• Once input is over, it will add null character at the end of the string.

#include<stdio.h>
int main()
{
char name[20];
printf("Enter your name : ");
scanf("%s", name);
printf("Hello %s, welcome to DS class \n", name);
return 0;
}
Gets():
• Pre-defined function can read multi word strings.
• Stop reading characters into array only when we press enter key.

#include<stdio.h>
int main()
{
char name[20];
printf("Enter your name : ");
gets(name);
printf("Hello %s, welcome to DS class \n", name);
return 0;
}

Output:
Enter your name : sri vatsa
Hello sri vatsa, welcome to DS class
Structures

• Structure is called user defined data type.


• Primitive variable can store only 1 element at a time.
• Arrays can store more than one element but of same type.
• To store records such as Employee details, Student details, Account details and
so on, we use structures.
• Structure can store more than 1 element of different data types.

Syntax :
struct identity
{
datatype ele1;
datatype ele2;
..
..
datatype elen;
};

Examples:

• Primitive variable directly store the value.


• Array variable stores the base address of memory block. We access elements
using index.
• Structure variable stores the base address like array. We access elements using
dot(.) operator.
Size of Structure:
• Size of structure is equals to sum of individual elements size defined in structure.
• We can find the size using sizeof() function.

Size of integer:
#include <stdio.h>
int main()
{
int x;
printf("int size : %d \n", sizeof(x));
printf("int size : %d \n", sizeof(int));
return 0;
}

Size of Emp structure:


#include <stdio.h>
struct Emp
{
int id;
char name[20];
float salary;
};
int main()
{
struct Emp e;
printf("Emp size : %d \n", sizeof(e));
printf("Emp size : %d \n", sizeof(struct Emp));
return 0;
}

• We can initialize the structure directly using assignment operator.


• We must follow the order of element while assigning values.

#include <stdio.h>
struct Emp
{
int id;
char name[20];
float salary;
};
int main()
{
struct Emp e = {101, "Hareen", 50000};
printf("Emp id : %d \n", e.id);
printf("Emp name : %s \n", e.name);
printf("Emp salary : %f \n", e.salary);
return 0;
}

• We can read structure values dynamically at runtime.

#include <stdio.h>
struct Emp
{
int id;
char name[20];
float salary;
};
int main()
{
struct Emp e ;

printf("Enter Emp details : \n");


scanf("%d%s%f", &e.id, e.name, &e.salary);

printf("Emp details are : \n");


printf("Emp id : %d \n", e.id);
printf("Emp name : %s \n", e.name);
printf("Emp salary : %f \n", e.salary);
return 0;
}

Passing structure as a parameter to function:


• We can pass structure like array or string.
• The base address will be sent to the function.
• We need to declare same structure type argument to store the address.

#include <stdio.h>
struct Emp
{
int id;
char name[20];
float salary;
};
void display(struct Emp);
int main()
{
struct Emp e ;
printf("Enter Emp details : \n");
scanf("%d%s%f", &e.id, e.name, &e.salary);
display(e);
return 0;
}
void display(struct Emp x)
{
printf("Emp details are : \n");
printf("Emp id : %d \n", x.id);
printf("Emp name : %s \n", x.name);
printf("Emp salary : %f \n", x.salary);
return 0;
}
A function can return the structure:
• After processing the data inside the function, it can returns the value.
• A function can return any type of data.
• We must specify the structure type as return type when we return from that
structure.

#include <stdio.h>
struct Emp
{
int id;
char name[20];
float salary;
};
struct Emp read();
int main()
{
struct Emp x;
x = read();
printf("Emp details are : \n");
printf("Emp id : %d \n", x.id);
printf("Emp name : %s \n", x.name);
printf("Emp salary : %f \n", x.salary);
return 0;
}
struct Emp read()
{
struct Emp e;
printf("Enter Emp details : \n");
scanf("%d%s%f", &e.id, e.name, &e.salary);
return e;
}
Pointers

• Pointer is a derived data type.


• Pointer variable stores address of memory location.

• We need to specify asterisk(*) for every pointer type variable.

The 2 operators using in pointers are


1. Address(&): The operator returns the memory address of specified variable.
2. Pointer(*): The operator returns the data in the specified memory location
#include <stdio.h>
int main()
{
int a=10;
int *p=&a;
printf("%d \n", a);
printf("%d \n", p);
printf("%d \n", &a);
printf("%d \n", &p);
printf("%d \n", *p);
printf("%d \n", *(&p));
printf("%d \n", **(&p));
return 0;
}
Why Java doesn’t support pointers concept?
• Every programming language supports pointers.
• C supports Internal and External Pointers
• Java supports only Internal pointers.
• Object reference variable in Java is pointer type – hence the default value is
null.

Types of pointers:
• Typed pointers: These pointers can point to specific type of data.
o Int* -> can points to int data only
o Float* -> can points to float data only
o Struct Emp* -> can points to only Emp data.
• Uptyped pointer: This pointer can points to any type of data. It is also called
Generic pointer.
o Void* -> Can points to any type of data.

Call By Value:
• Calling the function by passing values as parameters.
• All parameter values will be copied into arguments(local variables) of called
function.
• The data which is processed in the called function cannot be accessed from the
calling function.

#include <stdio.h>
void modify(int, int);
int main()
{
int a=10, b=20;
modify(a, b);
printf("a value is : %d \n", a);
printf("b value is : %d \n", b);
return 0;
}
void modify(int a , int b)
{
a=a+5;
b=b+5;
}

Call By Reference:
• Calling the function by passing address(reference) as parameter.
• Pointer variables can collect address.
• We need to collect these references into pointer type arguments in called
function.
• When we modify the data in called function that affects calling function
arguments data.

#include <stdio.h>
void modify(int*, int*);
int main()
{
int a=10, b=20;
modify(&a, &b);
printf("a value is : %d \n", a);
printf("b value is : %d \n", b);
return 0;
}
void modify(int* a , int* b)
{
*a = *a+5;
*b = *b+5;
}

Note: Passing array as parameter (or) Passing structure as parameter comes under “Call
by Reference”.

#include <stdio.h>
struct Emp
{
int id;
char name[20];
float salary;
};
void display(struct Emp);
int main()
{
struct Emp e ;
printf("Enter Emp details : \n");
scanf("%d%s%f", &e.id, e.name, &e.salary);
display(e);
return 0;
}
void display(struct Emp x)
{
printf("Emp details are : \n");
printf("Emp id : %d \n", x.id);
printf("Emp name : %s \n", x.name);
printf("Emp salary : %f \n", x.salary);
return 0;
}

Size of Pointer:
• The size of pointer varies based on compiler type.

Compiler type Int size Pointer size


16 bit 2 bytes 2 bytes
32 bit 4 bytes 4 bytes

• In 16 bit compiler, memory locations will be 2^16 to store the values.


• In 32 bit compiler, memory locations will be 2^32.
• Pointer variable always store a memory address that is a value between 0 to
2^16 or 2^32.
• To store any value between 0 to 2^16, the variable memory should be 2 bytes.

#include <stdio.h>
struct Emp
{
int id;
char name[20];
float salary;
};
int main()
{
char* cp;
short* sp;
double* dp;
struct Emp* ep;
printf("size of char* : %d \n", sizeof(cp));
printf("size of short* : %d \n", sizeof(sp));
printf("size of double* : %d \n", sizeof(dp));
printf("size of Emp* : %d \n", sizeof(ep));
return 0;
}
Pointer modify:
• Increment and Decrement operators are called Modify operators.
• Modify operators increase or decrease the value of integer by one.

#include <stdio.h>
int main()
{
int x=10, y=20;
printf("x value : %d \n", x);
printf("++x value : %d \n", ++x);

printf("y value : %d \n", y);


printf("--y value : %d \n", --y);
return 0;
}

• When we modify a pointer, the value will be increased or decreased by size


bytes.
• Char* modified by 1 byte
• Float* modified by 4 bytes

#include <stdio.h>
int main()
{
char ch='g';
short s=10;
float f=2.3;
char* cp=&ch;
short* sp=&s;
float* fp=&f;

printf("cp value : %u \n", cp);


printf("++cp value : %u \n", ++cp);

printf("sp value : %u \n", sp);


printf("++sp value : %u \n", ++sp);

printf("fp value : %u \n", fp);


printf("++fp value : %u \n", ++fp);

return 0;
}

• Pointer modify concept introduced to process the elements of array when


pointer points to an array.
• Array holds base address of memory block.
• Array working like internal pointer variable.
• When we access elements using index, the expression converts as follows.

#include <stdio.h>
int main()
{
int arr[5] = {10,20,30,40,50}, i;

printf("Array elements are : \n");


for(i=0 ; i<5 ; i++)
{
printf("%d \t", arr[i]);
printf("%d \t", *(arr+i));
printf("%d \t", *(i+arr));
printf("%d \n", i[arr]);
}
return 0;
}

Pointer to structure:
• We can create pointers to user defined data types also.
• We access structure elements using dot(.) operator.

#include <stdio.h>
struct Emp
{
int id;
char name[20];
float salary;
};
int main()
{
struct Emp e;
printf("Enter Emp details : \n");
scanf("%d%s%f", &e.id, e.name, &e.salary);

printf("Name : %s \n", e.name);


return 0;
}

• When a pointer is pointing to the structure, we use arrow(->) operator to access


the elements.

#include <stdio.h>
struct Emp
{
int id;
char name[20];
float salary;
};
int main()
{
struct Emp e;
struct Emp *p = &e;
printf("Enter Emp details : \n");
scanf("%d%s%f", &p->id, p->name, &p->salary);

printf("Name : %s \n", p->name);


return 0;
}

Dynamic Memory Allocation

• In C programming language, we allocate memory in 2 ways


o Static memory – Fixed in size
o Dynamic memory – Size varies
• Static memory is allocated to ordinary variables as follows.
stdlib.h:
• Pre-defined header file belongs to C library.
• It is providing functionality to allocate and de-allocate the memory.
• The functions are
o Malloc(): Allocate memory dynamically to structures
o Calloc(): Allocate memory to arrays.
o Realloc(): Increase the Decrease the size of array which is allocated using
Calloc()
o Free(): De-allocate the memory.

Malloc():
• Allocate memory to structures dynamically.
• Allocated block address will be assigned to pointer type variable.
• The prototype is..
• Malloc() function allocates size bytes memory and returns base address of
memory block.
• It returns NULL pointer if the memory is not available.

Code:
#include<stdio.h>
#include<stdlib.h>
struct Emp
{
int id;
char name[20];
float salary;
};
int main()
{
struct Emp *p;
p = (struct Emp*)malloc(sizeof(struct Emp));

if(p==NULL)
{
printf("Out of memory \n");
}
else
{
printf("Enter Emp details : \n");
scanf("%d%s%f", &p->id, p->name, &p->salary);
printf("Name : %s \n", p->name);
}
return 0;
}
Calloc():
• It is used to allocate memory to arrays dynamically.
• It is belongs to stdlib.h header file.
• The prototype is:
o void* calloc(size_t n, size_t size);

• After memory allocation, all the locations initializes with default values.

Note: When a pointer is pointing to array, we access elements using addresses not
through indexing. Generally we use arr[i] as *(arr+i)

#include<stdio.h>
#include<stdlib.h>
int main()
{
int *arr, n, i;
printf("Enter array size : ");
scanf("%d", &n);
arr = (int*)calloc(n, sizeof(int));
if(arr==NULL)
{
printf("Out of memory \n");
}
else
{
printf("Array default values are : \n");
for(i=0 ; i<n ; i++)
{
printf("%d \n", *(arr+i));
}
}
return 0;
}

Reading elements into array and find the sum of all elements in array:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *arr, n, i, sum=0;
printf("Enter array size : ");
scanf("%d", &n);
arr = (int*)calloc(n, sizeof(int));
if(arr==NULL)
{
printf("Out of memory \n");
}
else
{
printf("Enter %d elements : \n", n);
for(i=0 ; i<n ; i++)
{
scanf("%d", arr+i);
}
for(i=0 ; i<n ; i++)
{
sum = sum + *(arr+i);
}
printf("Sum of array elements : %d \n", sum);
}
return 0;
}

You might also like