0% found this document useful (0 votes)
17 views261 pages

CTSD All Chapters

The document covers the fundamentals of pointers in C programming, including their syntax, advantages, and applications such as dynamic memory allocation and managing complex data structures. It explains the relationship between pointers and arrays, the use of pointers as function arguments, and the concept of dangling pointers. Additionally, it introduces dynamic memory allocation (DMA) and its benefits, emphasizing the flexibility and efficiency it provides in memory management.

Uploaded by

rahulroughwork81
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views261 pages

CTSD All Chapters

The document covers the fundamentals of pointers in C programming, including their syntax, advantages, and applications such as dynamic memory allocation and managing complex data structures. It explains the relationship between pointers and arrays, the use of pointers as function arguments, and the concept of dangling pointers. Additionally, it introduces dynamic memory allocation (DMA) and its benefits, emphasizing the flexibility and efficiency it provides in memory management.

Uploaded by

rahulroughwork81
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 261

CTSD- 2 (303105151)

Sunny M. Ramchandani
Assistant Professor
Computer Science and Engineering
CHAPTER
- 1Pointers
Syllabus
Basics of pointers,
Advantages of pointers
Accessing a variable through its pointer
Pointers and arrays
Array of pointers
Pointer to pointer
Pointer as a function argument
Call by value & call by reference
Dangling Pointer
Introduction
Pointers are variables that store memory addresses, enabling efficient data access
and manipulation.
They are fundamental in programming for dynamic memory allocation, array
handling, and passing arguments by reference.
Pointers can be used to create advanced data structures like linked lists and
manage multi-level indirection with concepts like pointer-to-pointer and array of
pointers.
W hile powerful, pointers require careful handling to avoid issues like dangling
pointers and memory leaks.
Mastery of pointers is essential for optimized and low-level programming.
Pointer
Syntax p is integer pointer variable
datatype *ptr_variablename;
& is address of or referencing operator which
returns memory address of variable.
Example * is indirection or dereferencing operator which
returns value stored at that memory address.
void main()
{
& operator is the inverse of * operator
int a=10, *p; // assign memory address of a to pointer x = a is same as x = *(&a)
variable p
p = &a;
printf("% d % d % d", a, *p, p);
}

Output

10 10 5000
Advantages of Pointer
Efficient Memory Management: Pointers enable dynamic memory
allocation, allowing the allocation and deallocation of memory at
runtime, which is essential for optimizing resource usage.
Function Arguments (Pass by Reference): Pointers allow functions
to modify the original variables by passing their addresses, avoiding
the need to return values.
Efficient Array and String Handling: Instead of copying arrays or
strings, pointers can directly reference their memory, reducing
overhead and improving performance.
Advantages of Pointer(Cont.)
Building Complex Data Structures: Pointers are fundamental for creating and
managing dynamic data structures like linked lists, trees, graphs, and hash
tables.
Accessing Hardware Resources: Pointers allow direct manipulation of memory
and hardware addresses, making them crucial for system-level programming
and embedded systems.
Faster Execution for Large Data: By using pointers, you can avoid copying large
data structures, improving efficiency and speed in programs.
Flexibility in Coding: Pointers offer more control and flexibility in accessing and
modifying data, especially in situations where traditional variable access is
insufficient.
C Pointers Application
Passing Argument by reference
For accessing array elements
To return multiple value
For dynamic memory allocation
Why use Pointer?
C uses pointers to create dynamic data structures, data structures
built up from blocks of memory allocated from the heap at run-time.
Example linked list, tree, etc.
C uses pointers to handle variable parameters passed to functions.
Pointers in C provide an alternative way to access information
stored in arrays.
Pointer use in system level programming where memory addresses
are useful. For example shared memory used by multiple threads.
Pointers are used for file handling.
This is the reason why C is versatile.
Pointer arithmetic
#include< stdio.h> x++;
int main() y++;
{ z++;
int i=3,*x; printf("New address in x = % X\n",x);
float j=23.5,*y; printf("New address in y = % X\n",y);
char k='S', *z; printf("New address in z = % X\n",z);

x=&i; return 0;
y=&j; }
z=&k;
printf("Original address in x = % X\n",x);
printf("Original address in y = % X\n",y);
printf("Original address in z = % X\n",z);
Pointers and arrays
Relationship between pointer and array
An array name acts as a constant pointer to its first element.
Accessing elements in an array using a pointer is equivalent to
using the array subscript notation.
int arr[ ] = {10, 20, 30, 40};
int *p = arr; // 'p' points to the first element of 'arr'

printf("% d\n", arr[ 0] ); // Outputs 10


printf("% d\n", *p); // Outputs 10 (value at the first address)
printf("% d\n", *(p + 1)); // Outputs 20 (value at second address)
Pointers and arrays(Cont.)
Accessing Array Elements Using Pointers
Instead of using array indexing, elements can be accessed using
pointer arithmetic.
int arr[ ] = {5, 10, 15};
int *p = arr;

printf("% d\n", *p); // Outputs 5


printf("% d\n", *(p + 1)); // Outputs 10
printf("% d\n", *(p + 2)); // Outputs 15
Pointers and arrays(Cont.)
Pointers as Array Iterators
Pointers can be used to iterate through arrays more efficiently,
especially in large datasets.

int arr[ ] = {1, 2, 3, 4, 5};


int *p = arr;

for (int i = 0; i < 5; i++) {


printf("% d ", *(p + i)); // Access each element
}
Pointers and arrays(Cont.)
Arrays of Pointers
An array of pointers is a collection where each element stores
the address of another variable or array.
Commonly used for handling a list of strings or multi-
dimensional data.
char *names[ ] = {"Alice", "Bob", "Charlie"};
printf("% s\n", names[ 0] ); // Outputs "Alice"
printf("% s\n", *(names + 1)); // Outputs "Bob"
Key Differences Between Pointers and Arrays

Aspect Pointer Array


Definition Stores the address of a variable. Collection of elements stored in
Resizing Can point to any memory location dynamically. contiguous memory.
Fixed size defined during
Arithmetic Supports pointer arithmetic (p+1, p-1) declaration.
Limited to array indexing.
Memory Access Accesses values via dereferencing. Accesses values using indices
or pointer arithmetic.
Array of pointers
An array of pointers in C is an array where each element is a pointer.
Instead of storing data values directly, the array stores memory
addresses pointing to data.
Declaration:
data_type *array_name[ size] ;
Data_type specifies the type of data the pointers will point to.
array_name is the name of the array.
Size is the number of pointers in the array.
Array of pointers
#include <stdio.h>

int main() {
int a = 10, b = 20, c = 30;

// Declare an array of pointers


int *arr[ 3] ;

// Assign addresses of integers to the pointers


arr[ 0] = &a;
arr[ 1] = &b;
arr[ 2] = &c;

// Access and print the values using pointers


for (int i = 0; i < 3; i++) {
printf("Value at arr[ % d] : % d\n", i, *arr[ i] ); Output:
}
Value at arr[ 0] : 10
return 0; Value at arr[ 1] : 20
} Value at arr[ 2] : 30
Array of pointers
Advantages of Using Array of Pointers
Memory Efficiency: Useful for storing strings or large datasets
without duplicating data.
Dynamic Handling: You can modify the pointers to point to
different data during runtime.
Flexibility: It allows easy management of arrays with variable-
length elements like strings.
Array of Pointer
As we have an array of char, int, float etc, same way we can have an
array of pointer.
Individual elements of an array will store the address values.
So, an array is a collection of values of similar type. It can also be a
collection of references of similar type known by single name

Syntax
datatype *name[ size] ;

2018
int *ptr[ 5] ; //declares an array of integer pointer of size 5
Relation between Array & Pointer
W hen we declare an array, compiler allocates continuous blocks of
memory so that all the elements of an array can be stored in that
memory.
The address of first allocated byte or the address of first element is
assigned to an array name.
Thus array name works as pointer variable.
The address of first element is also known as base address.

2018
Array of Pointer –Cont.
An array of pointers ptr can be used to point to different rows of
matrix as follow:
for(i=0; i< 5; i++)
{
ptr[ i] =&mat[ i] [ 0] ;
}

By dynamic memory allocation, we do not


require to declare two-dimensional array, it
can be created dynamically using array of
pointers 2018
Pointer to Pointer –Double Pointer
Pointer holds the address of another variable of same type.
W hen a pointer holds the address of another pointer then such type
of pointer is known as pointer-to-pointer or double pointer.
The first pointer contains the address of the second pointer, which
points to the location that contains the actual value.
Syntax Pointer Pointer Variable
datatype **ptr_variablename;

int **ptr; address address value


Write a program to print variable, address of pointer variable and pointer to pointer
variable.
#include < stdio.h>
int main () {
int var;
int *ptr;
int **pptr;
var = 3000;
ptr = &var; // address of var
pptr = &ptr; // address of ptr using address of operator &
printf("Value of var = % d\n", var );
printf("Value available at *ptr = % d\n", *ptr );
printf("Value available at **pptr = % d\n", **pptr);
return 0;
}

Output

Value of var = 3000


Value available at *ptr = 3000
Value available at **pptr = 3000
Pointer as a function argument

Using a pointer as a function argument allows a function to directly


access and modify the original value of a variable passed to it.
This is particularly useful when you want to update the value of a
variable, pass large data structures efficiently, or return multiple
values from a function.
Syntax:
return_type function_name(data_type *pointer);

data_type *pointer :The parameter is a pointer to the data type.


Inside the function, the pointer can be dereferenced to access or
modify the original variable.
Pointer as a function argument
Example modify value using pointer

#include < stdio.h>

// Function to update the value of a variable using a pointer


void updateValue(int *num) {
*num = 42; // Modify the value at the address pointed to by num
}

int main() {
int x = 10;
printf("Before: x = % d\n", x);

// Pass the address of x to the function


updateValue(&x);

printf("After: x = % d\n", x); Output:


Before: x = 10
return 0; After: x = 42
}
Callcan
We by pass
Valuearguments
and Call bytoReference
the C function in two ways:
1.Call by Value:

Parameter passing in this method copies values from actual parameters


into formal function parameters. As a result, any changes made inside
the functions do not reflect in the caller’s parameters.
call// Cbyprogram
Valueto show use // Driver code
example : value
// of call by int main()
{
#include <stdio.h> int var1= 3, var2 = 2;

void swap(int var1, int var2) printf("Before swap Value of var1and var2 is: % d, % d\n", var1,
{ var2);
int temp = var1;
var1= var2; swap(var1, var2);
var2 = temp; printf("After swap Value of var1and var2 is: % d, % d", var1,var2);
}
return 0;
} Before swap Value of var1and var2 is: 3,
2
After swap Value of var1and var2 is: 3, 2
2. Call by Reference
2. Call by reference:

The caller’s actual parameters and the function’s actual


parameters refer to the same locations, so any changes made
inside the function are reflected in the caller’s actual
parameters.
We will discuss with this by an example :
Example : to show use of
// C program
// call by Reference int var1= 3, var2 = 2;
#include < stdio.h> printf("Before swap Value of var1and
void swap(int *var1, int *var2) var2 is: % d, % d\n", var1, var2);
{ swap(&var1, &var2);
int temp = *var1; printf("After swap Value of var1and var2
*var1= *var2; is: % d, % d", var1, var2);
*var2 = temp; return 0;
} }
// Driver code
int main()
{
Dangling Pointer
Dangling pointers in C:
In C programming pointers are used to manipulate memory addresses,
to store the address of some variable or memory location. But certain
situations and characteristics related to pointers become challenging in
terms of memory safety and program behavior these include Dangling
(when pointing to deallocated memory), Void (pointing to some data
location that doesn’t have any specific type), Null (absence of a valid
address), and W ild (uninitialized) pointers.
Dangling Pointer in C

A pointer pointing to a memory location that has been deleted (or freed) is called a dangling
pointer. Such a situation can lead to unexpected behavior in the program and also serve as a
source of bugs in C programs.
Assignment No 1
The Flowchart
1.W hat is a pointer? Write a program to declare a pointer and initialize it with the
address of a variable, then display the variable’s value using the pointer.
2.Illustrate how pointers enable call-by-reference. Compare it with call-by-value
using a swap function.
3.How can you use pointers to access elements of an array? Explain with syntax
and an example.
4.How can you use pointers to access elements of an array? Explain with syntax
and an example.
5.W hat is a pointer to a pointer? Write the syntax and explain with an example.
6.W hat is a dangling pointer? Explain with an example.
www.paruluniversity.ac.
in
Computational Thinking for Structured
Design- 2(303105151)
Sunny M Ramchandani
Computer Science & Engineering
CHAPTER
Dynamic-Memory
1 Allocation
Syllabus
Dynamic Memory Allocation:
Introduction,
merits of DMA
Malloc
Calloc
Realloc and free functions
Introduction
Dynamic Memory Allocation (DMA) in C allows programs to
allocate memory at runtime using functions from the stdlib.h library.
Unlike static memory allocation, where memory size is fixed during
compile time, DMA provides flexibility to allocate or release memory
during program execution.
This ensures efficient memory utilization, especially for data
structures like arrays and linked lists where the size may vary.
The commonly used functions for DMA are malloc(), calloc(),
realloc() and free().
Merits of DMA
Efficient Memory Utilization: Memory is allocated and deallocated at runtime, ensuring
that only the required amount of memory is used and released when no longer needed.
Flexibility: Unlike static allocation, DMA allows the creation of data structures (e.g.,
arrays, linked lists) with variable sizes, making programs more adaptable.
Supports Large Data: DMA enables handling large data structures by allocating
memory from the heap instead of the limited stack memory.
Scalability: Memory can be resized dynamically using realloc() as requirements change
during runtime, avoiding waste or shortage.
Ease of Managing Complex Data Structures: Dynamic memory makes it easy to
implement advanced structures like linked lists, trees, and graphs that require memory
allocation as nodes are added or removed.
Dynamic Memory allocation:

Since C is a structured language, it has some fixed rules for


programming. One of them includes changing the size of an array.

An array is a collection of items stored at contiguous memory


locations.
Computational Thinking
Structure Design
The length (size) of the array above is 9. But what if there is a requirement to change
this length (size)?

For example,
If there is a situation where only 5 elements are needed to be entered in this array. In
this case, the remaining 4 indices are just wasting memory in this array. So there is a
requirement to lessen the length (size) of the array from 9 to 5.

Take another situation. In this, there is an array of 9 elements with all 9 indices filled.
But there is a need to enter 3 more elements in this array. In this case, 3 indices more
are required. So the length (size) of the array needs to be changed from 9 to 12.
This procedure is referred to as Dynamic Memory Allocation in C.
Structure
Therefore,Design
C Dynamic Memory Allocation can be defined as a procedure in
which the size of a data structure (like Array) is changed during the runtime.
C provides some functions to achieve these tasks. There are 4 library
functions provided by C defined under < stdlib.h> header file to facilitate
dynamic memory allocation in C programming. They are:

malloc()
calloc()
free()
realloc()
Computational Thinking
C malloc() method :

The “malloc” or “memory allocation” method in C is used to dynamically allocate a


single large block of memory with the specified size. It returns a pointer of type void
which can be cast into a pointer of any form. It doesn’t Initialize memory at
execution time so that it has initialized each block with the default garbage value
initially.

Syntax of malloc() in C :
ptr = (cast-type*) malloc(byte-size)
COMPUTER LANGUAGE

If space is insufficient, allocation fails and returns a NULL pointer.


#include < stdio.h>
#include < stdlib.h> // Access and modify the allocated memory

int main() { *ptr = 25;


int *ptr; printf("Value stored at allocated memory: % d\n", *ptr);

// Allocate memory for an integer using malloc // Free the allocated memory when no longer needed
(important to prevent memory leaks)
ptr = (int*)malloc(sizeof(int)); free(ptr);

// Check if memory allocation was successful return 0;


(malloc may return NULL) }
if (ptr == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
calloc() method
“calloc” or “contiguous allocation” method in C is used to dynamically allocate the specified number
of blocks of memory of the specified type. it is very much similar to malloc() but has two different
points and these are:
It initializes each block with a default value ‘0’.
It has two parameters or arguments as compared to malloc().
Syntax of calloc() in C :

ptr = (cast-type*)calloc(n, element-size);

here, n is the no. of elements and element-size is the size of each element.
Programming Language
#include < stdio.h>
Programming Language
#include < stdlib.h>
// Access the allocated memory (elements will be zero-
initialized)
printf("First element: % d\n", ptr[ 0] );
int main() {
int *ptr; // You can now modify the elements as needed
int size_of_array = 5; ptr[ 2] = 75;
printf("Element at index 2: % d\n", ptr[ 2] );
// Allocate memory for an array of 5 integers using calloc
(initialized to zero) // Free the allocated memory when no longer needed
ptr = (int*)calloc(size_of_array, sizeof(int)); (important to prevent memory leaks)
free(ptr);
// Check if memory allocation was successful (calloc may
return NULL) return 0;
if (ptr == NULL) { }
printf("Memory allocation failed!\n");
return 1;
Programming Language
free() method
“free” method in C is used to dynamically de-allocate the memory. The
memory allocated using functions malloc() and calloc() is not de-
allocated on their own. Hence the free() method is used, whenever the
dynamic memory allocation takes place. It helps to reduce wastage of
memory by freeing it.

Syntax of free() in C :
free(ptr);
realloc() method
“realloc” or “re-allocation” method in C is used to dynamically change
the memory allocation of a previously allocated memory. In other
words, if the memory previously allocated with the help of malloc or
calloc is insufficient, realloc can be used to dynamically re-allocate
memory. re-allocation of memory maintains the already present value
and new blocks will be initialized with the default garbage value.

Syntax of realloc() in C :
ptr = realloc(ptr, newSize);
where ptr is reallocated with new size 'newSize'.
INTRODUCTION OF PROGRAMMING
LANGUAGE
Programing Applications

Programming Applications of Dynamic Memory Allocation


Dynamic memory allocation provides flexibility in memory management,
making it essential for solving real-world programming problems. Below
are some key programming applications:
INTRODUCTION OF PROGRAMMING
Dynamic Data Structures
LANGUAGE
Example: Linked lists, stacks, queues, trees, and graphs.
W hy?
These structures require dynamic memory allocation because their size
is not fixed and depends on runtime requirements.
Singly Linked List: Nodes are created dynamically as elements are
added.
Binary Trees: Each node is dynamically allocated based on input
data.
Dynamic Arrays

Example: Resizable arrays like std::vector in C++ or dynamically


allocated arrays using malloc/calloc in C.
W hy?
Arrays allocated with static memory have a fixed size, which may lead to
wastage or limitation. Dynamic memory allows for resizing using realloc.
Memory-Efficient Programs

Example: Applications requiring a large number of small objects (e.g.,


bitfields in embedded systems).
W hy?
malloc and calloc allow allocating memory just when needed, reducing
memory wastage. This is crucial in memory-constrained environments
like embedded systems or IoT devices.
Dangling Pointer
Dangling pointers in C:
In C programming pointers are used to manipulate memory addresses,
to store the address of some variable or memory location. But certain
situations and characteristics related to pointers become challenging in
terms of memory safety and program behavior these include Dangling
(when pointing to deallocated memory), Void (pointing to some data
location that doesn’t have any specific type), Null (absence of a valid
address), and W ild (uninitialized) pointers.
Dangling Pointer in C

A pointer pointing to a memory location that has been deleted (or freed) is called a dangling
pointer. Such a situation can lead to unexpected behavior in the program and also serve as a
source of bugs in C programs.
Assignment No 2
The Flowchart
Explain the concept of dynamic memory allocation and how it differs from static
memory allocation. Provide a real-world use case where DMA is advantageous.
Write a short note on the advantages of dynamic memory allocation with
examples.
W hat is the purpose of the malloc() function? Explain its syntax and functionality
with an example program.
How does calloc() differ from malloc()? Write a program to demonstrate the
difference.
Explain the purpose of realloc() function. Write a program to resize a dynamically
allocated array using realloc().
W hy is it important to use the free() function? Write a program to allocate and
then deallocate memory for a dynamic array.
www.paruluniversity.ac.
in
CTSD- 2 (303105151)
Pathan Bilalkhan R.
Assistant Professor
Computer Science and Engineering
Preprocessor Directives
Outline

File Inclusion
Macros
Conditional Compilation and Pragmas
What is Preprocessor directives?

In the C programming language, preprocessor directives are instructions given to the compiler to
preprocess the source code before actual compilation.

These directives always begin with a # symbol.

In the next slide detailed explanation of the most common preprocessor directives, including File
Inclusion, Macros, Conditional Compilation, and Pragmas, along with examples:
A preprocessor is a program that processes our source program before it is passed to
the compiler.
The preprocessor works on the source code and creates expanded source code.
The preprocessor offers several features called preprocessor directives.
Preprocessor starts with # symbol.
The directives can be placed anywhere in a program but are most often placed at the
beginning of the program, before the function definition.

5
Types of preprocessor directives.

Preprocessor Directives Description

#define Used to define a macro

#undef Used to undefine a macro

#include Used to include a file in the program

#ifdef Used to check whether a macro is defined by #define or not

#ifndef Used to check whether a macro is not defined by #define or not

#if Used to check specified condition

#elif Alternate code that executes when #if or #elif fails

#else This block executes when all #if & #elif fails

#endif Used to terminate conditional statements

6
File inclusion allows us to include the contents of one source code file into another.
This is done using the #include directive, which tells the C preprocessor to insert the
contents of the specified file into the current file at the point where the #include
directive appears.
File inclusion is commonly used to separate code into different files for better
organization and maintainability.
It also allows us to reuse code that is common to multiple source files without
having to duplicate it.
Syntax:
For Standard Library Inclusion: #include <header_file_name.h>
For Custom Header File Inclusion: #include "header_file_name.h"
7
Standard Library Inclusion:
The standard library inclusion is used to include standard header files that define
functions, constants, and macros used in C programming.
These header files are usually provided by the compiler or the operating system, and
are included using angle brackets (<>) as follows:
Ex:

Output: Hello world


Explanation:
We include the standard I/O header file stdio.h using the #include directive.
This header file defines the printf() function, which we use to print "Hello, world!" to the
console.
Because we included the header file using the angle bracket notation (< >), the
compiler will search for the header file in its standard library directories.
8
Custom Header File Inclusion:
Custom header files are created by the programmer to define functions, constants,
and macros that are specific to a particular program or module.
These header files are included using double quotes ("")
When a file is included using the #include directive, its contents are treated as if they were
part of the current file.
This means that any function or macro definitions in the included file are available for use
in the current file, and any global variables in the included file are visible in the current file.
Ex:

9
Output:
We include a custom header file add.h using the #include directive.
This header file contains a function add() that takes two integers as input and returns
their sum.
We use this function to calculate the sum of a and b, and then print the result to the
console using printf().
Because we included the header file using the double quote notation (" "), the compiler will
search for the header file in the current directory or in any directories specified by the - I flag
at compilation time.
1
0
A macro is a piece of code in a program that is replaced by the value of the macro.
Macro is defined by #define directive.
Whenever a macro name is encountered by the compiler, it replaces the name with
the definition of the macro.

11
Types of macros in C
1. Object-Like Macros:

An object-like macro is a simple identifier that will be replaced by a code fragment. It is


called object-like because it looks like an object in code that uses it. It is popularly used to
replace a symbolic name with a numerical/variable represented as a constant.
Ex:

Output:
12
2. Chain Macros:
Macros inside macros are termed chain macros. In chain macros first of all parent
macro is expanded then the child macro is expanded.
Ex:

Output:
13
3. Multiline Macros:
An object- like macro could have a multi- line. So to create a multi- line macro you have to use
backslash- newline.
Ex:

Output:

1
4
4. Function-Like Macros:
These macros are the same as a function call. It replaces the entire code instead of a
function name. A pair of parentheses immediately after the macro name is necessary.
Note: If we put a space between the macro name and the parentheses in the macro
definition, then the macro will not work.
Ex:

Output:
1
5
Six directives are available to control conditional compilation. They delimit blocks of program
text that are compiled only if a specified condition is true. These directives can be nested.
The program text within the blocks is arbitrary and may consist of preprocessor directives, C
statements, and so on. The beginning of the block of program text is marked by one of three
directives:
#if
#ifdef
#ifndef
Optionally, an alternative block of text can be set aside with one of two directives:
#else
#elif
The end of the block or alternative block is marked by the #endif directive.

1
6
#ifdef:
This directive checks whether the identifier is defied or not. Identifiers can be defined
by a #define directive or on the command line. If such identifiers have not been
subsequently undefined, they are considered currently defined.
Ex:

Output:

17
#ifndef
This directive checks to see if the identifier is not currently defined.
Ex:

Output:

1
8
#if:
This directive checks whether the constant-expression is true (nonzero). The operand
must be a constant integer expression that does not contain any increment (++),
decrement (- -), sizeof , pointer (*), address (&), and cast operators.
#elif:
The #elif directive performs a task similar to the combined use of the else-if statements in
C. This directive delimits alternative source lines to be compiled if the constant
expression in the corresponding #if , #ifdef , #ifndef , or another #elif directive is false and
if the additional constant expression presented in the #elif line is true. An #elif directive is
optional
#else
This directive delimits alternative source text to be compiled if the condition tested for in
the corresponding #if, #ifdef, or #ifndef directive is false. An #else directive is optional.
#endif
This directive ends the scope of the #if, #ifdef, #ifndef, #else, or #elif directive.

1
9
Ex:

Output:

2
0
#pragma is a special purpose directive that is used to turn on or off some features.
#pragma allows us to provide some additional information to the compiler.
Pragmas are compiler specific i.e., the behavior of pragma varies from compiler to
compiler.
1. #pragma startup and #pragma exit
These directives help us to specify the functions that are needed to run before the program
starts and just before the program exits i.e., before the control passes to the main() and
just before the control returns from the main().
Syntax:
#pragma startup function_name
#pragma exit function_name
21
Pragmas (#pragma)

#pragma is used to provide specific instructions to the compiler, often related to optimizations or
warnings.

Common Pragmas:

Disable Warnings:
#pragma warning(disable: 4996) // Disable a specific warning (MSVC)
Pack Structures:
#pragma pack(1) // Align structures to 1-byte boundaries
struct MyStruct {
char a;
int b;
};
Pragmas (#pragma)

#pragma is used to provide specific instructions to the compiler, often related to optimizations or
warnings.
Region Markers:
Common Pragmas:
Some compilers support marking code sections for
better organization.
Disable Warnings:
#pragma warning(disable: 4996) #pragma region MyRegion
// Disable a specific warning (MSVC) void function() {
Pack Structures: // Code here
#pragma pack(1) // Align structures to 1-byte boundaries }
struct MyStruct { #pragma endregion
char a;
int b;
};
Pragmas (#pragma)

Example: int main() {


#include < stdio.h> struct MyStruct s;
printf("Size of packed
#pragma pack(1) structure: % zu\n", sizeof(s));
struct MyStruct { return 0;
char a; }
int b;
};
Summary Table

Directive Purpose Example


#include Includes files into the #include < stdio.h>
#define program.
Defines constants or #define MAX 100
#if, #ifdef, #endif macros.
Includes/excludes code #ifdef DEBUG
conditionally.
#pragma Provides compiler-specific #pragma pack(1)
instructions (e.g., disable
warnings, packing
structures, etc.).
3. #pragma GCC poison
This directive is supported by the GCC compiler and is used to remove an identifier
completely from the program. If we want to block an identifier then we can use the
#pragma GCC poison directive.
Syntax: #pragma GCC poison identifier

26
4. #pragma GCC dependency:
The #pragma GCC dependency allows you to check the relative dates of the current file and
another file. If the other file is more recent than the current file, a warning is issued. This is
useful if the current file is derived from the other file, and should be regenerated.
Syntax: #pragma GCC dependency "main.c"

Explanation: At the compile time compiler will check whether the “parse.y” file is more
recent than the current source file. If it is, a warning will be issued during compilation.
27
5. #pragma GCC system_header
The #pragma GCC system_header directive in GCC is used to tell the compiler that the
given file should be treated as if it is a system header file. warnings that will be generated
by the compiler for code in that file will be suppressed hence it is
extremely useful when the programmer doesn’t want to see warnings or errors. This
pragma takes no arguments. It causes the rest of the code in the current file to be treated
as if it came from a system header.
Syntax: #pragma GCC system_header
Note:
The above code is for external library that
we want to include in our main code. So to
inform the compiler that external_library.h is
a system header, and we don’t want to see
warnings from it
the #pragma GCC system_header is used.

28
Example:

Output:

29
6. #pragma once
The #pragma once directive has a very simple concept. The header file containing this
directive is included only once even if the programmer includes it multiple times during a
compilation. This directive works similar to the #include guard idiom. Use of #pragma
once saves the program from multiple inclusion optimisation.
Syntax: #pragma once
Example:
#pragma once is used to avoid multiple inclusions.

Output:

30
CTSD- 2 (303105151)
Sunny M. Ramchandani
Assistant Professor
Computer Science and Engineering
CHAPTER
- 3 STRUCTURES, UNIONS
ENUMERATORS,
Syllabus
Enumerators: Enumerator Types
Structures:Declaration Initialization Accessing Structures, Complex
Structures, Structure and Functions Array of
structures Arrays within structures Anonymous structures Nested
structures pointers in structures Self-referential
structures Structure Padding
Unions: Bit fields
Typedef
What is Enumerators?
In the C programming language, enumerators are used to define a set of named integer constants.
This is done using the enum keyword, which stands for "enumeration."
Enumerators make code more readable and maintainable by allowing programmers to use meaningful
names instead of raw numeric values.
Syntax of Enum
enum EnumName {
ENUM_CONSTANT1,
ENUM_CONSTANT2,
ENUM_CONSTANT3,
...
};
What is Enumerators?

Key Points:
Default Values: The enumerators are assigned integer values starting
from 0 by default, incrementing by 1for each subsequent value.
Custom Values: You can assign specific integer values to some or all of
the enumerators.
Type: Enumerators are of type int in C.
Scope: Enumerators are globally visible if defined outside a function, or
locally visible if defined inside a function.
What is Enumerators?
Defining and Using Enumerators
Basic Example:
#include < stdio.h>
enum Weekdays { MONDAY, // 0 TUESDAY, // 1
W EDNESDAY, // 2 THURSDAY, // 3
FRIDAY, // 4 SATURDAY, // 5 SUNDAY // 6
};
int main() {
enum Weekdays today = W EDNESDAY;
printf("Day number: % d\n", today); // Output: 2
return 0;
Key Advantages of Enumerators

1.Code Readability:
Using meaningful names instead of raw numbers improves code clarity.
Example: FRIDAY is more descriptive than 4.
2.Maintenance:
If a value needs to change, you can update it in one place (the enum definition)
instead of changing it throughout the code.
3.Prevent Errors:
Enumerators restrict the values to the predefined set, reducing accidental
errors.
Customizing Enumerators

Partial Value Assignment:


Unassigned constants take the next integer value automatically.
enum Numbers {
ONE = 1,
TWO, // 2
FIVE = 5,
SIX // 6
};
Customizing Enumerators

Repeated Values:
Two or more enumerators can have the same value.
enum Status {
ACTIVE = 1,
ENABLED = 1,
DISABLED = 0
};
Customizing Enumerators
Enumerators with Typedef
You can combine typedef with enum for convenience.
#include < stdio.h>
typedef enum {SMALL = 1,MEDIUM, LARGE
} Size;

int main() {
Size shirtSize = MEDIUM;
printf("Shirt size: % d\n", shirtSize); // Output: 2
return 0;
}
Limitations of Enumerators

1.Enumerators in C are limited to integers. If you need other


types (e.g., strings), you must use alternative data structures
like arrays or structs.
2. Enumerators cannot perform range validation at runtime. It is
up to the programmer to ensure valid values.
Structures:

Declaration Initialization Accessing Structures, Complex


Structures, Structure and Functions Array of structures Arrays
within structures Anonymous structures Nested structures
pointers in structures Self-referential structures Structure
Padding.

In C programming, structures are user-defined data types that allow grouping different types of variables (of
possibly different data types) under a single name.
Structures are commonly used to represent real-world entities such as books, students, or employees.
Structure

Declaration of a Structure: A structure is declared using the struct keyword, followed by


the structure name and the set of members enclosed in curly braces.

struct structure_name { struct Student {

data_type char name[ 50] ;


member_name1; int age;
data_type
float grade;
member_name1;
};
....
....
};
Structure
Initialization of Structures: You can initialize a structure either during declaration or later in
the
code.
Initialization at the time of Declaration

You can directly initialize the members of a structure when you


declare it:

struct Student
Initialization student1=
After {"kalpesh patel", 20, 85.5}; struct Student student2;
Declaration
student2.age = 22;
If you have already declared a structure,
you can initialize its members later using student2.grade = 90.0;

dot notation: strcpy(student2.name, "kalpesh patel");


Structure
Designated Initializers (in C99 and later):

You can initialize members by specifying their names explicitly.

struct Student student1= {.age = 20, .name = "John", .grade =


85.5};
Accessing Structure Members
You can access the members of a structure using the dot (.) operator.

struct Student student1= {"John Doe", 20, 85.5};

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

printf("Age: % d\n", student1.age);

printf("Grade: % .2f\n", student1.grade);


Complex Structures
A complex structure may contain arrays, other
structures, or pointers as its members. This allows
creating nested structures. struct Event {

struct Date { char name[ 100] ;

int day; struct Date eventDate; // Nested structure

int month; float cost;

int year; };

};
struct Event event1= {"Conference", {12, 7, 2024}, 150.0};
Structure and Functions
Structures can be passed to functions either by value or by reference (using pointers). W hen passed by value, a
copy of the structure is created. W hen passed by reference, the function works with the original structure.

Passing Structure by Value: int main() {

void printStudent(struct Student student) { struct Student student1= {"Alice", 21, 90.5};

printf("Name: % s\n", student.name); printStudent(student1);

printf("Age: % d\n", student.age); return 0;

} }
Structure and Functions
Passing Structure by Reference (using Pointers): int main() {

void printStudent(struct Student* student) { struct Student student1= {"Alice", 21, 90.5};

printf("Name: % s\n", student-> name); // Use ` -> ` to printStudent(&student1); // Pass by reference


access members via pointer (address of student)

printf("Age: % d\n", student-> age); return 0;

} }
Array of Structures
An array of structures allows you to store multiple structures of the same type.

struct Student students[ 3] = {

{"John", 20, 85.5},

{"Alice", 21, 92.3},

{"Bob", 19, 78.6}

};

printf("First student: % s\n", students[ 0] .name);


Arrays Within Structures
Structures can have arrays as their members, allowing you to store multiple values of a particular type.

struct Student {

char name[ 50] ;

int grades[ 5] ; // Array within structure

};

struct Student student1= {"John", {85, 90, 78, 92, 88}};

printf("Grade 1: % d\n", student1.grades[ 0] );


Anonymous Structures
Anonymous structures do not require a name, and they are useful when creating one-time structures.

struct {

int x;

int y;

} point;

point.x = 10;

point.y = 20;

printf("Point coordinates: (% d, % d)\n", point.x, point.y);


Nested Structures
A structure can contain another structure as one of its members. This allows creating complex hierarchical data
representations.

struct Address { struct Person {

char street[ 100] ; char name[ 50] ;

char city[ 50] ; struct Address address; // Nested

int postalCode; structure

}; };
struct Person person1= {"John", {"Main St", "CityX", 12345}};

printf("Street: % s\n", person1.address.street);


Pointers to Structures
You can use pointers to structures, and it allows for dynamic memory allocation and manipulation of structure
Using
data.Pointers to Access Members: Dynamically Allocating Memory for Structures:

struct Student { struct Student *studentPtr = (struct Student*)malloc(sizeof(struct


Student));
char name[ 50] ;
strcpy(studentPtr->name, "Bob");
int age;
studentPtr->age = 22;
};

struct Student student1= {"Alice", 21};


printf("Name: % s\n", studentPtr->name);
struct Student *ptr = &student1;
printf("Age: % d\n", studentPtr->age);
printf("Name: % s\n", ptr->name); // Use ` ->` for accessing members via
pointer free(studentPtr); // Free allocated memory

printf("Age: % d\n", ptr->age);


Self-Referential Structures
A self-referential structure is a structure that has a pointer to itself. This is commonly used for linked lists or
tree data structures.

struct Node {

int data;

struct Node* next; // Pointer to the same type of structure

};

struct Node node1;

node1.data = 10;

node1.next = NULL; // Points to NULL (end of list)


Structure Padding and Alignment
To ensure that data is aligned correctly in memory for performance reasons, compilers may insert "padding"
between structure members. This is to meet alignment requirements (e.g., ensuring that an int is aligned on a 4-
byte boundary).
Example of structure padding:

struct MyStruct {

char a; // 1byte

int b; // 4 bytes

};

In this structure, there will be padding bytes inserted after a to align b on a 4-byte boundary. The size of the structure may not be equal to the sum of the
sizes of its members due to padding.

You can use sizeof to check the size:

printf("Size of MyStruct: % zu\n", sizeof(struct MyStruct));


Summary of Structure Types and Concepts
Feature Description
Declaration struct StructName { ... };
Initialization structName member1= {value1, value2};
Accessing Members Use dot (.) or arrow (->) operator to access members
Complex Structures Structures containing arrays, pointers, or other structures as
Structure and Functions Structures
members can be passed to functions by value or reference (using
Array of Structures Array to store multiple structures of the same type
pointers)
Arrays within Structures Structures can have arrays as members
Anonymous Structures Structures without a name, used for one-time use
Nested Structures Structures containing other structures as members
Pointers in Structures Using pointers to structures allows dynamic memory allocation
Self-Referential Structures Structures with a pointer to the same type, useful for linked lists, trees
Structure Padding Compilers may insert padding for memory alignment reasons
Unions: Bit fields , Typedef
In C, unions, bit fields, and typedef are distinct features, each serving different purposes but often used
together for more efficient memory management and code readability.

Union Syntax:
Unions in C
union UnionName {
A union is a special data type that allows different data
dataType1member1;
types to be stored in the same memory location. The size
of a union is the size of its largest member, as all dataType2 member2;

members share the same memory. dataType3 member3;

...

};
Unions: Bit fields , Typedef
Key Features of Unions:

All members of a union share the same memory location.

The size of a union is the size of its largest member.

At any given time, only one of the union members can


hold a value, and writing to one member will overwrite the
others.
Example of a Union:
#include < stdio.h> int main() { data.f = 3.14; // Assign float value

union Data union Data data; printf("data.f = % .2f\n", data.f);

{ strcpy(data.str, "Hello, World!"); // Assign string value

int i; // Assign integer value printf("data.str = % s\n", data.str);

float f; data.i = 10; return 0; // Note: only the last assigned member is valid

} Output:
char str[ 20] ; printf("data.i = % d\n", data.i);
data.i = 10
};
data.f = 3.14

data.str = Hello, World!


Bit Fields in C
Bit fields allow specifying the number of bits that each structure member should occupy. This feature is commonly used when memory is constrained
(e.g., in embedded systems) and small values or flags need to be stored efficiently.

Bit Field Syntax:

struct StructName {

dataType member1: numberOfBits;

dataType member2 : numberOfBits;

...

};

The dataType defines the underlying type (usually int, unsigned int, or char).

The numberOfBits specifies how many bits the member will use.
Example of Bit Fields
int main() {
#include < stdio.h> Output:
struct BitField bf;
a=5

b = 19
bf.a = 5; // Binary: 101
struct BitField {
bf.b = 19; // Binary: 10011 c = 33

unsigned int a : 3; // 3 bits bf.c = 33; // Binary: 100001 Explanation:

unsigned int b : 5; // 5 bits In this example, the bit fields a, b, and c use exactly 3, 5, and 6 bits,
printf("a = % d\n", bf.a); // Output: 5
respectively.
unsigned int c : 6; // 6 bits printf("b = % d\n", bf.b); // Output: 19
The data type unsigned int ensures that the values are non-
printf("c = % d\n", bf.c); // Output: 33
}; negative.

return 0;
Bit fields are used to save space when you know the exact number
of bits you need for each member.
}
Example of Bit Fields
Bit Field Characteristics:

The maximum number of bits a bit field can use depends on the size of the underlying data type (e.g.,
an int is typically 32 bits).

Bit fields can be packed together in a structure, saving memory space compared to standard integer
types.
Typedef in C
The typedef keyword in C is used to define a new name (alias) for an existing type. This can make the code
more readable and allow for easier changes to data types.

Syntax of Typedef:

typedef existing_type new_type_name;

W hy Use typedef?

To create more meaningful or easier-to-read names for complex data types.

To simplify code, especially when dealing with pointers or structures.


Example of Typedef with Unions
int main() { strcpy(data.str, "Hello, World!");
#include < stdio.h> printf("data.str = % s\n", data.str);
Data data;
return 0;
typedef union { }
data.i = 10;
int i; Output:
printf("data.i = % d\n", data.i); data.i = 10
float f; data.f = 3.14
data.str = Hello, World!
char str[ 20] ;
In this example:
data.f = 3.14;
} Data; The typedef creates a new type Data as an alias for the
union.
printf("data.f = % .2f\n",
Now, instead of using union Data every time, we can
data.f); simply use Data.
Example of Typedef with Bit Fields
int main() { printf("a = % d\n", bf.a); Output:
#include < stdio.h>
BitField bf; printf("b = % d\n", bf.b); a= 5

printf("c = % d\n", bf.c); b = 19


typedef struct {
bf.a = 5; c = 33
unsigned int a : 3;
bf.b = 19; return 0; In this example:
unsigned int b : 5;
The typedef allows us to create a
bf.c = 33; }
unsigned int c : 6; new name BitField for the structure
containing bit fields.
} BitField;
This simplifies the code and makes
the data type more readable.
Using Typedef with Union, Bit Fields, and Structs Together
You can combine unions, bit fields, and typedef to create more readable and efficient code.
Example: Union with Bit Fields and Typedef:
#include < stdio.h>
int main() { Output:
Status status;
Flag1: 1, Flag2: 0, Value: 42
typedef union {
status.flags.flag1= 1;
W hole value: 170
struct {
status.flags.flag2 = 0;
unsigned int flag1: 1; // 1bit status.flags.value = 42;

unsigned int flag2 : 1; // 1bit

unsigned int value : 6; // 6 bits printf("Flag1: % d, Flag2: % d, Value: % d\n", status.flags.flag1, status.flags.flag2, status.flags.value);

} flags; printf("Whole value: % u\n", status.whole);

unsigned int whole; // Entire value in 8 bits (1byte)


return 0;
} Status;
}
Using Typedef with Union, Bit Fields, and Structs Together
In this example:

The typedef simplifies the definition of the union Status.

The union contains a bit field structure for flags and a single integer (whole) to hold the entire 8 bits as a
single value.
Using Typedef with Union, Bit Fields, and Structs Together
Summary of Unions, Bit Fields, and Typedef
Feature Union Bit Field Typedef
Definition Stores multiple types in the Allows precise control over the Defines a new name
same memory location number of bits used by a (alias) for an existing
Memory Shares memory for all Saves
membermemory by using a Simplifies
data type code,
Usage members, size is the largest specific number of bits especially with complex
Use Case Storing different types of Storing small values or flags Improving readability
member types
data, only one at a time efficiently and maintainability
Example union Data { int i; float f; } struct { unsigned int a:3; } typedef struct { int x; }
Usage Point;

By using unions, bit fields, and typedef, you can make your C programs more memory-efficient, readable, and easier to maintain.
comparison of typedef and #define in C language in a tabular format
Feature typedef #define
Purpose Creates alias for data types Defines macros for constant values,
expressions, or code fragments
Usage Type aliasing Macro substitution
Syntax typedef existing_type new_alias; #define macro_name replacement_text
Type Checking Ensures type safety at compile time No type checking, simple text substitution
Scoping Scoped to the block in which it is defined Global scope
Error Handling Compile-time errors for type mismatches May cause errors if used improperly
Example typedef unsigned long ulong; #define PI 3.14
Function-like Macros Not applicable Can define function-like macros
Parameter Evaluation Not applicable Function-like macros may have issues
with parameter evaluation
Use Cases Simplifying complex type definitions Defining constants, inline code
Example Usage typedef Example:
#define Example:
#include < stdio.h>
#include <stdio.h>
typedef unsigned long ulong; #define PI 3.14

int main() #define SQUARE(x) ((x) * (x))

int main()
{
{
ulong num = 1000000;
double radius = 5.0;
printf("Number: % lu\n", num); double area = PI * SQUARE(radius);

return 0; printf("Area: % .2f\n", area);

return 0;
}
}
Assignment No 3
The Flowchart
1.Explain the purpose of enumerators in programming. Provide examples of how
enumerators improve code readability and maintainability.
2.Define a structure in C and explain its components. How is it different from arrays?
3.Compare and contrast anonymous structures and named structures. W hat are
the advantages of using anonymous structures?
4.Define a union and explain how it is different from a structure.
5.W hat are bit fields in C? Explain how they can be used to optimize memory usage.
6.Discuss the role of typedef in creating user-defined types. Provide examples of
how it simplifies the use of structures and pointers.
www.paruluniversity.ac.
in
Computational Thinking for
Structured Design-2
303105151
Chapter- 5
FILE HANDLING
CONTENT
FILE Pointer
File modes
Opening a file
Writing into a file
Reading from a file
Closing a file
Some more function
Input & Output Function in C
Reading input from the user and showing it on the console
(output) are the common tasks every C program needs. C
language provides libraries (header files) that contain various
functions for input and output. In next slide, we will learn
different types of formatted and unformatted input and
output functions.
The Standard Files in C
The C language treats all the devices as files. So,
devices such as the "display" are addressed in the
same way as "files".
The following three files are automatically opened
when a program executes to provide access to the
keyboard and screen.
The Standard Files in C
Standard File File Device
Standard input stdin Keyboard

Standard output stdout Screen

Standard error stderr Your screen

To access a file, C uses a predefined FILE struct type to refer to the file for reading and writing purpose. First
understand how to read values from the screen and how to print the result on the screen.
Types of Input & Output Functions
We have the following categories of IO function in C −

Unformatted character IO functions: getchar() and putchar()

Unformatted string IO functions: gets() and puts()

Formatted IO functions: scanf() and printf()


The unformatted I/O functions read and write data as a stream of bytes
without any format, whereas formatted I/O functions use predefined formats
like "% d", "% c" or "% s" to read and write data from a stream.
Unformatted character IO functions: getchar() and putchar( )
Example 1: The following program reads a
These two functions accept a single character as input from
single key into a char variable −
the keyboard, and display a single character on the output #include < stdio.h>
terminal, respectively. int main() {
char ch;
The getchar() function it reads a single key stroke without printf("Enter a character: ");
the Enter key. ch = getchar();
puts("You entered: ");
putchar(ch);
int getchar(void) return 0;
}
There are no parameters required. The function returns an Output:
integer corresponding to the ASCII value of the character key Enter a character: W
input by the user. You entered:
W
Unformatted character IO functions: getchar() and putchar( )
Example 2: The following program shows how you can read a series of
characters till the user presses the Enter key −
#include <stdio.h>
int main() {
char ch;
char word[ 10] ;
int i = 0;
printf("Enter characters. End with pressing enter: ");
while(1) {
ch = getchar();
word[ i] = ch;
if (ch == '\n')
break;
i++;
}
printf("\nYou entered the word: % s", word); Output:
return 0; Enter characters. End with pressing enter: Hello
}
You entered the word: Hello
Unformatted character IO functions: getchar() and putchar( )
You can also use the unformatted putchar() function to print a single character. The C library
function "int putchar(int char)" writes a character (an unsigned char) specified by the argument
char to stdout.

int putchar(int c)

A single parameter to this function is the character to be written. You can also pass its ASCII
equivalent integer. This function returns the character written as an unsigned char cast to an int
or EOF on error.
Formatted String Input & Output Functions: gets(), fgets(), puts(), and fputs()
#include <stdio.h>
gets():
The char *gets(char *str) function reads a line from int main() {
stdin into the buffer pointed to by str until either a
terminating newline or EOF (End of File) is char name[ 20] ;
encountered.
printf("Enter your name: ");
gets(name);
char *gets (char *str) printf("You entered the name: % s", name);

This function has a single argument. It is the pointer return 0;


to an array of chars where the C string is stored. The }
function returns "str" on success and NULL on error Output
or when EOF occurs while no characters have been Enter your name: Virat Kohli
You entered the name: Virat Kohli
read.
Formatted String Input & Output Functions: gets(), fgets(), puts(), and fputs()
#include < stdio.h>
fgets():
In newer versions of C, gets() has been deprecated int main () {
as it is potentially a dangerous function because it char name[ 20] ;
doesnt perform bound checks and may result in
buffer overflow. printf("Enter a name: \n");
fgets(name, sizeof(name), stdin);

Instead, it is advised to use fgets() function − printf("You entered: \n");


fgets(char arr[ ] , size, stream); printf("% s", name);

fgets() can be used to accept input from any input return 0;


stream such as stdin (keyboard) or FILE (file stream). }
Output
Enter a name: Virat Kohli
You entered : Virat Kohli
Formatted String Input & Output Functions: gets(), fgets(), puts(), and fputs()
The following example shows the difference between puts() and
puts(): fputs()
#include <stdio.h>
The function "int puts (const char *str)" writes the
string 's' and a trailing newline to stdout. int main () {

char name[ 20] = "Rakesh Sharma";


int puts(const char *str) printf("With puts(): \n");
puts(name);
The str parameter is the C string to be written. If successful, it returns printf("\nWith fputs(): \n");
a non-negative value. On error, the function returns EOF. fputs(name, stdout);

We can use the printf() function with % s specifier to print a string. We return 0;
can also use the puts() function (deprecated in C11and C17 versions) }
With puts():
or the fputs() function as an alternative. Rakesh Sharma

With fputs():
Rakesh Sharma
Formatted String Input & Output Functions: gets(), fgets(), puts(), and fputs()

The scanf() function reads the input from the standard input stream stdin and scans that input according to the
format provided −

int scanf(const char *format, ...)

The printf() function writes the output to the standard output stream stdout and produces the output according
to the format provided.

int printf(const char *format, ...)

The format can be a simple constant string, but you can specify % s, % d, % c, % f, etc., to print or read strings,
integers, characters or floats respectively. There are many other formatting options available which can be used
based on the specific requirements.
Formatted String Input & Output Functions: gets(), fgets(), puts(), and fputs()
% l or % ld or % li Long
Format Specifier Type % lf Double
%c Character
% Lf Long double
%d Signed integer
% lu Unsigned int or unsigned long
% e or % E Scientific notation of floats
% lli or % lld Long long
%f Float values
% llu Unsigned long long
% g or % G Similar as % e or % E
%o Octal representation
% hi Signed integer (short)
%p Pointer
% hu Unsigned Integer (short)
%s String
%i Unsigned integer
%u Unsigned int

% x or % X Hexadecimal representation
Formatted String Input & Output Functions: gets(), fgets(), puts(), and fputs()
#include <stdio.h>

int main(){

char str[ 100] ;

printf("Enter a value: ");


gets(str);

printf("\nYou entered: ");


puts(str);

return 0;
} Output:
Enter a value: seven 7
You entered: seven 7
Unformatted character IO functions: getchar() and putchar( )
Example 3: The following example shows how you can use the putchar() function −
#include <stdio.h>
int main() {
char ch;
for(ch = 'A' ; ch <= 'Z' ; ch++) {
putchar(ch);
}

return(0);
}

Output:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
File Handling in C
File handling in C is the process of handling file operations such as
creating, opening, writing data, reading data, renaming, and deleting
using the C language functions. With the help of these functions, we can
perform file operations to store and retrieve the data in/from the file in
our program.
Need of File Handling in C
If we perform input and output operations using the C program, the data
exists as long as the program is running, when the program is terminated,
we cannot use that data again. File handling is required to work with files
stored in the external memory i.e., to store and access the information to/
from the computer's external memory. You can keep the data
permanently using file handling.
Types of file
A file represents a sequence of bytes. There are two types of files: text files
and binary files −
1. Text file − A text file contains data in the form of ASCII characters and is
generally used to store a stream of characters. Each line in a text file ends with a
new line character ("\n"), and generally has a ".txt" extension.
2. Binary file − A binary file contains data in raw bits (0 and 1). Different
application programs have different ways to represent bits and bytes and use
different file formats. The image files (.png, .jpg), the executable files
(.exe, .com), etc. are the examples of binary files.
File Pointer
In C, file handling is performed through a set of standard functions
provided by the C standard I/O library (stdio.h).
Why File Handling?

To store data permanently (unlike variables that store data temporarily in


RAM).
Useful for data persistence, reports, logs, configuration files, etc.
File Pointer

Types of Files
1. Text file(.txt): Store human-readable data.
2. Binalry file(.bin): Store data in binary format (not

human-readable, more compact and faster for


reading/writing).
File Pointer
While working with file handling, you need a file pointer to store the reference of the FILE structure
returned by the fopen() function. The file pointer is required for all file-handling operations.
The fopen() function returns a pointer of the FILE type. FILE is a predefined struct type in stdio.h and
contains attributes such as the file descriptor, size, and position, etc.

typedef struct { int fd; /* File descriptor */ unsigned char Declaring a File Pointer (FILE*)
*buf; /* Buffer */ size_t size; /* Size of the file */ size_t Below is the syntax to declare a file pointer −
pos; /* Current position in the file */ } FILE;
FILE* file_pointer;
Opening (Creating) a File
A file must be opened to perform any operation. The fopen() function is used to create a new file or open an
existing file. You need to specify the mode in which you want to open. There are various file opening modes
explained below, any one of them can be used during creating/opening a file.
The fopen() function returns a FILE pointer which will be used for other operations such as reading, writing,
and closing the files.

Syntax:

FILE *fopen(const char *filename, const char *mode);

Here, filename is the name of the file to be opened, and mode defines the file's opening mode.
File opening modes in fopen()
The file access modes by default open the file in the text or ASCII mode. If you are going to handle binary files,
then you will use the following access modes instead of the above-mentioned ones:

"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"


There are various modes in which a file can be opened. The following are the different file opening modes
File opening modes in fopen()
Mode Description
r Opens an existing text file for reading purposes.
Opens a text file for writing. If it does not exist, then a new file is created. Here your program
w
will start writing content from the beginning of the file.
Opens a text file for writing in appending mode. If it does not exist, then a new file is created.
a
Here your program will start appending content in the existing file content.
r+ Opens a text file for both reading and writing.
Opens a text file for both reading and writing. It first truncates the file to zero length if it exists,
W+
otherwise creates a file if it does not exist.
Opens a text file for both reading and writing. It creates the file if it does not exist. The reading
a+
will start from the beginning but writing can only be appended.
Example of Creating a File
In the following example, we are creating a new file. The file mode to create a new file will be "w" (write-mode).
#include < stdio.h>

int main() {
FILE * file;

// Creating a file
file = fopen("file1.txt", "w");

// Checking whether file is


// created or not
if (file == NULL) {
printf("Error in creating file");
return 1;
Output }
printf("File created.");
File created.
return 0;
}
Example of Opening a File
In the following example, we are opening an existing file. The file mode to open an existing file will be "r" (read-
only). You may also use other file opening mode options explained above.
Note: There must be a file to be opened. #include <stdio.h>

int main() {
FILE * file;

// Opening a file
file = fopen("file1.txt", "r");

// Checking whether file is


// opened or not
if (file == NULL) {
printf("Error in opening file");
return 1;
}
Output printf("File opened.");
File opened.
return 0;
}
Closing a File
Each file must be closed after performing operations on it. The fclose() function closes an opened file.

Syntax

int fclose(FILE *fp);

The fclose() function returns zero on success, or EOF if there is an error in closing the file.

The fclose() function actually flushes any data still pending in the buffer to the file, closes the file, and
releases any memory used for the file. The EOF is a constant defined in the header file stdio.h.
Example of Closing a File
#include <stdio.h>

int main() {
FILE * file;

// Opening a file
file = fopen("file1.txt", "w");

// Checking whether file is


// opened or not
if (file == NULL) {
printf("Error in opening file");
return 1;
}
printf("File opened.");

// Closing the file


Output fclose(file);
File opened. printf("\nFile closed.");
File closed. return 0;
}
Writing to a Text File
The following library functions are provided to write data in a file opened in writeable mode −
fputc() : Writes a single character to a file.
fputs(): Writes a string to a file.
fprintf(): Writes a formatted string (data) to a file.
Writing to a Text File
Writing Single Character to a File
The fputc() function is an unformatted function that writes a single character value of the argument "c" to the
output stream referenced by "fp".

int fputc(int c, FILE *fp);


Writing to a Text File
#include <stdio.h>

int main() {

FILE *fp;
char * string = “Computer Science & Engineering";
int i;
char ch;

fp = fopen("file1.txt", "w");

for (i = 0; i < strlen(string); i++) {


ch = string[ i] ;
if (ch == EOF)
break;
fputc(ch, fp); Output
}
printf ("\n");
fclose(fp); After executing the program, "file1.txt" will be created in
the current folder and the string is written to it.
return 0;
}
Writing to a Text File
Writing String to a File

The fputs() function writes the string "s" to the output stream referenced by "fp". It returns a non-negative
value on success, else EOF is returned in case of any error.

int fputs(const char *s, FILE *fp);


Writing to a Text File
#include< stdio.h>

int main() {

FILE *fp;
char *sub[ ] = {"C Programming Tutorial\n", "C++ Tutorial\n",
"Python Tutorial\n", "Java Tutorial\n"};
fp = fopen("file2.txt", "w");

for (int i = 0; i < 4; i++) { Output:


fputs(sub[ i] , fp);
} When the program is run, a file named "file2.txt" is created in the current
folder and save the following lines −
fclose(fp);
C Programming Tutorial
return 0; C++ Tutorial
} Python Tutorial
Java Tutorial
Writing to a Text File
Writing Formatted String to a File

The fprintf() function sends a formatted stream of data to the disk file represented by the FILE pointer.

int fprintf(FILE *stream, const char *format [ , argument, ...] )

Example:

In the following program, we have an array of struct type called "employee". The structure has a string, an
integer, and a float element. Using the fprintf() function, the data is written to a file.
Writing to a Text File
int main() {
#include <stdio.h> When the above program is executed, a text
FILE *fp; file is created with the name "file3.txt" that
struct employee { struct employee emp[] = { stores the employee data from the struct
{25, 65.5, "Ravi"},
int age; array.
{21, 75.5, "Roshan"},
float percent; {24, 60.5, "Reena"}
char *name; };
};
char *string;
fp = fopen("file3.txt", "w");

for (int i = 0; i < 3; i++) {


fprintf(fp, "% d % f % s\n", emp[i].age, emp[i].percent, emp[i].name);
}
fclose(fp);

return 0;
}
Reading from a Text File
The following library functions are provided to read data from a file that is opened in read mode −

fgetc(): Reads a single character from a file.


fgets(): Reads a string from a file.
fscanf(): Reads a formatted string from a file.
Reading from a Text File
Reading Single Character from a File

The fgetc() function reads a character from the input file referenced by "fp". The return value is the character
read, or in case of any error, it returns EOF.

int fgetc(FILE * fp);

The following example reads the given file in a character by character manner till it reaches the end of file.
Reading from a Text File
#include < stdio.h>

int main(){

FILE *fp ;
char ch ;
fp = fopen ("file1.txt", "r");

while(1) {
ch = fgetc (fp);
if (ch == EOF)
break;
printf ("% c", ch);
}
printf ("\n");
fclose (fp);
Output:
}
Computer Science & Engineering
Reading from a Text File
Reading String from a File
The fgets() function reads up to "n-1" characters from the input stream referenced by "fp". It copies the read string
into the buffer "buf", appending a null character to terminate the string.

Example
This following program reads each line in the given file till the end of the file is detected −
Reading from a Text File
# include <stdio.h>

int main() {

FILE *fp;
char *string;
fp = fopen ("file2.txt", "r");

while (!feof(fp)) {
fgets(string, 256, fp);
printf ("% s", string) ; Output:
} C Programming Tutorial
fclose (fp); C++ Tutorial
} Python Tutorial
Java Tutorial
Reading from a Text File
Reading Formatted String from a File

The fscanf() function in C programming language is used to read formatted input from a file.

int fscanf(FILE *stream, const char *format, ...)

Example

In the following program, we use the fscanf() function to read the formatted data in different types of
variables. Usual format specifiers are used to indicate the field types (% d, % f, % s, etc.)
Reading from a Text File
#include <stdio.h>

int main() {

FILE *fp;
char *s;
int i, a;
float p;

fp = fopen ("file3.txt", "r");

if (fp == NULL) {
puts ("Cannot open file"); return 0;
}

while (fscanf(fp, "% d % f % s", &a, &p, s) != EOF)


printf ("Name: % s Age: % d Percent: % f\n", s, a, p); Output:
fclose(fp);
Name: Ravi Age: 25 Percent: 65.500000
return 0; Name: Roshan Age: 21Percent: 75.500000
} Name: Reena Age: 24 Percent: 60.500000
Renaming a File
The rename() function is used to rename an existing file from an old file name to a new file name.

Syntax:

int rename(const char *old_filename, const char *new_filename)


Renaming a File
#include < stdio.h>

int main() {
// old and new file names
char * file_name1= "file1.txt";
char * file_name2 = "file2.txt";

// Renaming old file name to new one


if (rename(file_name1, file_name2) == 0) {
printf("File renamed successfully.\n"); Output:
} else { If there is a file (file1.txt) available, the following will be the
perror("There is an error."); output −
}

return 0; Name: Ravi Age: 25 Percent: 65.500000


} Name: Roshan Age: 21Percent: 75.500000
Name: Reena Age: 24 Percent: 60.500000
File operations in C
Common file functions
Function Description Function Description
fopen() Opens a file fread() Reads from a binary file
fclose() Closes a file
fwrite() Writes to a binary file
fprintf() Writes formatted output to a file

fscanf() Reads formatted input from a file fseek() Moves the file pointer to a specific location

fputs() Writes a string to a file rewind() Moves the file pointer to the beginning
fgets() Reads a string from a file
File opening modes in fopen()
Mode Description

“r” Open for reading.

“w” Open for writing.(create a newfile or


truncates if exits)
“a” Open a appending.

“r+” Open for reading and writing.

“w+” Open for reading and


writing(overwrite.)
“a+” Open for reading and appending.
Understanding File Access Types
Sequential Access:
Data is read/written in order (line by line, character by character).
Example: Reading a text file from start to end.
Random Access:
Jump to any part of the file using fseek(), ftell(), and rewind().
Useful for large files where reading the whole file is inefficient.
Example Programs
Example 1: Write and Read from a File (Text, Sequential Access)
// Reading from file
#include < stdio.h>
char ch;
fp = fopen("student.txt", "r"); // open in read mode
int main() {
if (fp == NULL) {
FILE *fp;
printf("File not found!\n");
return 1;
// Writing to file
}
fp = fopen("student.txt", "w"); // open in write mode
if (fp == NULL) {
printf("Reading File Content:\n");
printf("Error opening file!\n");
while ((ch = fgetc(fp)) != EOF) {
return 1;
putchar(ch);
}
}
fprintf(fp, "Name: John Doe\nAge: 21\nBranch: CSE\n");
fclose(fp);
fclose(fp); // close after writing
return 0;
}
Example Programs
Example 2: Append Data to a File

#include < stdio.h>

int main() {
FILE *fp = fopen("student.txt", "a"); // open in append mode
if (fp == NULL) {
printf("File not found!\n");
return 1;
}

fprintf(fp, "City: Vadodara\n");


fclose(fp);

printf("Data appended successfully!\n");


return 0;
}
Example Programs
Example 3: Append Data to a File

#include < stdio.h> // Move file pointer to beginning


rewind(fp);
int main() {
FILE *fp = fopen("data.txt", "w+"); // Move pointer to second number (assume fixed length per line)
fseek(fp, 10, SEEK_SET); // skip "Number: 1\n" (10 bytes)
if (fp == NULL) {
printf("Error creating file.\n"); char line[30];
return 1; fgets(line, sizeof(line), fp); // read second line
}
printf("Second line: % s", line);
// Writing numbers to file
for (int i = 1; i < = 5; i++) { fclose(fp);
fprintf(fp, "Number: % d\n", i); return 0;
} }
Points to Remember
Always check if the file is successfully opened.(if (fp == NULL))
Always close file using fclose(fp) after reading/writing.
Use fseek() and ftell() for efficient random access.
Use fprintf() and fscanf() for formatted I/O.
Suggested Exercises for Students
Write a program to store student records in a file.
Modify the above program to append new student data.
Create a program to count the number of words in a given file.
Create a program to search for a word in a file and print its line number.
Write a binary file program using fwrite() and fread() to store and retrieve
student
structures.
File Modes
Basic FILE MODES :
r - Read mode, we can open a file in “r” mode if we wish only
to read data from the file
w - Write mode, we can open a file in “w” mode if we wish
only to write data into the file
a - Append mode, we can open a file in “a” mode if we wish
only to append data into the file
OPENING A FILE
fopen(), is used open the file, if there is no file with
the specified name, NULL will be returned to FILE
*.

Syntax:
FILE * fptr;
READING FROM A FILE
#include < stdio.h>
#include < stdlib.h> fgetc(): Reads the next character from the
int main() {
FILE *fptr;
input stream stream and returns its integer
char ch; value. Returns EOF (usually -1) on end-of-
fptr = fopen("myfile.txt", "r"); file or error.
if (fptr == NULL) {
printf("Error opening file!\n");
exit(1);
}
printf("Contents of the file:\n");
while ((ch = fgetc(fptr)) != EOF) {
printf("% c", ch); // Print each character to the console
}
fclose(fptr);
return 0;
}
CLOSING A FILE
#include < stdio.h>
#include < stdlib.h> fclose(): Closes the file associated with
int main() { the stream stream, flushing any buffered
FILE *fptr;
fptr = fopen("myfile.txt", "w");
output. Returns 0 on success, or EOF on
if (fptr == NULL) { error.
perror("Error opening file");
exit(1);
}
fprintf(fptr, "This is some text.\n");
if (fclose(fptr) == EOF) {
perror("Error closing file");
exit(1);
}
printf("File closed successfully.\n");
fptr = NULL;
return 0;
}
CLOSING A FILE
rewind(): Sets the file pointer to the beginning of the file.
fwrite(): Writes a block of data.
rewind(fptr);
fwrite(buffer, sizeof(int), 10, fptr); // Writes 10 ints from
buffer
ftell(): Returns the current file pointer position.
fread(): Reads a block of data.
long position = ftell(fptr);
fread(buffer, sizeof(int), 10, fptr); // Reads 10 ints into
buffer
fseek(): Moves the file pointer.
fscanf(): Formatted input (like scanf from a file).
fscanf(fptr, "% d % s", &x, name);
fseek(fptr, 0, SEEK_SET); // Beginning of file

fseek(fptr, 10, SEEK_CUR); // 10 bytes from


current position

fseek(fptr, 0, SEEK_END); // End of file


THANK YOU
Searching and Sorting
Sunny M. Ramchandani
Assistant Professor
Computer Science and Engineering(AIML)
Outline
Selectionsort
CHAPTER-
BubbleSort 1
Insertion sort Preprocessor Directives
Linear and Binary Searching Techniques
Introduction to Searching & Sorting
W hat is Searching?
Searching refers to the process of finding a particular item (data element)
in a collection of data. This could be a number, a name, a record, or any
item stored in an array, list, or database.
Example: Looking for a student's roll number in a list.
Types:
Linear Search –simple but slower
Binary Search –faster but works only on sorted data
Introduction to Searching & Sorting
W hat is Sorting?
Sorting means arranging data in a particular order –usually ascending or
descending.
Example: Arranging student marks from highest to lowest.
Common sorting techniques include:
Bubble Sort
Selection Sort
Insertion Sort
Merge Sort
Quick Sort
Introduction to Searching & Sorting
Why Do We Learn Searching and Sorting?
1. Improves Efficiency
Searching becomes faster when data is sorted. E.g., Binary Search is much faster than Linear Search on
sorted data.
2. Used in Real-Life Applications
1. Searching in Google or databases
2. Sorting products by price on shopping websites
3. Filtering data in Excel sheets
3. Foundation for Advanced Topics
These techniques are a must-know before learning more complex algorithms like searching in graphs,
data mining, etc.
4. Used in Interviews and Competitions
Most coding interviews and competitions include problems based on searching and sorting.
W hat is Sorting?
Sorting is the process of arranging data in a particular order –either ascending (small
to large) or descending (large to small).

Example:
Given a list of numbers: [ 5, 2, 8, 1, 3]
After sorting(ascending): [ 1, 2, 3, 5, 8]
W hy is Sorting Important?
Makes data easier to search and analyze.
Improves the performance of other algorithms (like Binary Search).
Used in databases, reports, and real-world applications like e-commerce filters,
school records, etc.
Types of Sorting algorithm
1. Bubble Sort
Repeatedly compares adjacent elements and swaps them if they are in the wrong order.
Simple but slow for large datasets.
Think: Bubbles rising up in water (largest bubble moves to the end).

2. Selection Sort
Repeatedly selects the smallest (or largest) element and places it at the correct position.
Fewer swaps than bubble sort, but still O(n²) time.
Think: Finding the smallest value and fixing it one by one.

3. Insertion Sort
Builds the sorted list one item at a time by inserting elements into the correct position.
Good for small or nearly sorted datasets.
Think: How you sort playing cards in your hand.
Types of Sorting algorithm
4. Merge Sort (Divide and Conquer)
Divides the list into halves, sorts each half, then merges them.
Efficient and stable. Time complexity is always O(n log n).
Think: Split the list into smallest pieces and merge them back sorted.

5. Quick Sort (Divide and Conquer)


Selects a pivot, partitions the list around the pivot, and recursively sorts sublists.
Very fast in practice. Average time: O(n log n)
Think: Pick a middle point and arrange smaller on left, larger on right.

6. Heap Sort
Converts the array into a heap structure and repeatedly removes the root (max or min).
Good time complexity, but not stable.
Think: Binary tree logic applied for sorting.
Types of Sorting algorithm
Algorithm Time Complexity (Avg) Space Best Use Case
Bubble Sort O(n²) O(1) Simple cases, teaching
Selection Sort O(n²) O(1) Small arrays, fewer swaps needed
O(n²)
Insertion Sort O(1) Nearly sorted arrays
Merge Sort O(n log n) O(n) Linked lists, external sorting
Quick Sort O(n log n) O(log n) Fastest for large arrays (avg case)
Heap Sort O(n log n) O(1) W hen memory is limited
Selection Sort
Definition:
Selection Sort is a simple comparison-based sorting algorithm. It repeatedly finds
the minimum (or maximum) element from the unsorted part and moves it to the
sorted part.
Dry Run of the Example:
Initial array: [ 29, 10, 14, 37, 13]
Pass 1: Smallest is 10 Swap with 29 [ 10, 29, 14, 37, 13]
Pass 2: Smallest is 13 Swap with 29 [ 10, 13, 14, 37, 29]
Pass 3: Smallest is 14 Already in place [ 10, 13, 14, 37, 29]
Pass 4: Smallest is 29 Swap with 37 [ 10, 13, 14, 29, 37]
Selection Sort
#include <stdio.h> int main() {
void printArray(int arr[ ] , int
int data[ ] = {29, 10, 14, 37, 13};
void selectionSort(int arr[ ] , int n) { n) {
int i, j, minIndex, temp; int size = sizeof(data) /
int i;
sizeof(data[ 0] );
for (i = 0; i < n - 1; i++) { for (i = 0; i < n; i++) {
minIndex = i; printf("% d ", arr[ i] );
for (j = i + 1; j < n; j++) { printf("Original array: ");
}
if (arr[ j] < arr[ minIndex] ) { printArray(data, size);
minIndex = j; printf("\n");
} }
} selectionSort(data, size);
// Swap the found minimum with the first element
temp = arr[ minIndex] ; printf("Sorted array: ");
arr[ minIndex] = arr[ i] ;
arr[ i] = temp; printArray(data, size);
}
} return 0;
}
Selection Sort
Merits (Advantages):
1.Simple and easy to implement
Great for beginners and teaching the logic of sorting.
2. Fewer Swaps
Performs only one swap per pass (useful when memory writes are
costly).
3. In-place Algorithm
No need for additional memory, works on the same array.
4. Deterministic Time
The number of comparisons is fixed (even if the array is sorted).
Selection Sort
Demerits (Disadvantages):
1.Slow for large datasets
O(n²) time complexity makes it inefficient compared to Merge or Quick
Sort.
2. Not stable by default
May change the order of equal elements.
3. No early stopping
Even if the array becomes sorted early, it continues running all passes.
4. Not adaptive
Doesn't improve performance on nearly sorted arrays.
Selection Sort
W here to Use (Practical Scenarios):
W hen memory writes are expensive (because it does fewer swaps).
W hen dataset size is small.
In embedded systems where memory is tight.
For educational or demonstrative purposes.
Key Characteristics of Selection Sort
Feature Description

Type Comparison-based, In-place

Stable Not stable (Can be made stable with changes)

Time Complexity Best: O(n²), Avg: O(n²), Worst: O(n²)

Space Complexity O(1) (No extra space needed)

Number of Swaps O(n) (Fewer swaps compared to Bubble Sort)

Adaptive No (Does not take advantage of sorted data)


Bubble Sort
Definition:
Bubble Sort is a simple comparison-based sorting algorithm that repeatedly
compares and swaps adjacent elements if they are in the wrong order. The biggest
(or smallest) element "bubbles up" to its correct position in each pass.
Bubble Sort
Dry Run (Step- by- Step Execution)
Given array: [ 64, 25, 12, 22, 11]
Pass 1:
Compare 64 & 25 Swap [ 25, 64, 12, 22, 11]
Compare 64 & 12 Swap [ 25, 12, 64, 22, 11]
Compare 64 & 22 Swap [ 25, 12, 22, 64, 11]
Compare 64 & 11 Swap [ 25, 12, 22, 11, 64]
Largest number 64 is now in its correct place.

Pass 2:
Compare 25 & 12 Swap [ 12, 25, 22, 11, 64]
Compare 25 & 22 Swap [ 12, 22, 25, 11, 64]
Compare 25 & 11 Swap [ 12, 22, 11, 25, 64]
And so on...
Bubble Sort
#include < stdio.h> int main() {
void printArray(int arr[ ] , int
void bubbleSort(int arr[ ] , int n) { int data[ ] = {64, 25, 12, 22, 11};
n) {
int temp; int size = sizeof(data) /
int swapped; for (int i = 0; i < n; i++)
sizeof(data[ 0] );
for (int i = 0; i < n - 1; i++) { printf("% d ", arr[ i] );
swapped = 0; printf("\n");
printf("Original array: ");
for (int j = 0; j < n - i - 1; j++) { }
if (arr[ j] > arr[ j + 1] ) {
printArray(data, size);
// Swap
temp = arr[ j] ;
arr[ j] = arr[ j + 1] ;
bubbleSort(data, size);
arr[ j + 1] = temp;
swapped = 1;
}
printf("Sorted array: ");
} printArray(data, size);
// If no two elements were swapped in inner loop, break
if (swapped == 0) return 0;
break;
} }
}
Key Characteristics of Bubble Sort
Property Description

Algorithm type Comparison-based, in-place

Best: O(n) (with early stopping)


Time Complexity
Average/Worst: O(n²)

Space Complexity O(1) –No extra space required

Stability Stable –preserves the order of equal elements

Adaptiveness Adaptive –can stop early if sorted

Number of Swaps High (compared to Selection Sort)


Bubble Sort
Advantages (Merits)
1.Very simple to understand and implement
2. No extra space needed (in-place sorting)
3. Stable sort –equal elements maintain original order
4. Adaptive with optimization –stops early if already sorted
5. Good for small or nearly sorted datasets
Bubble Sort
Disadvantages (Demerits)
1.Inefficient for large datasets –O(n²) time complexity
2. Too many unnecessary comparisons and swaps
3. Not suitable for real-time applications
4. Slower than more advanced algorithms like Merge Sort, Quick Sort,
or Heap Sort
W hen to Use Bubble Sort
Situation Usefulness

Educational/learning purposes Excellent

Small datasets Acceptable

Real-world large datasets Not recommended

Stability required? Good choice


Insertion Sort
W hat is Insertion Sort?
Insertion Sort builds the final sorted array one element at a time, like the way we
sort playing cards in our hands.
At each step, it takes one element from the unsorted part and inserts it into the
correct position in the sorted part.
Insertion Sort
Dry Run / Step-by-Step
Given array: [ 9, 5, 1, 4, 3]
Pass 1:
Key = 5 compare with 9 shift 9 insert 5
Result: [ 5, 9, 1, 4, 3]
Pass 2:
Key = 1 compare with 9, 5 shift both insert 1
Result: [ 1, 5, 9, 4, 3]
Pass 3:
Key = 4 shift 9, 5 insert 4
Result: [ 1, 4, 5, 9, 3]
Pass 4:
Key = 3 shift 9, 5, 4 insert 3
Final Sorted Array: [ 1, 3, 4, 5, 9]
Insertion sort
#include < stdio.h> int main() {
void printArray(int arr[ ] , int
void insertionSort(int arr[ ] , int n) { int data[ ] = {9, 5, 1, 4, 3};
n) {
int key, j; int size = sizeof(data) /
for (int i = 1; i < n; i++) { for (int i = 0; i < n; i++)
key = arr[ i] ; sizeof(data[ 0] );
j = i - 1; printf("% d ", arr[ i] );
printf("\n");
// Move elements of arr[ 0..i-1] that are greater than key printf("Original array: ");
// to one position ahead }
while (j > = 0 && arr[ j] > key) {
printArray(data, size);
arr[ j + 1] = arr[ j] ;
j--;
}
insertionSort(data, size);
arr[ j + 1] = key;
}
}
printf("Sorted array: ");
printArray(data, size);

return 0;
}
Insertion Sort
Time and Space Complexity

Case Time Complexity

Best Case (already sorted) O(n)

Average Case O(n²)

Worst Case (reverse sorted) O(n²)

Space Complexity: O(1) (in-place sorting)


Stable: Yes
Adaptive: Yes
Key Characteristics Insertion Sort
Characteristic Description
Type Comparison-based, in-place sorting
Stable (does not change order of equal
Stability
elements)
Adaptive Efficient for nearly sorted data
Best Case O(n), occurs when array is already sorted
Worst Case O(n²), occurs when array is sorted in reverse
Number of swaps Fewer than Bubble Sort (in general)
Insertion Sort
Advantages (Merits)
1. Simple to understand and code
2. Efficient for small datasets
3. Efficient for nearly sorted data (adaptive)
4. In-place sort (no extra memory used)
5. Stable sort
6. Great for real-time systems where data is received over time

Disadvantages (Demerits)
1. Inefficient on large datasets
2. Time complexity is O(n²) in average and worst cases
3. Not suitable for large-scale applications
Insertion Sort
Use Cases of Insertion Sort
Sorting small datasets quickly
W hen data is nearly sorted (very efficient)
In online algorithms, where data comes in piece by
piece
Used as part of hybrid algorithms (like Timsort)
Linear Search
W hat is Linear Search?
Linear Search (also known as Sequential Search) is the simplest search
algorithm.
It checks each element of a list one by one from start to end until the
target element is found or the end is reached.
Linear Search
How Linear Search WorksSteps:
1. Start from index 0.
2. Compare each element with the target.
3. If a match is found, return the index.
4. If end of array is reached and no match, return -1.
Linear Search
#include < stdio.h> int main() {
int data[ ] = {10, 25, 35, 40, 55};
int linearSearch(int arr[ ] , int n, int target) int size = sizeof(data) / sizeof(data[ 0] );
{ int key = 40;
for (int i = 0; i < n; i++) {
if (arr[ i] == target) int result = linearSearch(data, size, key);
return i; // Return index if found
} if (result != -1)
return -1; // Not found printf("Element % d found at index % d.\n", key, result);
} else
printf("Element % d not found in the array.\n", key);

return 0;
}
Linear Search
Dry Run / Step-by-Step
Input Array:[ 10, 25, 35, 40, 55] , Target: 40
1. Compare 10 no
2. Compare 25 no
3. Compare 35 no
4. Compare 40 match at index 3
Return: 3
Linear Search
Time & Space Complexity

Case Time Complexity

Best Case O(1) (element is at beginning)

Average Case O(n)

Worst Case O(n) (element at end or not found)

Space Complexity: O(1)


No extra memory used
Linear Search
Key Characteristics of Linear Search

Feature Description

Type Sequential, comparison-based

Works on sorted? Works on both sorted & unsorted arrays

Efficiency Poor for large datasets

In-place? Yes (no extra array used)

Stability Not applicable (not a sorting method)


Linear Search
Advantages (Merits)
1. Very simple to implement and understand
2. Works on both sorted and unsorted arrays
3. No preprocessing needed
4. Good for small datasets
5. Can be used on linked lists, arrays, and other data
structures
Disadvantages (Demerits)
1. Inefficient for large datasets
2. Slow performance compared to binary search on
sorted arrays
3. Time increases linearly with input size
4. No advantage from sorted data
Linear Search
Use Cases of Linear Search
W hen working with unsorted data
W hen data size is small
In embedded systems with low memory and simple
requirements
Searching in user input lists, strings, etc.
Linear Search
Summary Table

Feature Linear Search

Data Requirement Sorted or Unsorted

Time Complexity O(n)

Space Complexity O(1)

Best Case O(1)

Worst Case O(n)

Use Case Small or simple data


Binary Search
What is Binary Search?
Binary Search is a search algorithm that finds the position of a target value within a sorted array.
It works by repeatedly dividing the search interval in half:
Compare the target with the middle element.
If equal target found.
If target < middle search the left half.
If target > middle search the right half.

Important Condition
Binary Search only works on sorted arrays (ascending or
Binary Search Example
#include < stdio.h> int main() {
int data[ ] = {10, 20, 30, 40, 50, 60};
int binarySearch(int arr[ ] , int n, int key) {
int low = 0, high = n - 1, mid; int size = sizeof(data) / sizeof(data[ 0] );
int key = 40;
while (low < = high) {
mid = low + (high - low) / 2; int result = binarySearch(data, size, key);

if (arr[ mid] == key) if (result != -1)


return mid; printf("Element % d found at index % d.\n", key,
else if (arr[ mid] < key) result);
low = mid + 1;
else
else
high = mid - 1; printf("Element % d not found in the array.\n", key);
}
return -1; // Not found return 0;
} }
Binary Search
Dry Run / Step- by- Step

Array: [ 10, 20, 30, 40, 50, 60] , key = 40


1. low = 0, high = 5, mid = 2 arr[ 2] = 30 key > 30 search right
2. low = 3, high = 5, mid = 4 arr[ 4] = 50 key < 50 search left
3. low = 3, high = 3, mid = 3 arr[ 3] = 40 Found at index 3
Binary Search
Time & Space Complexity
Case Time Complexity

Best Case O(1) (middle element is target)

Average Case O(log n)

Worst Case O(log n)


Space Complexity:
Iterative: O(1)
Recursive: O(log n) due to stack frames
Binary Search
Key Characteristics of Binary Search

Feature Description

Type Divide and Conquer

Data requirement Array must be sorted

Efficiency Very fast for large datasets

Stability Not applicable (not a sorting algo)

Recursive/Iterative Can be implemented both ways


Binary Search
Advantages (Merits)
1. Very fast compared to linear search (especially on large arrays).
2. Time complexity is logarithmic: O(log n).
3. Efficient for static, sorted datasets.
4. Can handle large datasets efficiently.
5. Works well in read-only data environments.

Disadvantages (Demerits)
1. Requires sorted data
2. Not suitable for dynamic or frequently changing data
3. More complex to implement than linear search
4. Not efficient on small datasets
Binary Search
Summary Table

Feature Binary Search

Works on Sorted data only

Time Complexity O(log n)

Space Complexity O(1) (Iterative)

Data Preprocessing Required (Sorting)

Efficiency on large data Very high


Linear Search vs Binary Search
Feature / Criteria Linear Search Binary Search

Definition Sequentially checks each element one by one Repeatedly divides the array and searches halves

Data Requirement Works on both sorted and unsorted arrays Requires sorted array

Time Complexity (Best) O(1) — element found at start O(1) — element is in the middle
Time Complexity (Average) O(n) O(log n)

Time Complexity (Worst) O(n) — element at end or not found O(log n) — element not found

Space Complexity O(1) — in-place O(1) for iterative, O(log n) for recursive

Algorithm Type Brute force Divide and conquer


Stability Not applicable Not applicable
Performance Slow on large datasets Very fast on large datasets

Implementation Complexity Very simple and easy to implement Slightly complex (requires mid, low, high logic)

Use Case Small or unsorted datasets Large and sorted datasets

Adaptability Works on arrays, lists, strings, etc. Mainly works on arrays with random access

Preprocessing Required No Yes (sorting if not already sorted)

Best Use Scenarios Real-time search, small datasets Large data lookups, search libraries, databases
Selection Sort
The selection sort is a simple comparison-based sorting algorithm that sorts a
collection by repeatedly finding the minimum (or maximum) element and placing it
in its correct position in the list.

It is very simple to implement and is preferred when you have to manually


implement the sorting algorithm for a small amount of dataset.
Algorithm Working Principle:
Start from the first element and assume it as the minimum.
Compare this element with the remaining elements in the array.
If a smaller element is found, update the minimum index.
Swap the minimum element with the first element of the unsorted part.
Move the boundary of the sorted part one step forward.
Repeat the process until the entire array is sorted.
Example
#include < stdio.h> int main() {
void selectionSort(int arr[ ] , int n) { int arr[ ] = {5, 1, 4, 2, 8};
for (int i = 0; i < n - 1; i++) { int n = sizeof(arr) / sizeof(arr[ 0] );
int min_idx = i; selectionSort(arr, n);
for (int j = i + 1; j < n; j++) { printf("Sorted array: ");
if (arr[ j] < arr[ min_idx] ) { for (int i = 0; i < n; i++) {
min_idx = j; printf("% d ", arr[ i] );
} }
} printf("\n");
// Swap if a smaller element was found return 0;
if (min_idx != i) { }
int temp = arr[ i] ;
arr[ i] = arr[ min_idx] ;
arr[ min_idx] = temp; Output :
} Sorted array : 12 4 5 8
}
}
Advantages & Disadvantages of selection sorting
Advantages :
Simple and easy to implement
Performs well on small datasets
Works well when memory space is limited

Disadvantages :
for large datasets
Not a stable sorting algorithm
Bubble Sort
Bubble Sort is a simple comparison-based sorting algorithm that repeatedly swaps
adjacent elements if they are in the wrong order.

This process continues until the array is sorted.


Algorithm Working Principle:
Start from the first element and compare it with the next.
If the first element is greater than the second, swap them.
Move to the next pair and repeat step 2.
Continue this process until the largest element is placed at the last position.
Repeat the process for the remaining unsorted elements.
The process stops when no more swaps are required.
Example
#include < stdio.h> int main() {
int arr[ ] = {5, 1, 4, 2, 8};
void bubbleSort(int arr[ ] , int n) { int n = sizeof(arr) / sizeof(arr[ 0] );
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) { bubbleSort(arr, n);
if (arr[ j] > arr[ j + 1] ) {
// Swap if the current element is greater than the next printf("Sorted array: ");
int temp = arr[ j] ; for (int i = 0; i < n; i++) {
arr[ j] = arr[ j + 1] ; printf("% d ", arr[ i] );
arr[ j + 1] = temp; }
} printf("\n");
}
} return 0;
} }

Output : 12 4 5 8
Advantages & Disadvantages of bubble sort
Advantages :
Simple and easy to understand
Stable sorting algorithm
Efficient for nearly sorted data (with optimized version)

Disadvantages :
Inefficient for large datasets
Requires many swaps, making it slower in practice
Insertion Sort
Insertion Sort is a simple sorting algorithm that builds the sorted list one element at
a time by taking each element and inserting it into its correct position.

Algorithm Working Principle:

Assume the first element is already sorted.


Pick the next element and compare it with the sorted part.
Shift elements in the sorted part to the right to create space for the new element.
Insert the new element at its correct position.
Repeat the process for all elements.
Example:
#include < stdio.h> int main() {
void insertionSort(int arr[ ] , int n) {
for (int i = 1; i < n; i++) { int arr[ ] = {5, 1, 4, 2, 8};
int key = arr[ i] ; // The current element to be int n = sizeof(arr) / sizeof(arr[ 0] );
inserted
int j = i - 1; // Index of the element to compare insertionSort(arr, n);
with key printf("Sorted array: ");

// Move elements greater than key one position for (int i = 0; i < n; i++) {
ahead printf("% d ", arr[ i] );
while (j > = 0 && arr[ j] > key) {
arr[ j + 1] = arr[ j] ; }
j = j - 1; printf("\n");
}
arr[ j + 1] = key; // Insert the key in its correct return 0; }
Linear & Binary Search
Linear Search :

Linear search is a simple searching algorithm that checks each element of the
array sequentially until a match is found or the end of the array is reached.

It is also known as sequential search.

It can be used on both sorted and unsorted data.


Example
#include < stdio.h> int main() {
int numbers[ ] = {10, 20, 30, 40, 50};
int linearSearch(int arr[ ] , int size, int target) { int result = linearSearch(numbers, 5, 30); // Search
for (int i = 0; i < size; i++) { for 30
if (arr[ i] == target) {
return i; // Found! if (result != -1) {
} printf("30 found at index % d\n", result); // Output:
} 30 found at index 2
} else {
return -1; // Not found printf("30 not found\n");
} }
return 0;
}

Output :
Linear & Binary Search (conti..)
Binary Searching :

Binary search is a much more efficient search algorithm, but it requires the data to be
sorted.

It works by repeatedly dividing the search interval in half.

If the middle element is the target, the search is complete.

If the target is less than the middle element, the search continues in the left half.
Example
#include < stdio.h> int main() {

int binarySearch(int arr[ ] , int size, int target) { int arr[ ] = {2, 5, 7, 8, 11, 12};
int low = 0, high = size - 1, mid; int target = 11;
while (low < = high) { int index = binarySearch(arr, 6, target);
mid = low + (high - low) / 2; if (index != -1) printf("Found at index: % d\n", index);
if (arr[ mid] == target) return mid; else printf("Not found\n");
if (arr[ mid] < target) low = mid + 1;
else high = mid - 1; return 0;
}
}
return -1;
} Output :
Found at index: 4
Difference between Linear and Binary Search
Linear Search Binary Search

Data Requirement: Works on both Data Requirement: Requires the data


sorted and unsorted arrays or lists. to be sorted in ascending or
descending order.
Search Mechanism: Sequentially checks Search Mechanism: Repeatedly divides
each element of the array from the the search interval in half.Compares the
beginning until the target element is target element with the middle element
Time
foundComplexity:
or the end ofInthe
thearray
worstiscase, it
reached. Time
of theComplexity:
interval. It significantly
has to examine all 'n' elements. reduces the search space with each
step, making it much faster for large
Efficiency: Less efficient for large Efficiency:
datasets. Highly efficient for large,
datasets. sorted datasets.

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy