CTSD All Chapters
CTSD All Chapters
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'
int main() {
int a = 10, b = 20, c = 30;
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] ;
}
Output
int main() {
int x = 10;
printf("Before: x = % d\n", x);
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:
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:
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 :
Syntax of malloc() in C :
ptr = (cast-type*) malloc(byte-size)
COMPUTER LANGUAGE
// 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);
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
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.
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.
#else This block executes when all #if & #elif fails
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:
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:
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)
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
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
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
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;
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.
void printStudent(struct Student student) { struct Student student1= {"Alice", 21, 90.5};
} }
Structure and Functions
Passing Structure by Reference (using Pointers): int main() {
void printStudent(struct Student* student) { struct Student student1= {"Alice", 21, 90.5};
} }
Array of Structures
An array of structures allows you to store multiple structures of the same type.
};
struct Student {
};
struct {
int x;
int y;
} point;
point.x = 10;
point.y = 20;
}; };
struct Person person1= {"John", {"Main St", "CityX", 12345}};
struct Node {
int data;
};
node1.data = 10;
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.
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;
...
};
Unions: Bit fields , Typedef
Key Features of Unions:
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
struct StructName {
...
};
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 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:
W hy Use typedef?
unsigned int value : 6; // 6 bits printf("Flag1: % d, Flag2: % d, Value: % d\n", status.flags.flag1, status.flags.flag2, status.flags.value);
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()
{
{
ulong num = 1000000;
double radius = 5.0;
printf("Number: % lu\n", num); double area = PI * SQUARE(radius);
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
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 −
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);
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 −
The printf() function writes the output to the standard output stream stdout and produces the output according
to the format provided.
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(){
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?
Types of Files
1. Text file(.txt): Store human-readable data.
2. Binalry file(.bin): Store data in binary format (not
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:
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:
int main() {
FILE * file;
// Creating a file
file = fopen("file1.txt", "w");
int main() {
FILE * file;
// Opening a file
file = fopen("file1.txt", "r");
Syntax
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");
int main() {
FILE *fp;
char * string = “Computer Science & Engineering";
int i;
char ch;
fp = fopen("file1.txt", "w");
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 main() {
FILE *fp;
char *sub[ ] = {"C Programming Tutorial\n", "C++ Tutorial\n",
"Python Tutorial\n", "Java Tutorial\n"};
fp = fopen("file2.txt", "w");
The fprintf() function sends a formatted stream of data to the disk file represented by the FILE pointer.
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");
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 −
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.
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.
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;
if (fp == NULL) {
puts ("Cannot open file"); return 0;
}
Syntax:
int main() {
// old and new file names
char * file_name1= "file1.txt";
char * file_name2 = "file2.txt";
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
int main() {
FILE *fp = fopen("student.txt", "a"); // open in append mode
if (fp == NULL) {
printf("File not found!\n");
return 1;
}
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
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.
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
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
return 0;
}
Insertion Sort
Time and Space Complexity
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
Feature Description
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);
Feature Description
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
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
Implementation Complexity Very simple and easy to implement Slightly complex (requires mid, low, high logic)
Adaptability Works on arrays, lists, strings, etc. Mainly works on arrays with random access
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.
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.
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.
// 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.
Output :
Linear & Binary Search (conti..)
Binary Searching :
Binary search is a much more efficient search algorithm, but it requires the data to be
sorted.
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