0% found this document useful (0 votes)
30 views

C Pgdca

Uploaded by

For Notsure
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)
30 views

C Pgdca

Uploaded by

For Notsure
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/ 96

kn Unäv

kn Unäv

CENTRE FOR DEVELOPMENT OF IMAGING TECHNOLOGY


(Under Government of Kerala)

TECHNOLOGY EXTENSION DIVISION


Ground Floor, TC 26/322 (3), Chittezham Lavanya, Behind SMSM Institute
Statue, Thiruvananthapuram - 695 001
Phone Number 0471- 2321360, 2322100
Website :www.tet.cdit.org
E-mail: tet@cdit.org

PROGRAMMING IN C
& DATA STRUCTURE

STUDY MATERIAL
Version I

For Private Circulation Only

1 Programming in C & Data Structure


kn Unäv

Study Material
Printed on 2023
by
CENTRE FOR DEVELOPMENT OF IMAGING TECHNOLOGY
(Under Government of Kerala)

C-DIT – Head Office


Chithranjali Hills, Thiruvallam P.O.,
Trivandrum - 695027.
Ph: 0471-2380910, 2380912
E-mail:cdit@cdit.org
Web:www.cdit.org

©
Centre for Development of Imaging Technology (C-DIT)
This edition is authorised for Private Circulation Only
All rights reserved. This publication may not be reproduced in any way.
Programming in C & Data Structure 2
kn Unäv

PREFACE

This course material has been prepared with a broad


perspective by a team of Industry and Academic experts in
tune with the latest industry requirements and trends. This
book is designed to be the clear, concise, normative reference
to C Programming and Data Structure.
The chapters are designed to help you understand
and grasp the concepts related to the subject matter. We hope
that you find this material informative and useful in your
studies. Please note that this material should not be considered
a substitute for your coursework or required reading. We
encourage you to actively engage with the material and seek
additional resources as needed. We have included various
exercises and activities to help reinforce the concepts discussed
and encourage active engagement.
We request every user of this course material to send
the feedback to us. The suggestions and opinions of the
users will serve as a guideline for future modifications and
improvements.

3 Programming in C & Data Structure


kn Unäv

Programming in C & Data Structure 4


kn Unäv

CONTENTS
SI No Subjects Page No

1 Module I - Basics of Programming 7

2. Module II - Introduction to C Programming 19

3. Module III - C Arrays and Functions 48

4. Module IV - Pointers and File Handling in C 65

5. Module V - Data Structures using C 78

5 Programming in C & Data Structure


kn Unäv

Programming in C & Data Structure 6


kn Unäv

Module I
Basics of Programming
1 Problem Solving using Computers
Problem solving is the process of identifying, analyzing, and resolving problems or obstacles
that arise in various situations. It involves defining the problem, gathering information, identifying
possible solutions, evaluating those solutions, and choosing the most effective course of action.
Effective problem solving requires critical thinking, creativity, and the ability to work collaboratively
with others. It is a skill that can be developed through practice and experience, and is essential for
success in many fields, including business, engineering, medicine, and law.
Problem solving through computers involves using computational tools and techniques to solve
problems. Programming is closely related to problem solving because programming involves designing
and implementing software solutions to solve problems. The process of programming often involves
identifying and analyzing problems, breaking them down into smaller, more manageable parts, and
then designing and implementing a solution using programming languages and tools. Programming
requires the ability to think critically and creatively, as well as the ability to communicate effectively
with computers through code. Programmers must also be able to work collaboratively with others,
including other programmers, designers, and stakeholders, in order to identify requirements, design
solutions, and implement them effectively.
1.1 General Steps invloved in Problem Solving
1. Define the problem
◦ Identify the specific problem that needs to be solved and clearly define it.
◦ Involves gathering information, data, or feedback from relevant sources.
2. Analyze the problem
◦ Break down the problem into smaller parts and analyze each part to gain a better
understanding of the problem.
◦ Use critical thinking and analytical skills to examine the problem from different angles.
3. Develop a solution
◦ Generate possible solutions to the problem by using different problem-solving techniques.
◦ Evaluate the pros and cons of each potential solution and choose solution that best
addresses the problem.
4. Implement the solution
◦ Put the chosen solution into action, using a well-planned implementation strategy.
5. Monitor and evaluate the results
◦ Track the implementation of the solution and evaluate its effectiveness.
◦ Make adjustments or modifications as necessary.
6. Document the process
◦ Keep a record of the problem-solving process, including the steps taken, the decisions
made, and the results achieved, for future reference and learning.
7 Programming in C & Data Structure
kn Unäv

1.2 Type of problems


There are mainly two types of problems. Some problems, such as finding the area of a triangle or
preparing a salary slip, can be solved in a series of straight-forward steps. These solutions are called
algorithmic solutions. But there are problems that don’t have straight-forward solutions. Buying
stock, expanding a company, etc. are examples of such problems. Their solutions require reasoning
built on knowledge and experience, and such solutions are called heuristic solutions.
1.3 Algorithm
An algorithm is a step-by-step set of instructions for solving a problem or performing a task.
Algorithms can be represented in various ways, including in natural language, flowcharts, or
pseudocode. Algorithms are not tied to any specific programming language and can be easily translated
into code in a variety of languages such as Python, Java, or C++.
1.3.a Properties of a good algorithm
1. Correctness: The algorithm should solve the problem correctly and produce the desired
output for all possible inputs.
2. Efficiency: The algorithm should be efficient, meaning that it should take the minimum amount
of time and resources to solve the problem.
3. Clarity: The algorithm should be easy to understand and follow.
4. Robustness: The algorithm should be able to handle unexpected or invalid inputs gracefully
without crashing or producing incorrect output.
5. Generality: The algorithm should be designed to work for a wide range of inputs, not just a
specific set of cases.
1.3.b Representation of an algorithm
(i) Pseudocode is a high-level description of an algorithm that uses plain English or another natural
language. It outline the basic logic of the program without being tied to any specific programming
language syntax or grammar.
Example : A simple algorithum that reads in two numbers and outputs their sum.
1. Start
2. Prompt user for first number
3. Read in first number from user, say x
4. Prompt user for second number
5. Read in second number from user, say y
6. Add the first number x and the second number y
7. Store the result in variable say sum
8. Output the value of sum
9. End
(ii) Flowchart is a graphical representation of a solution to a problem or process. Flowchart uses
standardized symbols and shapes to represent different steps or actions. It is often used to illustrate
the flow of a program or process, making it easier to understand and follow.

Programming in C & Data Structure 8


kn Unäv

Basic Flow chart Symbols

Symbol Purpose Description

Terminal (Start/ Stop) Represents the start and the end of a flowchart.

Input/Output Used for input and output operations

Used for arithmetic operations and data


Processing
manipulations.
Used for decision making between two or more
Decision
alternatives.
Link to another page or another flowchart. The
Connector same symbol on the other page indicates that the
flow continues there.

Flow line Indicates the flow of logic by connecting symbols.

Example : Flow chart to find the largest among three numbers.

9 Programming in C & Data Structure


kn Unäv

1.4 Software
Software is a collection of computer programs, data, and instructions that tell the computer how
to perform specific tasks. Software can be categorized into two main types.
• System software.
• Application software.
1.4.a System software
System software is a type of software is designed to control and manage the computer’s hardware
resources, such as the operating system, device drivers, and utility programs.
• Operating system : It manages the computer’s hardware and software resources, and provides
services and interfaces for applications to interact with the hardware. Examples of operating
systems include Linux, Microsoft Windows, macOS, and Unix.
• Device driver : Device drivers are software programs that facilitate communication between
the operating system and the hardware devices connected to the computer. They enable the
operating system to control and manage hardware components such as printers, scanners,
keyboards, and mice.
• Utility programs: They are software programs that are used to perform specific system
maintenance and management tasks, such as disk cleanup, system backup and restore, and
virus scanning. They help to ensure that the system runs smoothly and efficiently.
1.4.b Application software
Application Software is type of software that is designed to perform specific tasks or functions
such as word processing, spreadsheet analysis, database management, graphic design, video editing,
gaming, etc. for end-users. It is also known as end-user software or productivity software. Some
examples of popular application software include
• The office suite packages typically include software for word processing, spreadsheets, and
presentations. Examples include Libre Office, Microsoft Office
• Multimedia software lets users play create or record videos, audio files, and image files.
Common examples of multimedia software are VLC Player, MX Player, and Windows Media
Player.
• Web browsers are software applications used to browse the internet. The most popular web
browsers are Chrome and Firefox.
• Enterprise resource planning (ERP) is a software and a system that manages all the core
activities and other business processes of an organisation. Examples of ERP software are
Odoo, Oracle NetSuite, and SAP Business ByDesign.
• Database software is designed to create a database to store, search, manipulate, and extract
data. MySql, Postgres, and Oracle are some of the examples.
• A custom-developed application software is built solely for an organisation or an individual
user according to their business needs.
Many application software programs are also available as cloud-based services, which allow users
to access the software and their data from any device with an internet connection. Google Docs is an
example of this kind of software.
Programming in C & Data Structure 10
kn Unäv

1.5 Program Development Cycle


The Program Development Cycle is used to represent the stages and tasks required to write a
program. The general process of developing a computer program is similar to the general problem
solving strategy. The steps in develeoping a program include

1. Analyse the Problem: The step involves the identification of the desired output, determining
the inputs required to produce the desired output, and figuring out the processes required to
produce the desired output from the input.
2. Design a solution: In design phase, a detailed description of steps to solve the problem is
created. Typically, this description is known as algorithm.
3. Code the program: Once a workable solution to a problem has been developed, it must
be converted into computer program code using a programming language like C, C++, or
JavaScript. The term coding refers to this process.
4. Test the program: Testing the program ensures that the software is free of errors and that it
indeed solves the given problem. At this point, the programme is executed using various sets
of input data to determine if it is working properly.
5. Document and Maintain the program : After the program has been deployed, it will require
ongoing maintenance to ensure that it continues to function correctly. This includes fixing
bugs, adding new features, and updating the software to keep up with changes in technology.
Documentation is a way to provide additional explanation in a natural language like English,
which makes it easier for others to understand the program code or working of the program.
Normally, software provides internal and external documentation. Internal documentation
exists within the code and explains it. External documentation is provided separately from
the program in a user’s guide or maintenance manual
Consider the below given problem as an example.
A local store needs to develop a program to compute the total price of an item that is sale when
given the item’s price and quantity. The total price must include the GST (5%) as well.
• Analyse the problem : In this stage, the programmer will look for solutions to the following
queries in the following order at this stage.
◦ What is the required output?
◦ What is the necessary input?
◦ What is the process to obtain the required output from the given input ?
These three steps directly corresponds to the three main building blocks of most programs –
input/process/output.
In the above problem, the program needs to output the Total Price
The following inputs are necessary to produce the desired output

11 Programming in C & Data Structure


kn Unäv

◦ Unit Price (Price of an item)


◦ Quantity
To produce the desired output from the input, following computations are to be performed
◦ Gross Price = Unit Price * Quantity
◦ GST = Gross Price x 5%
◦ Total Cost = Gross Price + GST.
• The design phase is the most significant phase of program development. Finding the key
tasks that the program must accomplish is an excellent method for developing a solution to
a specific problem. Each of these tasks evolved into a program module during the program
design process. If necessary, these program modules may be broken down into simpler tasks
known as submodules. It is possible to carry on this division process indefinitely to determine
all the tasks required to solve the given problem. The process of breaking down a problem into
simpler and simpler subproblem is called top-down design. Identifying the tasks and subtasks
involved in a program design is called modular programming.
To solve the above problem, the following three fundamental tasks must be carried out:
◦ Input data: Read the values for unit price and quantity
◦ Process: Compute the Gross Price, GST and Total Amount
◦ Output the results: Display Quantity and Total Amount.
Refining and adding more details to the above tasks will result a good algorithm. Below is the
pseudocode needed to solve the above problem.
1. Start
/* Input */
2. Prompt user for unit price
3. Read in unit price, say in variable itemPrice
4. Prompt user for quantity
5. Read in quantity say in variable itemQuantity
/* Process */
6. Compute grossprice = itemPricex itemQuantity
7. Computegst= grossprice * 5/100
8. ComputetotalCost = grossprice + gst
/* Output */
9. Print “Total Cost of ” + itemQuantity+ “of item(s)including GST” + ”is” + totalCost
10. End
• Coding and Internal documentation: In coding phase the pseudocode design is translated
into a particular programming language such as C, C++, etc. All the programs should
include annotations that explain the purpose of the portions of code within itself. This kind
Programming in C & Data Structure 12
kn Unäv

of annotation is known as internal documentation and is made up of comments. A comment


is text inserted into the program for explanatory purposes, but ignored by the computer when
the program is run. Comments are not seen by the program’s user, they are intended solely for
reading the code itself. The C Program to solve the above problem is given below.
include <stdio.h>
int main() {
float itemPrice, itemQuantity, totalCost, gst, grossPrice;
/* Input the price and quantity of the item */
printf(“Enter the price of the item: “);
scanf(“%f”, &itemPrice);
printf(“Enter the quantity of the item: “);
scanf(“%f”, &itemQuantity);

/* Calculate the total cost of the item, including GST */


grossPrice= itemPrice *temQuantity;
gst = 0.05 * grossPrice;
totalCost = grossPrice + gst;

/*Display the total cost of the item, including GST */


printf(“Total cost of %g item(s), including GST: %.2f”, itemQuantity, totalCost);
return 0;
}
• Testing a program is an important part of the development process, as it helps to identify
and fix errors or bugs in the program. Create a set of test cases that cover different scenarios
and input values. This will help to ensure that the program works correctly under different
conditions. Run the program with the test cases that are created and compare the actual output
with the expected output. If the actual output does not match the expected output, debug the
program to identify and fix the errors or bugs.
The two fundamental types of errors that can arise in coding a program are syntax errors and
logic errors.
A syntax error is a violation of the programming language’s rules for creating valid statements.
It can be caused, for example, by a misspelt keyword or by omitting a punctuation mark.
Syntax errors are normally detected when the program is translated by the computer into
machine language. Therefore, syntax errors are often easy to find and correct.
The logic error results from failing to use the proper combination of statements to accomplish
a certain task. It may occur due to faulty analysis, faulty design, or failure to code the program
properly. The following are a few kinds of logic errors:
13 Programming in C & Data Structure
kn Unäv

◦ Use of an incorrect formula to produce a desired result.


◦ Use of an incorrect sequence of statements to carry out the algorithm.
◦ Failure to predict some input data that may lead to an illegal operation, such as divide by
zero, when the program is run.
Logic errors are usually found only by running the program with a sufficient variety of test
data. Debugging tools and techniques, such as stepping through the code line by line and
using print statements to output the values of variables at different points in the program can
be used to fix the bugs. Once fixed the errors or bugs are fixed, run the program again with the
same test cases and ensure that the output is correct.
• External documentation
◦ User Guide or on-screen help system provides information about the program for its
end users and usually prepared by a technical writer. This documentation is used by
non experts -by people who know little about the computers and often nothing about
the programming. So the manner in which the user guide is presented is very important.
A technical writer must be experienced with the computers and must be able to explain
instructions so that they are clear, concise and easily understood by consumers.
◦ Program Maintenance Manual provides information about several different topics
pertain to the software and are helpful to programming experts. The help to fix or enhance
code written by the other programming experts
1.6 Programming Languages
Programming languages are computer languages that are used to write computer programs. These
languages allow programmers to communicate instructions to a computer, telling it what operations
to perform and how to perform them.
Programming languages typically consist of a set of rules and syntax that define how instructions
are written and interpreted. Different programming languages have different levels of complexity and
are suited for different types of programming task.
1.6.a Classification of programming languages
Programming languages can be classified in various ways, depending on their features, capabilities,
and applications. Here are some common classifications of programming languages:
1. High-level vs low-level: High-level languages are designed to be easy for humans to read and
write, with syntax and structures that resemble natural language. Low-level languages, on the
other hand, are closer to machine code and are used for system-level programming.
2. Procedural vs object-oriented: Procedural languages focus on defining sequences of
instructions that execute in a specific order. Object-oriented languages, on the other hand,
focus on defining objects that contain data and methods that act on that data.
3. Interpreted vs compiled: Interpreted languages are executed directly by an interpreter, while
compiled languages are translated into machine code before being executed.
1.6.b High level vs Low level
Low-level programming languages are programming languages that are closer to the hardware
of a computer and provide more direct control over the computer’s resources. There are two types of
low-level programming languages:
Programming in C & Data Structure 14
kn Unäv

1. Machine language: Machine language is the lowest level of programming language and
consists of binary code that is directly executed by the computer’s processor. Each instruction
is represented by a sequence of 0s and 1s, and the computer executes these instructions in
sequence.
Example : 01100001 01100010 01100011 01100010 01100100
2. Assembly language: Assembly language is a low-level programming language that is slightly
easier to read and write than machine language. It consists of human-readable mnemonics that
correspond to machine language instructions. An assembler translates assembly language into
machine language.
Example :
mov eax, [num] ; move number into eax register
mov ebx, 1 ; set ebx to 1 for multiplication
cmp eax, 0 ; check if number is zero
je done ; if yes, jump to done
Low-level programming languages are used for system-level programming, such as developing
operating systems, device drivers, and firmware. They provide more direct control over the computer’s
resources, but are also more difficult to write and debug than higher-level programming languages.
A high-level programming language is a programming language that is designed to be easy for
humans to read and write, as opposed to low-level programming languages that are designed to be
executed directly by a computer. High-level programming languages are typically designed with a
focus on abstraction, so that programmers can write code that is closer to natural language and easier
to understand.
Examples of high-level programming languages include:
◦ Python: A popular scripting language that emphasizes simplicity and readability. Python
code is typically easier to read and write than code in lower-level languages, making it a
good choice for beginners.
◦ Java: A versatile language that is widely used for building enterprise-level applications,
mobile apps, and games. Java is known for its stability, portability, and robustness.
◦ C++: A powerful language that is used for developing high-performance software such as
video games, operating systems, and scientific simulations. C++ is known for its speed,
efficiency, and control over system resources.
◦ JavaScript: A language that is used primarily for developing web applications and dynamic
user interfaces. JavaScript is a popular choice for client-side programming, as it can be
executed directly in a web browser.
◦ PHP: A server-side scripting language that is used for building dynamic web applications
and content management systems. PHP is known for its ease of use and flexibility.
High-level programming languages are typically easier to learn and use than low-level programming
languages, but they may sacrifice some performance and control over system resources in the interest
of simplicity and readability.

15 Programming in C & Data Structure


kn Unäv

1.6.c Procedural vs Object-oriented


Procedure-oriented programming (POP) is a programming paradigm based on the concept of
dividing a program into small, reusable functions, called procedures or subroutines. In this approach,
a problem is broken down into smaller, more manageable parts that can be solved using specific
procedures.
In a procedure-oriented programming language, the emphasis is on procedures and functions
rather than objects or data. These procedures take inputs, manipulate them using a set of predefined
algorithms or instructions, and produce outputs.
The main features of procedure-oriented programming languages are:
◦ Emphasis on procedures and functions
◦ Focus on algorithmic solutions
◦ Use of global variables
◦ Limited code reuse
◦ Top-down approach to problem solving
Examples of procedure-oriented programming languages include: C, Pascal, COBOL, FORTRAN.
Procedure-oriented programming languages are often used for scientific and engineering
applications, as well as for system-level programming. However, they have some limitations, such as
difficulty in managing large-scale projects and limited code reuse.
Object-oriented programming (OOP) is a programming paradigm that focuses on the use of
objects and classes to organize and structure code. In OOP, data and behavior are combined into
objects, which can interact with each other to accomplish tasks.
In an object-oriented programming language, programs are composed of classes, which define the
properties and behaviors of objects, and objects, which are instances of classes. Objects can interact
with each other by sending messages or calling methods, which are procedures that are associated
with a particular class.
The main features of object-oriented programming languages are:
◦ Encapsulation: The ability to hide the details of an object’s implementation from other
objects, so that only the necessary information is exposed.
◦ Inheritance: The ability to define a new class based on an existing class, inheriting its
properties and behaviors, and adding new ones as needed.
◦ Polymorphism: The ability of objects of different classes to be used interchangeably,
allowing for more flexible and reusable code.
Examples of object-oriented programming languages include: Java, Python, C++, Ruby, Smalltalk
Object-oriented programming languages are widely used for building complex software systems,
such as web applications, graphical user interfaces, and video games, as well as for scientific
simulations and data analysis. They offer a powerful and flexible way of organizing and structuring
code, making it easier to maintain and reuse.

Programming in C & Data Structure 16


kn Unäv

1.6.d Interpreted vs Compiled


The native language of a computer is binary—ones and zeros—and all instructions and data must
be provided to it in this form. In order to be executed, programs written in high-level languages must
be converted into machine code before execution. Translators are software that is used to convert
programmes written in high-level languages to machine code. The input to the translator is called
source code, and the output of the translator is called object code. There are mainly two types of
translators—compilers and interpreters—used to convert a high-level source programme into an
object program.
An interpreter translates and executes code written in a high-level programming language directly,
line by line, without the need for prior compilation. The interpreter reads each line of code and then
executes it immediately, rather than translating the entire code into machine language ahead of time.
Examples of interpreted programming languages are Python, Perl, JavaScript, Ruby
There are several advantages to using an interpreter, including:
◦ Faster development: Interpreted languages are generally easier to develop and test because
the development cycle is shorter. Since code can be run immediately after it is written,
developers can quickly test and debug their code.
◦ Platform independence: Interpreted languages can be run on any platform that has an
interpreter installed, making them more portable than compiled languages.
◦ Flexibility: Interpreted languages allow for more dynamic and flexible programming
because code can be executed on-the-fly, making it easier to modify code and try out new
ideas.
◦ Easy to learn: Interpreted languages often have a simpler syntax and are easier to learn
than compiled languages.
◦ Interactive environment: Interpreted languages often provide an interactive environment
that allows developers to test code snippets and see the results immediately.
However, there are also some disadvantages to using an interpreter, including:
◦ Slower performance: Interpreted languages are generally slower than compiled languages
because each line of code needs to be translated and executed in real-time.
◦ Limited optimization: Since interpreters translate code on-the-fly, they have limited
optimization capabilities compared to compilers.
◦ Security risks: Because interpreters execute code directly, they are more vulnerable to
security risks such as code injection or malware attacks.
A compiler takes the source code written in a high-level language and translates it into machine
code. This machine code can be executed directly by the computer’s processor, making the resulting
program fast and efficient. Examples of pure compiled languages are C, C++, Erlang, Haskell, Rust,
and Go.
There are several advantages to using a compiler, including
◦ Faster execution: Compiled programs are faster than interpreted programs, as the code is
translated into machine code specific to the computer’s hardware, making it more efficient.

17 Programming in C & Data Structure


kn Unäv

◦ Better error checking: The compilation process involves thorough error checking, which
can catch many errors before the program is even executed.
◦ Code optimization: Compilers can perform various optimizations on the resulting machine
code to make it run more efficiently, which can result in faster and more efficient programs.
Disadvantages of compilers:
◦ Longer development time: Writing and testing code for a compiler can take longer than
for an interpreter, as the process involves additional steps such as compilation and linking.
◦ More complex: Compilers can be more complex than interpreters, as they need to perform
more operations during the compilation process.
◦ More difficult debugging: Debugging compiled code can be more difficult than debugging
interpreted code, as it can be harder to identify the source of errors.

References
1. Prelude to Programming, 6th edition, StewartVenit, Elizabeth Drake, Pearson Ed.

Programming in C & Data Structure 18


kn Unäv

Module II
Introduction to C Programming
The C is a general purpose programmign language that was created in the early 1970s by Dennis
Ritchie at Bell Labs, who was also one of the developers of the Unix operating system. It is an
outgrowth of earlier two programming languages BPCL and B. ( In 1967, Martin Richards developed
a language called BCPL (Basic Combined Programming Language) which was derived from ALGOL.
In 1970, Ken Thompson created a language using many features of BCPL and called it simply B. C
was initially developed as a system programming language to be used for writing low-level operating
system code, and it was intended to be portable and efficient.
In 1978, Brian Kernighan and Dennis Ritchie published “The C Programming Language,” which
quickly became the definitive guide to the language and helped to popularize it. C rapidly gained
popularity in the 1980s as a language for developing software for personal computers and workstations.
In the early 1990s, the ANSI C standard was created to provide a standardized definition of the
language, which helped to improve its portability and compatibility across different systems. The
C99 and C11 standards were subsequently developed to add new features to the language and address
various issues.
Today, C remains a popular language for developing system software, embedded systems, and
other performance-critical applications due to its low-level capabilities and efficiency. Its influence
can be seen in many other popular programming languages, such as C++, Java, and Python.
2.1 Structure of a C program
Every C program consists of one or more modules called functions. (A function is a block of
code that performs a specific task.) One of the functions must be called main and serves as the entry
point of the program. When a C program is executed, the main() function is the first function that is
executed by the operating system. The main() function is responsible for coordinating the execution
of the program and typically contains the core logic of the program.
Some simple C program are given below.
Examples 1:
#include <stdio.h>
int main() {
printf(“Hello, world!\n”);
return 0;
}
• In this example, the program execution begins from the main() function and it prints the
message “Hello, world!” to the console using the printf() function and returns 0 to indicate
that the program completed successfully.
• The line #include<stdio.h> is a preprocessor directive in C that tells the compiler to include
the standard input-output library in the program. This library provides functions for performing
input and output operations in C programs, such as printing text to the console and reading
input from the user.
19 Programming in C & Data Structure
kn Unäv

• Curly braces { } are also used to define the body of a function in C. All statements that belong
to a function are enclosed within curly braces. Generally, curly braces { } are used to define
a block of code that belongs together. A block of code can contain one or more statements,
which are instructions that perform a specific task or action. By enclosing a set of statements
within curly braces, programmers can group them together and treat them as a single unit.
Examples 2:
/* Program to calculate the area of a circle.
Area = π r2 where π = 3.14159*/
#include <stdio.h>
// Define the value of PI
#define PI 3.14159
int main(){
int radius;
float area;

// Prompt the user to enter the radius


printf(“Enter the radius of the circle: ”);
scanf(“%d”, &radius);

// Calculate the area of the circle


area = PI * radius * radius;

// Output the result to the console


printf(“The area of the circle is %.2f\n”, area);
return 0;
}
Output
Enter the radius of the circle: 5
The area of the circle is 78.54
• The program prompts the user to enter the radius of the circle using the printf() functions and
reads the radius from standard input,ie, keyboard, using scanf() function. The user input is
stored in the variable radius using the & operator. Next, the program calculates the area of
the circle using the formula A = π r2, where π is the value of PI and r is the value of radius.
Finally, the program outputs the result to the console using the printf() function. The %.2f
format specifier is used to round the area to two decimal places. The program returns 0 to
indicate successful execution.
Programming in C & Data Structure 20
kn Unäv

• In the above program, the statements inside /* */ and statements starting with // are called
comments. Comments provide a brief explanation or description of the code that follows. They
are used to make the code more readable and easier to understand, both for the programmer
who wrote the code and for other programmers who may need to read or modify the code
in the future. There are two types of comments in C: single-line comments and multi-line
comments. Single-line comments begin with // and continue until the end of the line, while
multi-line comments are enclosed within /* and */ and can span multiple lines.
• #define directive is used to define the value of PI as a symbolic constant. When the program
is actually compiled, the symbolic constant will automatically be replaced by its equivalent
numerical value.
Example 3
/* Program to calculate the area of a circle using a user defined function to calculate area
Area = π r2 where π = 3.14159*/
#include <stdio.h>
// Define the value of PI as a global constant
const float PI = 3.14159;
// Function declaration to calculate the area of a circle
float calculate_area(float radius);
int main(){
int radius;
float area;
// Prompt the user to enter the radius
printf(“Enter the radius of the circle:”);
scanf(“%d”, &radius);
// Call the calculate_area() function
area = calculate_area(radius);
// Output the result to the console
printf(“The area of the circle is %.2f\n”, area);
return 0;
}
// Function declaration to calculate the area of a circle
float calculate_area(int radius){
float area = PI * radius * radius;
return area;
}

21 Programming in C & Data Structure


kn Unäv

• In this program, PI is defined as a constant global value using the const keyword. The
calculate_area() function takes a radius value as input and returns the calculated area of the
circle using the formula A = πr2. The main() function prompts the user to enter the radius of the
circle, calls the calculate_area() function to calculate the area, and then outputs the result to
the console. By using a user-defined function to calculate the area of the circle, the calculation
logic is seperated in a separate function and make the code more modular and reusable.
2.1 a General structure of a C program
A typical C program mainly consists of elements

• Preprocessor Directives: These are instructions that tell the compiler how to process the
code before compilation. They typically begin with the # symbol and include commands such
as #include and #define.
• Global Declarations: These are variables and functions that are used throughout the program
and are declared at the beginning of the program, before the main function.
• Main Function: This is the heart of the program and is the starting point for the program’s
execution. It contains statements that are executed one after the other, in the order in which
they are written.
• Statements: These are the individual instructions that make up the program. They can be
variable declarations, assignments, loops, conditionals, and other basic operations.
Programming in C & Data Structure 22
kn Unäv

• Functions: These are separate blocks of code that perform a specific task and can be called
from other parts of the program. Functions can have input parameters and can return values.
• Comments: These are non-executable statements that are used to provide information about
the program and improve its readability. They are ignored by the compiler. Documentation
section is also a set of comment lines which tells the details about the program such as the
name of the program, the author and other details.
2.2 Character set
A character set is a collection of characters and symbols that can be used to write programs.
The C character set includes uppercase and lowercase letters, digits, punctuation marks, and control
codes. The special characters and control codes represented a set of escape sequences. For example,
the escape sequence ‘\n’ represents a newline character, and the escape sequence ‘\t’ represents a
horizontal tab character.
2.3 C Tokens
In C programming language, a token is the smallest individual unit of a program that is meaningful
to the compiler.

23 Programming in C & Data Structure


kn Unäv

2.4 Keywords
Keywords are reserved words in C that have standard, predefined meanings in C.The standard
keywords are given below.
auto break case char
const continue default do
double else enum extern
float for goto if
int long register return
short signed sizeof static
struct switch typedef union
unsigned void volatile while
2.5 Identifiers
Identifiers are names given to variables, functions, arrays, and other user-defined entities in a
program.
Rules for identifiers forming identifiers
◦ can consist of letters, digits, and underscores.
◦ first character must be an alphabet or underscore.
◦ can not be a keyword.
Example : s, names, y12, sum_12, _temp.
Note :Use lowercase for variable names and uppercase for symbolic constants. Local variable names
should be short and external names should be longer and more descriptive. Variable names can begin
with an underscore (_), but this should be avoided as such names, by convention, are reserved for
library implementations.
2.6 Literals
Literals are data used for representing fixed values.
• Integer constants: An integer literal can be a decimal, octal, or hexadecimal constant. A prefix
specifies the base or radix: 0x or 0X for hexadecimal, 0 for octal, and nothing for decimal.
Example :
85 /* decimal */
0213 /* octal */
0x4b /* hexadecimal */
• Real constants: A real literal has an integer part, a decimal point, a fractional part, and
an exponent part. The floating point literals can be represented either in decimal form or
exponential form.
Example :
3.14159 /* Decimal Form */
314159E-5L /* Exponential Form */
Programming in C & Data Structure 24
kn Unäv

• Character constants: Character literals are enclosed in single quotes. A character literal can
be a plain character (e.g., ‘x’), an escape sequence (e.g., ‘\t’), or a universal character (e.g., ‘\
u02C0’). There are certain characters in C that represent special meaning when preceded by a
backslash for example, newline (\n) or tab (\t).
• String literals: String literals or constants are enclosed in double quotes “ ”
Example :
“good” //string constant
“” //null string constant
“ ” //string constant of white space
“x” //string constant having a single character.
“Earth is round\n” //prints string with a newline
2.7 Data types
C is a typed language. Each variable is assigned a specific type which defines what values it can
represent, how its data is stored in memory, and what operations can be performed on it. There are
three basic types in the C language: characters, integers and floating-point numbers. The keywords
used in C to represent character type is char, integer type is int and floating point type is float and
double.
• int: Integers are whole numbers that can have both zero, positive and negative values but no
decimal values. The size of int is usually 4 bytes (32 bits). And, it can take 232 distinct states
from -2147483648 to 2147483647.
• float and double : float and double are used to hold real numbers. The size of float (single
precision float data type) is usually 4 bytes and the size of double (double precision float data
type) is 8 bytes. The float stores real numbers with precision upto 6 decimal places where as
double stores real numbers upto 15 decimal places.
• Char: Keyword char is used for declaring character type variables. The size of the character
variable is 1 byte.
• Type specifiers – long and short: To store larger or small numeric values, the type specifiers
long or short may be used.
Example :long int, long float, short int, etc
• Type modifiers – signed and unsigned: signed and unsigned are type modifiers. The data
storage of a data type can be altered by using them.
◦ signed - allows for storage of both positive and negative numbers
◦ unsigned - allows for storage of only positive numbers
Example : unsigned int age;
2.8 Variables
A variable is a named memory location that is used to store a value. A variable is declared with a
data type, which specifies the type of data that can be stored in the variable. Variable declaration does
two things:
25 Programming in C & Data Structure
kn Unäv

• It tells the compiler what the variable name is


• It specifies what type of data the variable will hold
To declare a variable in C, the syntax is as follows:
data_type variable_name;
For example, to declare an integer variable named “num”, the syntax is:
int num;
C also allows initializing a variable at the time of declaration, like:
int num = 10;
2.9 Formatted output: printf
The formatted output is a way to print data to the standard output or a file in a specific format. The
printf() function is a standard library function in C that is used for formatted output. It is defined in
the <stdio.h> header file.
For example, to print a string to the console, we can use the following code:
printf(“Hello, world!\n”);
The “\n” at the end of the string is used to insert a newline character, which moves the cursor to the
next line after printing the string.
The syntax for using the printf() function is as follows:
printf(“format string”, variable1, variable2, ...);
Here, the “format string” specifies the format of the output, and the variables are the values to be
printed. Format specifiers are special characters that begin with a percent sign (%) and indicate the
type and format of the data to be printed or read.
Some common format specifiers used in C are
• %d: used to print or scan integers in decimal format
• %f: used to print or scan floating-point numbers
• %c: used to print or scan single characters
• %lf: used to print or scan double precision values
• %s: used to print or scan strings
• %p: used to print pointers
For example, to print an integer value, the code is given below
printf(“The value of num is %d\n”, num);
Here, the “%d” is the format specifier for an integer value. The value of the variable “num” will be
printed in place of the format specifier.
Similarly, to print a floating-point number, we can use the “%f” format specifier. For example:
float num = 3.14159;
printf(“The value of num is %.2f\n”, num);
Programming in C & Data Structure 26
kn Unäv

Here, the “.2” after the “%” sign specifies that the floating-point number should be printed with
two decimal places.
2.10 Formatted output: scanf
The scanf() function is used to read formatted input in C. The syntax for using the scanf() function
is as follows:
scanf(“format string”, &variable1, &variable2, ...);
Here, the “format string” specifies the format of the input that is expected, and the “&” symbol is
used to specify the memory location of the variables where the input will be stored.
For example, to read an integer value from standard input, the format string is “%d”. The following
code snippet shows how to use the scanf() function to read an integer value from standard input:
int num;
scanf(“%d”, &num);
Formatted input also allows reading multiple values at once. For example, to read an integer and
floating point values separated by a space, the format string is “%d %f”. The following code snippet
shows how to use the scanf() function to read an integer and floating point values:
int num1;
float num2;
scanf(“%d %f”, &num1, &num2);
2.11 Constants
A constant is a value that cannot be changed during program execution. Constants can be classified
into two types:
1. Numeric Constants: These are constants that represent a number, such as integers, floating-
point numbers, or even characters.
For example:
const int MAX = 100;
const float PI = 3.14;
const char NEWLINE = ‘\n’;
2. Symbolic Constants: Symbolic constants are defined using the #define preprocessor directive.
For example:
#define MAX 100
#define PI 3.14
#define NEWLINE ‘\n’
Symbolic constants are often used to define constants that are used frequently in the program, such
as the maximum size of an array or the value of pi. They make the code easier to read and maintain,
as they provide meaningful names instead of arbitrary values.

27 Programming in C & Data Structure


kn Unäv

2.12 Operators
2.12 a Arithmetic operators
The arithmetic (or numerical) operators come in two varieties: unary and binary.
• Binary operators: Binary operators operate on two operands or values. They take two values
as input and return a single value as output. Binary operators in C are given below
Operation Operator x =10; y= 3; x=10; y= 2.5
Addition + x+y = 13 x+y = 12.5
Subtraction - x-y=7 x+y = 7.5
Multiplcation * x * y = 30 x*y = 25.0
Division / x/y=3 x/y = 4.0
Modulus % x %y = 1 Not defined
Note: The modulus operator is valid only for non-floating-point types (e.g., char, int, etc), and
x % y produces the remainder from the division x / y (e.g., 18 % 7 is equal to 4)
It is important to notice that integer division truncates any fractional part (e.g., 17/5 is equal
to 3).
• Unary operators: An operator that operates on a single operand is known as a unary operator.
◦ Unary plus and minus (+ and -): These operators are used to reverse the sign of a value.
For example, the expression -x will give the negative value of x.
◦ Increment and decrement operators (++ and --): These operators are used to increment
or decrement the value of a variable by 1. Thus, the expression x++ is equivalent to
x = x + 1. The ++ and -- may be used as prefix (++x) or postfix (x++) with different
characteristics.
For example,
double x = 3.2;
double y = ++x;
double z = x++;
In the first case, called preincrement, the value of x is increased to 4.2 and then assigned
to y, which then also equals 4.2. ie, it is equivalent to two statements x = x+1; and y = x;
In the second case, called postincrement, the value of x is first assigned to z, and
subsequently increased by 1; so, z equals 4.2 and x equals 5.2. ie, y= x; and x = x+1;
2.12 b Precedence of an operator
The precedence of an operator determines the order in which operations are evaluated in an
expression. The precedence of the arithmetic operators is as follows (operators with higher precedence
are listed first):
◦ Postfix increment and decrement: a++, a--
◦ Prefix increment and decrement: ++a, --a
Programming in C & Data Structure 28
kn Unäv

◦ Unary plus and minus: +a, -a


◦ Multiplication, division, and remainder: *, /, %
◦ Addition and subtraction: +, -
2.12 c Type casting
Type casting refers to the process of converting a value of one data type to another. The two type
of type casting are available in C are
1. Implicit type conversion: Implicit type casting is the automatic conversion of a value from
one data type to another data type by the compiler without the need for any explicit conversion
instructions in the code and it is also known as automatic type casting. In most cases, this
happens when multiple data types are present in a single expression. In such cases, type
promotion occurs, which means one data type is converted to another to avoid data loss.
In implicit type conversion the different data types are converted to the largest data type
according to the following order:
char -> short int -> int -> unsigned int -> long -> unsigned long-> long long -> float -> double
-> long double
Example :
int num = 13;
float c = 2.5;
float sum;
sum = num + c;
printf(“sum = %f\n”, sum );
Output :sum = 120.000000
The compiler converts num into “float” and adds it with c to produce a ‘float’ result.
However, it is important to note that implicit type casting can sometimes result in loss of
precision or truncation of data, especially when casting between floating-point and integer
types.
2. Explicit type conversion: Explicit type casting in C is a way of converting one data type
to another data type by explicitly telling the compiler to do so. The syntax for explicit type
casting is as follows:
(data_type) expression;
Example,
int num = 10;
float result = (float) num;
In this example, the integer value 10 is explicitly cast to a float using the cast operator. The
value is then assigned to the variable result.
Explicit type casting is useful when it is needed to convert data types that are not automatically
compatible, such as converting a floating-point value to an integer value.
29 Programming in C & Data Structure
kn Unäv

2.12 d Relational operators


The relational operators are used to compare two values or operands. The result of a relational
operator is always a Boolean value, which is either true or false. There are six relational operators in
C, which are Equal to (==), Not equal to (!=), Greater than (>), less than (<), Greater than or equal to
(>=), Less than or equal to (<=)
The syntax for using a relational operator in C is :operand1 operator operand2
Here, operator checks whether the left-hand side operand is compared to the right-hand side operand.
The result of a relational operator is either 1 (true) or 0 (false), depending on whether the condition
is satisfied or not.
Operation Operator x =10; y= 3; x=10; y= 10
Equal to == False True
Not equal to != True False
Greater than > True False
Less than < False False
Greater than or equal to >= True True
Less than or equal to <= False True
2.12 e Logical operators
Logical operators are used to combine two or more relational expressions and return a true or false
result. There are three logical operators in C:
• && (logical AND) - returns true if both the operands are true.
• || (logical OR) - returns true if either of the operands is true.
• ! (logical NOT) - returns the opposite of the operand’s value.
A B A && B A || B ! (A && B)
False False False False True
False True False True True
True False False True True
True True True True False
The precedence of the relational operator and logical operators are as follows (operators with
higher precedence are listed first):
1 (Highest) !
2 >,>= <,<=
3 == !=
4 &&
5 (Lowest) ||

Programming in C & Data Structure 30


kn Unäv

2.12 f Conditional operator


The conditional operator in C is also known as the ternary operator. It is represented by the symbol
“? :”. The conditional operator evaluates a condition and returns one of two possible values depending
on whether the condition is true or false.
The syntax of the conditional operator is: condition ? value1 : value2
Here, the condition is evaluated first. If the condition is true, then the value1 is returned, otherwise
value2 is returned.
Example:
max = (num1 > num2) ? num1 : num2;
In this statement, the condition (num1 > num2)is evaluated first. If it is true, then the value of num1
is assigned to max, otherwise the value of num2 is assigned to max.
2.12 g Assignment operator
Assignment operator ( =) in C are used to assign a value to a variable. It assigns the value of right
hand side to left hand side. For example, the statement a = b assigns the value of b to a.
There are also shorthand assignment operators in C that can be used to perform arithmetic
operations and assign the result to a variable in a single step. These shorthand assignment operators
combine an arithmetic operator and the equal sign (=) assignment operator.
Operator Statement with shorthand operator Statement with simple assignment
operator
+= a += 6 a=a+6
-= a -= 6 a=a-6
*= a *= 6 a=a*6
/= a /= 6 a=a/6
%= a %= 6 a = a %6
2.12 h Operators precedence & associativity
The precedence of operators determines which operator is executed first if there is more than one
operator in an expression.
Example :int x = 5 - 17* 6;
In C, the precedence of * is higher than - and =. Hence, 17 * 6 is evaluated first. Then the expression
involving - is evaluated as the precedence of - is higher than that of =.
Operator Associativity is used when two operators of same precedence appear in an expression.
Associativity can be either Left to Right or Right to Left. For example: ‘*’ and ‘/’ have same
precedence and their associativity is Left to Right, so the expression “100 / 10 * 10” is treated as
“(100 / 10) * 10”.
Operator Meaning of operator Associativity
() Functional call
[] Array element reference
Left to right
-> Indirect member selection
. Direct member selection

31 Programming in C & Data Structure


kn Unäv

! Logical negation
~ Bitwise(1 's) complement
+ Unary plus
- Unary minus
++ Increment
Right to left
-- Decrement
& Dereference (Address)
* Pointer reference
sizeof Returns the size of an object
(type) Typecast (conversion)
* Multiply
/ Divide Left to right
% Remainder
+ Binary plus(Addition)
Left to right
- Binary minus(subtraction)
<< Left shift
Left to right
>> Right shift
< Less than
<= Less than or equal
Left to right
> Greater than
>= Greater than or equal
== Equal to
Left to right
!= Not equal to
& Bitwise AND Left to right
^ Bitwise exclusive OR Left to right
| Bitwise OR Left to right
&& Logical AND Left to right
|| Logical OR Left to right
?: Conditional Operator Right to left
= Simple assignment
*= Assign product
/= Assign quotient
%= Assign remainder
+= Assign sum
-= Assign difference Right to left
&= Assign bitwise AND
^= Assign bitwise XOR
|= Assign bitwise OR
<<= Assign left shift
>>= Assign right shift
, Separator of expressions Left to right

Programming in C & Data Structure 32


kn Unäv

2.13 Control structures


Control structures constructs enables the programmer to control the flow of execution of the
program. There are three basic types of control structures in C:
1. Selection Structures
2. Loop Structures
3. Jump Structures
2.14 Selection structures:
These structures allow the programmers to select a block of code from a set of code blocks. The
most commonly used selection structures in C are the if-else statement and switch statement.
2.14 a if statement
if the most simple selection structure in C. It is used to determine whether a certain statement or
block of code is executed based on a condition.
Syntax :
if (condition) {
// Code to be executed if the condition is true
}
Here, condition is a Boolean expression that evaluates to either true or false.

Example :
if (number < 0) {
number = - number;
}
printf(\n The absolute value = %d”, number);
33 Programming in C & Data Structure
kn Unäv

In this example, the program then checks if the number is negative using the condition number < 0.
If the condition is true, the program executes the block of code inside the if statement, which reverse
the sign of the number by multiplying with -1. Then it prints the absloute value of the number to the
console.
If the condition is false, the program skips the block of code inside the if statement and continues
executing the rest of the program. In this case, it prints the absloute value of the number to the console.
2.14 b if – else statement
The if – else statement is an extension of simple if statement.
Syntax :
if (condition) {
// code to be executed if the condition is true
} else {
// code to be executed if the condition is false
}
If the condition is true, the code within the first set of braces will be executed. If the condition is
false, the code within the second set of braces will be executed.

Example :
/* C program to check a person is eligible to vote in an election using if else
Criteria : if a person is eligible to vote if she/he is greater than or equal to 18 years. */
Programming in C & Data Structure 34
kn Unäv

#include <stdio.h>
int main(){
int age;
printf(“Enter your age :” );
scanf(“%d”, &age);
if(age>=18) {
printf(“You are eligible to vote\n”);
}
else {
printf(“You are not eligible to vote\n”);
}
printf(“Thank you.\n”);
}
If the user enters a value greater than or equal to 18, the test expression age >= 18 is evaluated to
true. Since the condition is true, the statements in the first set of braces are executed. Hence, You are
eligible to vote is displayed on the screen and else part is skipped.
If the user enters a value less than 18, the test expression age >= 18 is evaluated to false, skip the
statements inside the if block and the statements inside the else block are executed. Hence, You are
not eligible to vote is displayed on the screen.
2.14 c if – else – if statement
This structure allows the programmer to test multiple conditions and execute different blocks of
code depending on the outcome of each test.
Syntax :
if (condition1) {
// code block to execute if condition1 is true
}
else if (condition2) {
// code block to execute if condition2 is true
}
else if (condition3) {
// code block to execute if condition3 is true
}
...
else {
// code block to execute if all previous conditions are false
}
35 Programming in C & Data Structure
kn Unäv

If the condition1 is true, the code block immediately following the condition1 will be executed. If
the condition1 is false, execution will move on to the next “else if” block, which will test its own
condition, ie, condition2. This process goes on until a condition becomes true, or if none of the
conditions are true, the code block following the final “else” keyword will be executed.
It’s important to note that only the code block following the first condition that evaluates to true
will be executed. All other code blocks in the structure will be skipped over.
Example:
/* C program to check whether the given number is positive, negative or zero using if else if
statements */
Programming in C & Data Structure 36
kn Unäv

#include <stdio.h>
int main() {
int num;
printf(“Enter a number: ”);
scanf(“%d”, &num);
if (num< 0) {
printf(“The number is negative.\n”);
}
else if (num> 0) {
printf(“The number is positive.\n”);
}
else {
printf(“The number is zero.\n”);
}
return 0;
}
The above program uses the “if else if” structure to test the value of “num” and print a message
indicating whether it’s negative, positive, or zero. If “num” is less than zero, the code block following
the first “if” statement will be executed, printing the message “The number is negative.” If “num” is
not less than zero, the program will move on to the next condition, checking whether it’s greater than
zero. If it is, the code block following the second “if” statement will be executed, printing the message
“The number is positive.” If neither of these conditions is true, the program will move on to the final
“else” statement and execute its code block, printing the message “The number is zero.”
2.14 d Nesting of if statements
When a series of decisions are involved, the program may have to use more than one if - else
statement in nested form. The nesting of if mean an if statement inside another if statement.
Syntax:
if (condition1) {
// code block to execute if condition1 is true
if (condition2) {
// code block to execute if condition1 and condition2 are true
}
}

37 Programming in C & Data Structure


kn Unäv

Example:
/* C program to input two numbers and check the numbers are positive or negative using
nested if */
#include <stdio.h>
int main() {
int num1, num2;
printf(“Enter two numbers: ”);
scanf(“%d %d”, &num1, &num2);
if (num1 > 0) {
if (num2 > 0) {
printf(“Both numbers are positive.\n”);
}
else {
printf(“The first number is positive, but the second number is not.\n”);
}
}

Programming in C & Data Structure 38


kn Unäv

else {
if (num2 > 0) {
printf(“The second number is positive, but the first number is not.\n”);
}
else {
printf(“Both numbers are non-positive.\n”);
}
}
return 0;
}
This examples uses nested “if” statements to test the values of “num1” and “num2” and print a
message based on the outcomes of those tests.
If “num1” is greater than zero, the program will move to the inner “if” statement and test whether
“num2” is also greater than zero. If both conditions are true, the program will execute the code block
inside the inner “if” statement, printing the message “Both numbers are positive.” If “num2” is not
greater than zero, the program will execute the code block inside the inner “else” statement, printing
the message “The first number is positive, but the second number is not.”
If “num1” is not greater than zero, the program will move to the outer “else” statement and test
whether “num2” is greater than zero. If it is, the program will execute the code block inside the outer
“if” statement, printing the message “The second number is positive, but the first number is not.”
If “num2” is not greater than zero, the program will execute the code block inside the outer “else”
statement, printing the message “Both numbers are non-positive.”
2.14 e switch statement
The “switch” statement provides an alternative to using “if – else – if” statements and can make
the code more concise and easier to read. The “switch” statement allows to test the value of a variable
and execute different blocks of code based on the outcome of that test.
Syntax:
switch (expression) {
case value1:
// code block to execute if expression equals value1
break;
case value2:
// code block to execute if expression equals value2
break;
...
default:
// code block to execute if expression does not match any case
39 } Programming in C & Data Structure
kn Unäv

In this structure, the “switch” keyword is followed by a set of parentheses containing an expression
to test. The expression should evaluate to an integral type, such as an integer or character. The “case”
keyword is followed by a constant value that the expression is compared against. If the expression
matches the value, the code block immediately following the case statement will be executed. If the

Programming in C & Data Structure 40


kn Unäv

expression does not match any of the case values, the code block following the “default” keyword
will be executed. The “break” statement is used to exit the switch statement once the appropriate code
block has been executed.
Example:
#include <stdio.h>
int main() {
int grade;
printf(“Enter your grade (0-100): ”);
scanf(“%d”, &grade);
switch (grade / 10) {
case 10:
case 9:
printf(“Your grade is A.\n”);
break;
case 8:
printf(“Your grade is B.\n”);
break;
case 7:
printf(“Your grade is C.\n”);
break;
case 6:
printf(“Your grade is D.\n”);
break;
default:
printf(“Your grade is F.\n”);
break;
}
return 0;
}
In this program, the user is prompted to enter a grade between 0 and 100, which is stored in the
“grade” variable. The program then uses the “switch” statement to test the value of “grade” and print
a message indicating the corresponding letter grade.
If “grade” is between 90 and 100, the program will execute the code block for the first “case”
statement, printing the message “Your grade is A.” If “grade” is between 80 and 89, the program will
execute the code block for the second “case” statement, printing the message “Your grade is B.” If
41 Programming in C & Data Structure
kn Unäv

“grade” is between 70 and 79, the program will execute the code block for the third “case” statement,
printing the message “Your grade is C.” If “grade” is between 60 and 69, the program will execute
the code block for the fourth “case” statement, printing the message “Your grade is D.” If “grade” is
outside the range of 60 to 100, the program will execute the code block for the “default” keyword,
printing the message “Your grade is F.”
2.15 Loop structures
These structures are used to repeat a block of code a certain number of times or until a certain
condition is met. for, while, and do-while are the different loop structures in C.
There are mainly two types of loops in C Programming:
1. Entry Controlled loops: In entry controlled loops the test condition is checked before entering
the main body of the loop. for Loop and while loop are entry-controlled loops.
2. Exit Controlled loops: In exit controlled loops the test condition is evaluated at the end of the
loop body. The loop body will execute at least once, irrespective of whether the condition is
true or false. do-while loop is exit controlled loop.

Programming in C & Data Structure 42


kn Unäv

2.15 a while loop


The while loop is the most straightforward looping structure.
Syntax:
while (condition) {
// code block to execute while condition is true
}
In this structure, the “while” keyword is followed by a set of parentheses containing a condition.
The condition is evaluated before each iteration of the loop, and if it is true, the code block immediately
following the parentheses will be executed. If the condition is false, the loop will exit and control will
pass to the next statement in the program.
Example:
#include <stdio.h>
int main() {
int count = 1;
printf(“Count is: \n “,);
while (count <= 10) {
printf(“%d\n”, count);
count++;
}
return 0;
}
In this program, a variable “count” is initialized to 1. The “while” loop checks whether “count”
is less than or equal to 10, and if it is true, it prints the value of “count” and increments it by 1. This
process continues until “count” is equal to 10, at which point the loop exits and the program continues
with the next statement.
1.6.e for loop
The “for” loop is another entry-controlled loop that provides a more concise loop control structure.
Syntax:
for (initialization; condition; increment/decrement) {
// code block to execute while condition is true
}
In this structure, the “for” keyword is followed by a set of parentheses containing three statements
separated by semicolons. The first statement is the initialization statement, which initializes a variable
or sets a value before the loop starts. The second statement is the condition statement, which is
evaluated before each iteration of the loop. If the condition is true, the code block inside the loop will
be executed. The third statement is the increment or decrement statement, which is executed after
43 Programming in C & Data Structure
kn Unäv

each iteration of the loop.


Example:
#include <stdio.h>
int main() {
int i;
for (i = 1; i<= 10; i++) {
printf(“The value of i is %d\n”, i);
}
return 0;
}
In this program, a variable “i” is initialized to 1. The “for” loop checks whether “i” is less than or
equal to 10, and if it is true, it prints the value of “i” and increments it by 1. This process continues
until “i” is equal to 11, at which point the loop exits and the program continues with the next statement.
2.15 c do – while loop
In “do-while” loop the condition is checked at the end of the loop, rather than at the beginning.
This means that the loop body is executed at least once, even if the condition is initially false.

Programming in C & Data Structure 44


kn Unäv

Syntax:
do {
// code block to execute
} while (condition);
In this structure, the “do” keyword is followed by a block of code inside curly braces. After the
block of code, the “while” keyword is followed by a condition in parentheses and a semicolon. The
loop will continue to execute as long as the condition is true.

Example:
#include <stdio.h>
int main() {
int i = 1;
do {
printf(“The value of i is %d\n”, i);
i++;
} while (i<= 10);
return 0;
}
In this program, a variable “i” is initialized to 1. The “do-while” loop executes the code block
inside the curly braces, which prints the value of “i” and increments it by 1. Then, the loop checks
whether “i” is less than or equal to10. If the condition is true, the loop repeats, and if it is false, the
loop exits.
2.16 Jump structures:
These structures are used to transfer control from one part of the program to another. The most
commonly used jump structures in C are the break and continue statements.
2.16 a break statement
The “break” statement is a control flow statement that is used to
terminate the execution of a loop or switch statement. When a “break”
statement is encountered in a loop or switch statement, the program
immediately exits the loop or switch statement and continues with the
next statement after the loop or switch. The “break” statement is useful
when you want to exit a loop or switch statement prematurely, based
on a specific condition.
Example:
#include <stdio.h>
int main() {

45 Programming in C & Data Structure


kn Unäv

int i;
for (i = 1; i<= 10; i++) {
if (i == 5) {
break;
}
printf(“The value of i is %d\n”, i);
}
return 0;
}
In this program, a variable “i” is initialized to 0. The “for” loop executes 10 times, and for each
iteration, it prints the value of “i”. However, inside the loop, there is an “if” statement that checks
whether “i” is equal to 5. If the condition is true, the “break” statement is executed, which immediately
terminates the loop and continues with the next statement after the loop.
2.16 b continue statement
The “continue” statement is a control flow statement that is used to skip the current iteration of a
loop and continue with the next iteration. When a “continue” statement is encountered in a loop, the
program immediately skips the rest of the code in the loop for the current iteration and proceeds with
the next iteration.

Example:
#include <stdio.h>
int main() {
int i;
for (i = 1; i<= 10; i++) {
if (i == 5) {
continue;
}
Programming in C & Data Structure 46
kn Unäv

printf(“The value of i is %d\n”, i);


}
return 0;
}
In this program, a variable “i” is initialized to 1. The “for” loop executes 10 times, and for each
iteration, it prints the value of “i”. However, inside the loop, there is an “if” statement that checks
whether “i” is equal to 5. If the condition is true, the “continue” statement is executed, which skips the
rest of the code in the loop for the current iteration and proceeds with the next iteration.

References
1. Programming with C, Byron S Gottfried, Schaum’s Outlines
2. Programming in ANSI C, McGraw Hill, E Balagurusamy
3.

47 Programming in C & Data Structure


kn Unäv

Module III
C Arrays and Functions
3.1 Arrays
An array is a collection of similar data types that are stored in contiguous memory locations.
Arrays permits to store multiple values in a single variable.
Syntax of declaring an array variable;
data_type array_name[array_size];
where
• data_type is the data type of the elements in the array (e.g. int, float, char)
• array_name is the name given to the array
• array_size is the number of elements to store.
Example : To declare an array of integers
int my_array[5];
Accessing array elements: Each element of an array has an index number. The index starts at 0

for the first element and goes up to array_size-1 for the last element. For example, index number of
my_array, in the above example, is from 0 to 4.
The index number is used to access the elements of the array. For example, to access the third
element of the my_array array is
int x = my_array[2];
Assigning values Array elements: The values of arrays elements can be assigned at the time of
declaration or later in the program using index notation.
Example:
int my_array[3] = {1, 2, 3}; // initialize array elements with values 1, 2, and 3
or
int my_array[] = {1, 2, 3}; /* declares an array of size 3 initialize array elements with values 1, 2,
and 3 */
my_array[1] = 4; // change the value of the second element to 4
Input and Output of Array Elements: The following examples illustrate the input and output of
array elements
scanf(“%d”, &my_array[2]); // take input and store it in the 3rd element
scanf(“%d”, &my_array[i]); // take input and store it in the i+1th element
Programming in C & Data Structure 48
kn Unäv

printf(“%d”, my_array[0]); // print the first element of the array


printf(“%d”, my_array[2]); // print the third element of the array
printf(“%d”, my_array[i-1]); // print ith element of the array
The following program illustrate the various array operations
#include <stdio.h>
int main() {
int numbers[5] = {4, 2, 7, 1, 9}; // Declare an array of integers with a size of 5
// Print the contents of the array
printf(“\nNumbers: “);
for (int i = 0; i< 5; i++) {
printf(“%d “, numbers[i]);
}
// Accessing array elements
int x = numbers[2]; // get the value at index 2
numbers[1] = 8; // set the value at index 1 to 8
printf(“\nUpdated numbers: “); // Print the updated contents of the array
for (int i = 0; i< 5; i++) {
printf(“%d “, numbers[i]);
}
return 0;
}
3.2 Multidimenstional Arrays
A multidimensional array is an array with more than one dimension. It is also known as an array
of arrays, where each element in the array is itself an array.
The general syntax of a multidimensional array declaration in C is as follows:
type array_name[size1][size2]...[sizeN];
Here, type is the data type of the elements in the array, array_name is the name of the array, and
size1, size2, ..., sizeN are the sizes of the dimensions.
Example :
int myArray[3][4][2];
3.2.a Two Dimensional Arrays
In a two-dimensional array, each element is identified by two indices: a row index and a column
index. The first index specifies the row, and the second index specifies the column. The indices start
from 0, so the first row is row 0, and the first column is column 0.

49 Programming in C & Data Structure


kn Unäv

The general syntax of a multidimensional array declaration in C is as follows:


type array_name[size1][size2];
Example:
int myArray[3][4];

Accessing array elements: To access an element in a multidimensional array, use the row and column
indices.
For example, to access the element in the second row and third column of myArray, we can use the
following syntax:
int x = myArray[1][2];
Assigning values Array elements: An example to initialise an array at the declaration is given below.
Nested braces are used to initialise the array elements.
int myArray[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
To change the value of element in the second row and third colum is given below.
myArray[1][2] = 10;
Input and Output of Two Dimensional Array Elements: Input and output of two-dimensional
arrays are done using nested loops to iterate over the rows and columns of the array.
Example:
//input the elements of a two dimensional array
for (int i = 0; i< 3; i++) {
for (int j = 0; j < 4; j++) {
scanf(“%d”, &myArray[i][j]);
}
}
// output the elements of the array in matrix form

Programming in C & Data Structure 50


kn Unäv

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


for (int j = 0; j <4; j++) {
printf(“%d “, myArray[i][j]);
}
printf(“\n”);
}
3.3 Functions
A function in C is a self-contained block of code that performs a specific task. It is designed to take
one or more input parameters, process them, and return a value or perform an action. Functions in C
can be used to solve complex problems by breaking them down into smaller, more manageable pieces.
Functions are an important tool for organizing code and improving its readability and maintainability.
A function in C has the following components:
1. Function Definition: This is the actual code that implements the function. It contains the
statements that perform the intended operation.
The basic syntax of a function definition:
return_type function_name(parameter1, parameter2, ..., parameterN) {
// function body
return return_value;
}
Here, return_type is the data type of the value returned by the function, function_name is the
name of the function, and parameter1, parameter2, ..., parameterN are the input parameters of the
function. The function body contains the code that performs the specific task, and the return statement
is used to return the result of the function.
Example:
A simple function in C that takes two integers as input and returns their sum:
int sum(int a, int b) {
int result = a + b;
return result;
}
2. Function Declaration: Function declaration in C is the process of providing information about
a function to the compiler before it is used in a program. This tells the compiler about the name,
return type, and parameters of the function.
The basic syntax of a function definition
return_type function_name(parameter1, parameter2, ..., parameterN);
Example:
int sum(int , int ) ;

51 Programming in C & Data Structure


kn Unäv

The function definition is same as the first line of function definition or function heading.
3. Function Call: This is where the function is invoked with the necessary arguments. function_
name(argument1, argument2, ..., argumentN)
Example:
int s = sum( 10, 7 ) ;
Note : A parameter/formal parameter is a variable that is declared in a function’s definition and
used to represent a value that the function expects to receive. An argument/actual parameter, on the
other hand, is a value that is passed to a function when it is called.
3.3.a The working of a function
An illustration of the working of a function is given below.

3.3.b Parameter passing methods


In C, there are two ways to pass parameters to a function – pass by value and pass by reference.
1. Pass by value: In this parameter passing mechanism, the value of the argument is copied
and passed to the function. The parameter and the argument are two separate variables with
their own memory locations. Any changes made to the parameter within the function are not
reflected outside the function. This is the default way of passing parameters in C.

Programming in C & Data Structure 52


kn Unäv

Example:
#include <stdio.h>
void swap(int , int );
int main() {
int x = 5, y = 10;
swap(x, y);
printf(“x = %d, y = %d\n”, x, y);
return 0;
}
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
In this example, the swap function takes two integer parameters a and b, which are passed by
value. Within the function, a temporary variable temp is used to swap the values of a and b. However,
since the variables are passed by value, the values of x and y are not changed outside the function.
Therefore, the output of the program is x = 5, y = 10.
The memory representation while executing the program is shown below. The address of the
variables are different in main function and swap function. ie, the memory address of variable a inside
the swap function is different from the address of the variable x in the main function. Similarly the
memory address of variable b inside the swap function is different from the address of the variable y
in the main function. So any changes in the variables inside swap function will not be reflected in the
main function.
Memory: (Before function call)
Address Variable Value
--------------------------------------
0x100 x 10
0x104 y 20
After calling swap(&x, &y);
Memory before returning to main function:
Address Variable Value
--------------------------------------
0x200 a 20
0x204 b 10

53 Programming in C & Data Structure


kn Unäv

0x210 temp 10
Memory after swap function call:
Address Variable Value
--------------------------------------
0x100 x 10
0x104 y 20

2. Pass by reference: In this method, the address of the argument is passed to the parameter of
the function. The parameter is a pointer to the argument’s memory location, so any changes
made to the parameter inside the function affect the value of the argument outside the function.
Example:
#include <stdio.h>
void swap(int *, int *);
int main() {
int x = 5, y = 10;
swap(&x, &y);
printf(“x = %d, y = %d\n”, x, y);
return 0;
}
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
In this example, the swap function takes two integer pointers a and b, which are passed by reference.
Within the function, the values of the variables are swapped using pointers. Since the addresses of the
variables are passed by reference, the values of x and y are changed outside the function. Therefore,
the output of the program is x = 10, y = 5.
The memory representation while executing the program is shown below. The address of the
variables are same in both functions. ie, the memory address of variable a inside the swap function is
same as the address of the variable x in the main function. Similarly the memory address of variable
b inside the swap function is same as the address of the variable y in the main function. The variables
x and a are one and the same, even though they are referred by different names. Similarly y and b. So
any changes in variables a and b will be reflected in the variables x and y.

Programming in C & Data Structure 54


kn Unäv

Memory: (Before function call)


Address Variable Value
--------------------------------------
0x100 x 10
0x104 y 20
After calling swap(&x, &y);

Memory before returning to main function:


Address Variable Value
--------------------------------------
0x100 a 20
0x104 b 10
0x110 temp 10
Memory after swap function call:
Address Variable Value
--------------------------------------
0x100 x 20
0x104 y 10
Passing parameters by reference can be more efficient than passing parameters by value because
it avoids creating a copy of the variable. However, it can also lead to unintended consequences if not
used carefully.
3.3.c Recursive Functions
A recursive function is a function that calls itself. Recursive functions typically have a base case
and a recursive case. The base case is the condition that stops the recursion. It is the simplest case that
can be solved without calling the function again. The recursive case is the condition that continues the
recursion. It breaks the problem down into smaller subproblems and calls the function again.
Consider the example to find the factorial of number. The factorial of a nonnegative integer is
defined as follows:
0! = 1 (Eq. 1)
n! = n x ( n-1 )! if ( n> 0 ) (Eq. 2)
The definition of the factorial given in Eq. 1 and Eq. 2 are called a recursive definition. Equation 1 is
called the base case (that is, the case for which the solution is obtained directly); Equation 2 is called
the general case.
#include <stdio.h>
int factorial(int n);

55 Programming in C & Data Structure


kn Unäv

int main() {
int n = 4;
int result = factorial(n);
printf(“Factorial of %d is %d\n”, n, result);
return 0;
}
int factorial(int n) {
if (n == 0 ) {
return 1;
} else {
return n * factorial(n-1);

Programming in C & Data Structure 56


kn Unäv

}
}
In this example, the factorial function takes an integer parameter n. If n is 0, the base case is
reached and the function returns 1. Otherwise, the recursive case is executed, which calls the factorial
function again with n-1 as the parameter. This process continues until the base case is reached.
From the above example, every recursive definition has
− Every recursive definition must have one (or more) base cases.
− The general case must eventually be reduced to a base case.
− The base case stops the recursion.
Recursive functions can be used to solve a wide range of problems, including searching, sorting,
and traversing data structures. However, recursive functions can have performance issues if not
implemented correctly, as they can consume a lot of memory and cause a stack overflow. Therefore,
it is important to carefully design recursive functions and ensure that they have a base case that will
eventually be reached.
3.3.d Passing Arrays to Functions
While passing arrays to the argument, only the name of the array is passed as an argument (i.e,
starting address of memory area is passed as argument). No need to specify the subscript operator []
along with the array name. In formal parameter, subscript operator [] is used along with array name.
Example:
/* Program to pass an array containing age of a person to a function. This function will return
average age and display the average age in main function. */
#include <stdio.h>
float average(float a[]);
int main() {
float avg, c[]={23.4, 55, 22.6, 3, 40.5, 18};
avg=average(c); /* Only name of array is passed as argument. */
printf(“Average age=%.2f”,avg);
return 0;
}
float average(float a[]){
int i;
float avg, sum=0.0;
for(i=0;i<6;++i){
sum+=a[i];
}
avg = (sum/6);
57 Programming in C & Data Structure
kn Unäv

return avg;
}
3.4 Storage Class
Every variable in C programming has two properties: data type and storage class.
Data type refers to the type of information represented by a variable, e.g. interger, character,
floating point number, etc.
Storage class determines the following attributes of a variable
━ Scope : defines where the variable is accessable in the program.
━ Default definition value : a random value or zero.
━ Lifetime : how long the variable stays in existence.
━ Location of storage : whether in RAM or register.
There are four different storage class specifications in C
Storage class keyword
automatic auto
external extern
static static
register register
• Automatic Variables : The variables declared inside a block (function) are automatic or
local variables. ( A block is basically the code between an opening brace and a closing brace.
So a function body is a block.). Any variable declared within a block or function is interpreted
as automatic variable unless a different storage class specified in the declaration.
A keyword auto is used to define an auto storage class, but it is optional.
e.g. : auto int max; // Explicit declaration
int min; // By default auto
− Scope : within block/function
− Default definition value : random(garbage) values by default.
− Lifetime : during the exection of function / block
− Location of storage : RAM.
Example:
#include <stdio.h>
void foo() {
int x = 5; // automatic storage class
printf(“%d\n”, x);
}
Programming in C & Data Structure 58
kn Unäv

int main() {
foo();
return 0;
}
In this example, the variable x has automatic storage class because it is a local variable inside
the function foo. The variable is created when the function foo is called and destroyed when
the function exits.
• External Variables : The variables that are declared outside of all functions are known as
external or global variables. Their scope extends from the point of definition to the reminder
of the program, often an entire program.
− Scope : global/ entire file
− Default definition value : 0.
− Lifetime : during the exection of program.
− Location of storage : RAM.
Since global variables retain their values, their values can be modified or accessed in different
functions. Thus these variables provide a convenient mechanism for transferring values
between functions.
The extern keyword is used to declare a global variable, but it is optional since the these
variables are identified by their location of definition within the program
Example:
#include <stdio.h>
extern int x; // external storage class
void foo() {
printf(“%d\n”, x);
}
int main() {
x = 5;
foo();
return 0;
}
In this example, the variable x is declared with external storage class outside of any function.
The variable is defined in the main function and initialized to 5. The variable can be accessed
by the function foo because it has external storage class.
• Static Variables : The static variables are limited the function in which they are defined, but
retains their values throughout the program.
− Scope : within the function in which they are defind
59 Programming in C & Data Structure
kn Unäv

− Default definition value : 0.


− Lifetime : during the exection of program.
− Location of storage : RAM.
The static keyword is used to declare a static variable.
e.g. : static int max;
Example:
#include <stdio.h>
void foo() {
static int x = 0; // static storage class
x++;
printf(“%d\t”, x);
}
int main() {
foo();
foo();
foo();
return 0;
}
Output
1 2 3
In this example, the variable x has static storage class because it is declared as static inside
the function foo. The variable is initialized only once, at the time of the first call to the function. The
value of x is retained between calls to the function because the variable has static storage class.
Register Variable : The variables of register storage are initialized inside a register of the CPU.
Register variables come in handy if you want to access a variable frequently in the program; it cuts
down the time required in memory access and results in faster access of the variable stored in the
register. Initializing variables with register storage is just a suggestion to the compiler. It depends
on various parameters such as code optimization techniques of compiler or availability of registers
decide whether to allocate register or not. If the register is not used the variable is stored in the main
memory as in auto variable.
− Scope : within block/function
− Default definition value : random(garbage) values by default.
− Lifetime : during the exection of function / block
− Location of storage : Register.
e.g. register int x;

Programming in C & Data Structure 60


kn Unäv

Multifile Programs : C programs may be composed of multiple files. In multi file programs rules
associated with the use of storage classses are different.
− Functions : Within a multifile program, a function may be either static or external. An
external function will be recognised throughout the entire program, whereas a static
function will be recognised only within the file in which it is defined. Storage class
specification is placed at the beginning of the function definition.
Storage-class data-type name (type_1 arg_1, type_2 arg_2, ...., type_narg_n)
However if no storage class specifiction is not mentioned, then it is assumed as external
storage class .
− Variables : In variable declaration memory allocation does not happen whereas in
definition memory gets allocated to the variable. A declaration is just a reference for the
compiler that a variable or function is somewhere in the program or in another file to get
our program successfully compiled. Whereas in definition the compiler allocate memory
as per variable data type and it gets initialized to some default value as per the storage
class if it is not explicitly initialized by the programmer.
In a multifile program, the external variable can be defined in one file and accessed
in another. In order to access an external variable in another file, the variable must be
declared within that file and declaration must begin with storage class specifier extern.
Initial values can’t be included in external variable declarations.
3.5 Strings
A string is a sequence of characters. Strings in C are represented as arrays of characters, with the
last element of the array being the null character(\0).
An example of how to declare and initialize a string:
char string_name[] = “Hello, world!”;

This declares a character array named string_name and initializes it with the string “Hello world!”.
The null character is automatically added to the end of the string. The size of the array is automatically
determined by the compiler based on the length of the string plus one for the null character.
A sring can also be initialised as follows,
char array_name[] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘ ‘, ‘ W’,’ o’,’ r’,’’l’,’ d’,\0’};
3.5.a String functions in C
C provides several standard library functions for working with strings, including:
• strlen: returns the length of a string.
• strcpy: copies one string to another.
• strcat: concatenates two strings.
• strcmp: compares two strings.
61 Programming in C & Data Structure
kn Unäv

Example of how to use these functions:


#include <stdio.h>
#include <string.h>
int main() {
char str1[] = “hello”;
char str2[] = “world”;
char buffer[50];
printf(“Length of str1: %d\n”, strlen(str1));
printf(“Length of str2: %d\n”, strlen(str2));
strcpy(buffer, str1);
printf(“str1 copied into buffer: %s\n”, buffer);
strcat(buffer, “ “);
strcat(buffer, str2);
printf(“Buffer after concatenation: %s\n”, buffer);
if (strcmp(str1, str2) == 0) {
printf(“Strings are equal.\n”);
} else {
printf(“Strings are not equal.\n”);
}
return 0;
}
Two strings str1 and str2 are declared and initialized with the values “hello” and “world”
respectively in this example. The strlen function is used to determine the length of each string, and
the results are printed. Next, the strcpy function is used to copy the contents of str1 into a buffer, and
the resulting buffer is printed using printf. The strcat function is then used to concatenate the string
“ ” and str2 onto the end of the buffer, modifying the original string. The resulting buffer is printed.
Finally, the strcmp function is used to compare str1 and str2. If they are equal, a message is printed
saying so. Otherwise, a message is printed saying they are not equal.
Output:
Length of str1: 5
Length of str2: 5
str1 copied into buffer: hello
Buffer after concatenation: hello world
Strings are not equal.

Programming in C & Data Structure 62


kn Unäv

3.6 String manipulation without using string functions


A program to check if a given string is a palindrome without using string functions:
#include <stdio.h>
int isPalindrome(char str[]) {
int i, j;
int len = 0;
// Find the length of the string
for (i = 0; str[i] != ‘\0’; i++) {
len++;
}
// Check if the string is a palindrome
for (i = 0, j = len - 1; i<= j; i++, j--) {
if (str[i] != str[j]) {
return 0;
}
}
return 1;
}
int main() {
char str[100];
// Read the string from the user
printf(“Enter a string: “);
scanf(“%s”, str);
// Check if the string is a palindrome
if (isPalindrome(str)) {
printf(“%s is a palindrome\n”, str);
} else {
printf(“%s is not a palindrome\n”, str);
}
return 0;
}
Output:
Enter a string: malayalam
malayalam is a palindrome
In this program, we define a function called isPalindrome that takes a character array (string) as a
parameter. The function first finds the length of the string by looping through it until it finds the null
character indicating the end of the string. It then loops through the string from both ends, comparing
the characters at each end. If any two characters are not equal, the function immediately returns 0 to
indicate that the string is not a palindrome. If the function completes the loop without finding any
unequal characters, it returns 1 to indicate that the string is a palindrome.
63 Programming in C & Data Structure
kn Unäv

In the main function, a character array str is declared to hold the user’s input. The user is prompted
to enter a string and the string is read using the scanf function. Then, the isPalindrome function is
called with the input string passed as an argument. If the function returns 1, a message is printed
indicating that the string is a palindrome. Otherwise, a message is printed indicating that the string is
not a palindrome.
A program to find the occurenance of a given character in a string.
#include <stdio.h>
int countOccurrences(char *str, char ch);
int main() {
char str[] = “Programming in C and Data Structure”;
char ch = ‘a’;
int count = countOccurrences(str, ch);
printf(“The character ‘%c’ occurs %d times in the string.\n”, ch, count);
return 0;
}
int countOccurrences(char *str, char ch) {
int count = 0;
while (*str != ‘\0’) {
if (*str == ch) {
count++;
}
str++;
}
return count;
}
Output:
The character ‘a’ occurs 4 times in the string.
In this program, a string variable named str and a character variable named ch are declared. The
countOccurrences function is called passing str and ch as arguments.
The countOccurrences function accepts a pointer to a character array named str and a character
named ch as arguments. It initializes a count variable to 0 and loops through each character in the
string using a while loop. If the current character in the string matches the character ch, the count
variable is incremented. Finally, the function returns the count variable.
In the main function, the return value of the countOccurrences function is stored in an integer
variable named count.
References
1. Programming with C, Byron S Gottfried, Schaum’s Outlines
2. Programming in ANSI C, McGraw Hill, E Balagurusamy
Programming in C & Data Structure 64
kn Unäv

Module IV
Pointers and File
4
handling in C
4.1 Pointers
A pointer is a variable that stores the memory address of another variable. Pointers provide a
way to indirectly access and manipulate memory locations, and are commonly used in C to achieve
various programming tasks such as dynamic memory allocation, passing arguments by reference to
functions, and creating complex data structures.
4.1.a Declaration of a pointer variable
To declare a pointer variable in C, the asterisk symbol (*) is used before the variable name.
Syntax:
datatype *variable_name;
For example, the following code declares a pointer variable p that points to an integer:
int *p;
4.1.b Assigning value to a pointer variable
To assign a value to a pointer variable, the ampersand symbol (&) is used to obtain the memory
address of another variable. ‘&’ is called address of operator. For example, the following code assigns
the memory address of the integer variable x to the pointer variable p:
int x = 10;
p = &x;
4.1.c Accessing the value of a pointer variable
To access the value of the variable that a pointer points to, the asterisk (*) symbol is used again. `*`
is called indirection operator. For example, the following code prints the value of the integer variable
that p points to:
printf(“%d”, *p);
Example:
#include <stdio.h>
int main() {
int num = 10;
int *ptr = &num;
printf(“Value of num: %d\n”, num);
printf(“Address of num: %p\n”, &num);
printf(“Value of ptr: %p\n”, ptr);
printf(“Value pointed by ptr: %d\n”, *ptr);
*ptr = 20;

65 Programming in C & Data Structure


kn Unäv

printf(“New value of num: %d\n”, num);


return 0;
}
Output:
Value of num: 10
Address of num: 0x7fffa2c6d32c
Value of ptr: 0x7fffa2c6d32c
Value pointed by ptr: 10
New value of num: 20
The program begins by declaring an integer variable named “num” and initializing it with a value
of 10. A pointer variable “ptr” is then declared and initialized with the address of “num” using the
“&” operator.
The values of “num”, the address of “num”, the value of “ptr”, and the value pointed to by “ptr”
using the “*” operator are printed.
The value 20 is then assigned to the memory location pointed to by “ptr” using the “*” operator.
Since “ptr” points to the same memory location as “num”, this also changes the value of “num”.
Finally, the new value of “num” is printed to confirm that it has been updated.

4.1.d Advantages and Disadvantages of Pointers


Advantages
1. Dynamic memory allocation: Pointers allow for dynamic memory allocation, which means
memory can be allocated or freed during runtime.
2. Direct memory access: Pointers provide direct access to memory locations, which can be
useful in low-level programming tasks such as working with hardware.
3. Efficient data structures: Pointers can be used to create efficient data structures such as
linked lists, trees, and graphs.
4. Function arguments: Pointers can be used as function arguments to pass large data structures
and arrays by reference, avoiding the overhead of copying large amounts of data.
Disadvantages
1. Memory leaks: Pointers can cause memory leaks if not properly handled, leading to inefficient
use of memory and possible program crashes.
2. Segmentation faults: Improper use of pointers can lead to segmentation faults, which occur
when a program attempts to access memory it is not allowed to access.
Programming in C & Data Structure 66
kn Unäv

3. Hard to debug: Pointer-related bugs can be hard to track down and fix, especially in large
programs with complex data structures.
4. Null pointers: Using null pointers, which point to no memory location, can cause program
crashes and undefined behavior if not properly checked.
4.2 Arithmetic operations on pointers
Pointer arithmetic involves performing arithmetic operations on pointers to manipulate their
values. Here are some examples:
Adding/Subtracting an integer to a pointer: Adding or subtracting an integer value to a pointer
to move it to a new memory location. The integer value is multiplied by the size of the data type the
pointer is pointing to.
ie, Next Location = Current Location ± i * size_of(data type) where i is value added/subtracted.
Example:
#include<stdio.h>
int main(){
int no = 10;
int *ptr;
ptr = &no;
printf(“Current address no = %p \n”,&no);
printf(“Current address ptr = %p \n”,ptr);
ptr++;
printf(“Address after increment = %p \n”,ptr);
ptr--;
printf(“Address after decrement = %p \n”,ptr);
ptr = ptr + 3;
printf(“Address after Adding 3 = %p \n”,ptr);
ptr = ptr - 3;
printf(“Address after Subtracting 3 = %p \n”,ptr);
return 0;
}
Output:
Current address no = 0x7ffcc6d664fc
Current address ptr = 0x7ffcc6d664fc
Address after increment = 0x7ffcc6d66500
Address after decrement = 0x7ffcc6d664fc

67 Programming in C & Data Structure


kn Unäv

Address after Adding 3 = 0x7ffcc6d66508


Address after Subtracting 3 = 0x7ffcc6d664fc
In the above example, the size of the integer datatype is 4 bytes. When the ptr is incremented by
1, the address is incrementeb by 4 which is the size of integer datatype. This is same for the other
operations in the program.
4.3 Pointers and Arrays
In C, pointers and arrays are closely related concepts. An array is implemented as a pointer to the
first element of the array. This means that pointer arithmetic can be used to access elements of an
array.
Consider the following example:
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr;
for (int i = 0; i< 5; i++) {
printf(“arr[%d] = %d\n”, i, *(ptr + i));
}
return 0;
}
Output:
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5
In this example the array arr is initialised with values from 1 to 5. The starting address of the array
is assigned to ptr. Now ptr can be used traverse the array. Incrementing the ptr by one moves the next
location in the array, So ptr +1 is same as &a[1] and *(ptr+1) same as a[1].
4.4 Structures
A structure is a user-defined data type that groups together related data items of different types
under a single name. It allows to create complex data types that can store different types of data in a
structured manner.
4.4.a Declaration of a structure variable
A structure is declared using the struct keyword, followed by the structure name and a pair of curly
braces that enclose the members of the structure. Each member has a name and a data type, separated
by a semicolon.
Programming in C & Data Structure 68
kn Unäv

Syntax:
struct structName {
dataType1 member1;
dataType2 member2;
// more members...
};
Here, structName is the name of the structure, and member1, member2, and so on are the names of
the members of the structure. The data types of the members can be any valid C data type, including
other structures, pointers, and arrays.
An example of a structure that represents a person’s information is given below.
struct Person {
char name[20];
int age;
float height;
};
4.4.b Defining a Structure variable
A structure variable can be defined by using the keyword struct followed by tag name followed by
structure variables
Syntax:
struct structName variableName;
Example:
struct Person p1, p2;
Now, p1 and p2 are variables of type Person
4.4.c Accessing Structure elements
Structure elements are accessed by using . (dot) operator.
Syntax:
variableName.memberName;
An example showing the method of accessing structure elements is given below.
strcpy(p1.name, “John”);
p1.age = 25;
p1.height = 5.8;
printf(“Name: %s\n”, p1.name);
printf(“Age: %d\n”, p1.age);
printf(“Height: %.1f\n”, p1.height);
69 Programming in C & Data Structure
kn Unäv

4.5 Structure and Pointers


Structures and pointers can be used together in C to create more complex data structures and
manipulate them efficiently.
4.5.a Declaration of a Pointer to Structure
A pointer to a structure is declared just like a pointer to any other data type, using the * operator.
Syntax:
struct structName *variableName;
Example:
struct Person {
char name[20];
int age;
float height;
};
struct Person *ptrPerson;
4.5.b Accessing strcture elements
To access the members of a structure through a pointer, the arrow operator (->) is used.
Example:
struct Person myPerson = {“Alice”, 25, 1.70};
struct Person *ptrPerson = &myPerson;
int age = ptrPerson->age;
Here, we declare a struct person variable myPerson and initialize its members with values. We then
declare a pointer to struct person ptrPerson and initialize it to the address of myPerson using the &
operator.
To access the age member of myPerson through the pointer ptrPerson, we use the arrow operator
->. This is equivalent to (*ptrPerson).age, but using the arrow operator is more concise.
Similarly, we can assign values to the members of a structure through a pointer using the arrow
operator.
For example:
ptrPerson->age = 26;
This assigns the value 26 to the age member of the struct person variable pointed to by ptrPerson.
Using pointers with structures can be especially useful when dealing with arrays of structures, as
it allows us to manipulate the data more efficiently.
4.6 Structure and Arrays
An array of structure is simply an array in which each element is of the structure data type. This
allows us to store multiple instances of the same structure in an array.
Programming in C & Data Structure 70
kn Unäv

Syntax:
struct structName variableName[size];
Example :
struct Person people[3];
The following program illustrates the working of array of structure
#include <stdio.h>
struct Person {
char name[20];
int age;
float height;
};
int main() {
struct Person people[3] = {
{“Alice”, 25, 1.65},
{“Bob”, 30, 1.80},
{“Charlie”, 35, 1.75}
};
for (int i = 0; i< 3; i++) {
printf(“Person %d: %s, %d years old, %.2f meters tall\n”,
i+1, people[i].name, people[i].age, people[i].height);
}
return 0;
}
Output:
Person 1: Alice, 25 years old, 1.65 meters tall
Person 2: Bob, 30 years old, 1.80 meters tall
Person 3: Charlie, 35 years old, 1.75 meters tall
4.7 union
A union is a user-defined data type that allows you to store different data types in the same memory
location. A union is similar to a structure, but with a few key differences.
When you declare a union, you define a set of member variables, each with its own data type.
However, all of the members of a union share the same memory location. This means that a union
variable can hold only one of its members at a time.

71 Programming in C & Data Structure


kn Unäv

Syntax:
union union_name {
member_type member_name1;
member_type member_name2;
...
member_typemember_nameN;
};
An example of a union that can store either an integer or a float is given below
union Number {
int i;
float f;
};
int main() {
union Number n;
n.i = 10;
printf(“n.i = %d\n”, n.i);
n.f = 3.14;
printf(“n.f = %f\n”, n.f);
printf(“n.i = %d\n”, n.i);
return 0;
}
In this example, we define a union called Number that can hold either an integer or a float. We
declare a variable of type Number called n and set its integer member to 10. We then print out the
value of n.i, which is 10.
Next, we set the float member of n to 3.14 and print out its value. We then print out the value of n.i
again, and we see that it has been overwritten with the binary representation of 3.14. This illustrates
the fact that all members of a union share the same memory location.
4.8 Files in C
A file is a collection of related data stored on a permanent storage device, such as a hard disk or
flash drive. The data in a file can be read and written by a program, allowing the program to access
and manipulate the information.
4.8.a Classification of files
Files can be classified in different ways. Some of the common classification are given below.

Programming in C & Data Structure 72


kn Unäv

1. Text files and Binary files


Text files are human-readable and are composed of ASCII characters, and can be edited using
a text editor such as Notepad or Sublime Text. They are typically used to store configuration
files, logs, and other types of data that do not require binary representation.
Binary files, on the other hand, are not human-readable and are composed of a sequence of
bytes that can represent any type of data, including images, audio, and video files. They can
be manipulated using specialized software, such as a compiler or an image editor.
2. Sequential files and Random files
A sequential file is a file that contains a sequence of records, each with the same length
and format. The records are stored one after the other, and they can only be accessed in the
order they were written. This means that to access a specific record in a sequential file, all
the preceding records must be read first. Sequential files are commonly used for storing large
amounts of data that will be processed in a specific order, such as log files.
On the other hand, a random file is a file that contains records of varying length and format,
and they can be accessed in any order. This means that a specific record can be accessed
directly, without the need to read all the preceding records. Random files are commonly used
for storing small amounts of data that will be accessed frequently, such as configuration files
or user preferences.
3. Formatted files and Unformatted files
Formatted files are text files where as unformatted files are binary files. Unformatted files
are typically used when storing complex data structures, such as arrays of structures or objects,
that cannot be easily represented in a text format. Formatted files are used for storing simple
data types, such as integers, floating-point numbers, and strings, in a human-readable form.
4.8.b The basic steps in working with a file
1. Declare a file pointer variable of type FILE that will be used to reference the file.
2. Open the file using the fopen() function, which returns a pointer to the opened file. This
function takes two arguments: the name of the file and the mode in which it will be opened
(read, write, append, etc.).
3. Check if the file was opened successfully by checking if the returned file pointer is not NULL.
4. Read from or write to the file using the appropriate functions such as fscanf(), fgets(), fputc(),
fprintf(), etc.
5. Close the file using the fclose() function when finished working with it. This will release the
file and ensure that any changes made to it are saved.

73 Programming in C & Data Structure


kn Unäv

4.8.c Different file opening modes


Mode Description
"r" Open for reading (file must exist)
"w" Open for writing (file need not exist)
"a" Open for appending (file need not exist)
"r+" Open for reading and writing, starting at beginning of file (file must exist)
"w+" Open for reading and writing, truncating file to zero length (file need not exist)
"a+" Open for reading and writing, appending to file (file need not exist)

In addition, each mode can be modified with the following characters to indicate the type of file
being opened:
Mode Modifier Description
"b" Open binary file
"t" Open text file

For example, “rb” would indicate opening a binary file for reading, while “wt+” would indicate
opening a text file for reading and writing, truncating the file to zero length if it already exists.
Example:
The following program illustrates the basic file processing in C
#include <stdio.h>
int main() {
FILE *fp;
char filename[] = “example.txt”;
char buffer[100];
// open file for writing
fp = fopen(filename, “w”);
// write some data to the file
fprintf(fp, “This is some text\n”);
fprintf(fp, “And here is some more\n”);
// close the file
fclose(fp);
// open file for reading
fp = fopen(filename, “r”);

Programming in C & Data Structure 74


kn Unäv

// read data from the file


while (fgets(buffer, 100, fp) != NULL) {
printf(“%s”, buffer);
}
// close the file
fclose(fp);
return 0;
}
This program creates a file named “example.txt”, writes some text to it, then reads the text back
and prints it to the console. The fopen() function is used to open the file, and the fprintf() function is
used to write data to the file. The while loop to read each line of the file using the fgets() function.
The fgets() function reads up to 100 characters from the file and stores them in the buffer array. The
contents ot buffer is displayed in the console using printf. The while loop continues until the end of
the file is reached (indicated by the fgets() function returning NULL). The function fclose() is used
to close the file.
4.8.d The basic steps in processing an unformatted file
1. Define a file pointer variable using the FILE data type.
2. Open the file using the fopen() function and assign the returned file pointer to the file pointer
variable.
3. Use the fseek() function to move the file pointer to a specific record in the file.
4. Use the fread() function to read data from the file at the current file pointer position.
5. Use the fwrite() function to write data to the file at the current file pointer position.
6. Use the fclose() function to close the file.
Example:
The following program illustrates the basic unformatted file processing in C
#include <stdio.h>
struct student {
char name[50];
int rollno;
float marks;
};
int main() {
struct student s;
FILE *fp;
fp = fopen(“students.dat”, “rb+”);
75 Programming in C & Data Structure
kn Unäv

// move the file pointer to the 3rd record


fseek(fp, 2 * sizeof(s), SEEK_SET);
// read data from the 3rd record
fread(&s, sizeof(s), 1, fp);
printf(“Name: %s\n”, s.name);
printf(“Roll No: %d\n”, s.rollno);
printf(“Marks: %.2f\n”, s.marks);
// write data to the 3rd record
strcpy(s.name, “John Doe”);
s.rollno = 101;
s.marks = 85.50;
fseek(fp, 2 * sizeof(s), SEEK_SET);
fwrite(&s, sizeof(s), 1, fp);
fclose(fp);
return 0;
}
In this example, This program has a structure named “student.dat” that represents a record in the
file. The file is opened in “rb+” mode to read and write binary data to and from the file. fseek() is used
to move the file pointer to the 3rd record or the record at index 2. The data from that record is read
into the s structure using fread(). The data is printed to confirm that the correct record has been read.
New data is written to the 3rd record using fwrite(). Finally, the file is closed using fclose().
4.9 Preprocessors
Preprocessors in C are directives that are processed before the compilation of the code begins.
They are used to include header files, define constants, and perform other tasks before the actual
compilation begins. Preprocessor directives begin with `#`
Some of the commonly used preprocessor directives in C are:
1. #include: This directive is used to include a header file in the program. Header files contain
declarations for functions and variables that are defined in other files. For example, to include
the standard input/output header file in a program, we use the following directive:
#include <stdio.h>
2. #define: This directive is used to define a constant or a macro. For example, to define a constant
named PI with a value of 3.14159, we use the following directive:
#define PI 3.14159
3. #ifdef and #ifndef: These are used for conditional compilation in a program. For example,
#ifndef PI
#define PI 3.14159
#endif
Programming in C & Data Structure 76
kn Unäv

4.10 Macros
A macro is a fragment of code that is given a name and can be used like a function. Macros are
defined using the #define preprocessor directive, followed by the macro name and the replacement
text.
An example of a simple macro that defines the constant value of pi:
#define PI 3.14159
With this macro, any occurrence of the identifier PI in the code will be replaced by the value
3.14159 at compile time. For example, the following code snippet:
double area = PI * r * r;
gets transformed into:
double area = 3.14159 * r * r;
Macros can also take arguments, which allows them to be used for more complex tasks. Here is an
example of a macro that calculates the square of a number:
#define SQUARE(x) ((x) * (x))
When the preprocessor encounters code that calls the SQUARE macro, it replaces it with the
corresponding code, substituting the argument for the parameter x. For example, the following code
snippet:
int x = 5;
int y = SQUARE(x);
gets transformed into:
int x = 5;
int y = ((x) * (x));
before the code is compiled.

References
1. Programming with C, Byron S Gottfried, Schaum’s Outlines
2. Programming in ANSI C, McGraw Hill, E Balagurusamy

77 Programming in C & Data Structure


kn Unäv

Module V
Data Structures using C
5
A data structure is a way of organizing and storing data in a computer program so that it can be
accessed and manipulated efficiently. It provides a standard way to represent, store and manipulate
complex data types.
There are several types of data structures in computer science including arrays, linked lists, stacks,
queues, trees, graphs, and hash tables. Each data structure has its own advantages and disadvantages
and is suited for different types of problems.

5.1 Classification of data structures


5.1.a Primitive Data Structures vs Non-primitive Data Structures:
1. Primitive Data Structures: These are basic data types provided by the programming language
such as integer, float, character, and double. These data types are used to represent simple data
values.
2. Non-primitive Data Structures: These data structures are derived from the primitive data
types and are used to represent more complex data values. Non-primitive data structures are
further classified into two types:
◦ Linear Data Structures: In this type of data structure, the elements are arranged in a
sequential manner, and each element is connected to its previous and next elements.
Examples of linear data structures include arrays, stacks, queues, and linked lists.
◦ Non-Linear Data Structures: In this type of data structure, the elements are not arranged
in a sequential manner. Instead, each element is connected to multiple other elements in a
specific pattern. Examples of non-linear data structures include trees and graphs.

Programming in C & Data Structure 78


kn Unäv

5.1.b Homogeneous and Heterogeneous data structures


Homogeneous and heterogeneous data structures refer to the type of data that a structure can hold.
A homogeneous data structure can only hold data of the same type. For example, an array of
integers is a homogeneous data structure because it can only hold integers. All the elements of the
array must have the same data type.
On the other hand, a heterogeneous data structure can hold data of different types. A common
example of a heterogeneous data structure is a struct in C. A struct can hold different types of data,
such as integers, floating-point numbers, and characters.
5.1.c Static vs Dynamic data structures
Static and dynamic data structures refer to the way in which memory is allocated for the structure
during program execution.
A static data structure has a fixed size that is determined at compile time. Memory for a static
data structure is allocated before the program starts running and remains constant throughout the
program’s execution. Examples of static data structures include arrays and structs in C
In contrast, a dynamic data structure can change size during program execution. Memory for a
dynamic data structure is allocated during runtime, and its size can be changed as needed. Examples
of dynamic data structures include linked lists, stacks, and heaps.
5.2 Searching
Searching is the process of finding a particular element or value from a given collection of data or
a set of records. In computer science, searching is an essential operation performed on various data
structures like arrays, linked lists, trees, and graphs to retrieve specific data. The goal of searching
is to find the location or index of the desired element within the data structure, or to determine if the
element is present or not.
The two main searching algorithms are
1. Linear Search: In linear search, the list of elements is traversed sequentially until the desired
element is found.
7. Binary Search: In binary search, the list of elements is divided into two halves repeatedly
until the desired element is found. This algorithm is only applicable for sorted arrays.
5.2.a Linear Search
Linear search algorithm is the simplest search algorithm. It goes through each element one by one
and checks if it is equal to the search key value. If the element matches the search key value, then the
search terminates. If the element does not match the search key value, then the search continues on
to the next element. Linear search algorithm is inefficient because it must check each element in the
array against the desired value. However, it is easy to implement and is often used when the search
space is small.
The program to implement linear search is given below.
#include <stdio.h>
int main() {

79 Programming in C & Data Structure


kn Unäv

int arr[10] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};


int n = 10, search_key, found = 0, i;
printf(“Enter the element to search: ”);
scanf(“%d”, &search_key);
for(i = 0; i< n; i++) {
if(arr[i] == search_key) {
found = 1;
break;
}
}
if(found == 1)
printf(“Element found at index %d\n”, i);
else
printf(“Element not found in the array\n”);
return 0;
}
In the above program the integer array arr with 10 elements and initialize it with some values. The
variable found is used to determine if the search key element is found in the array or not. Initially, the
variable found is set to 0 (false) indicating that the key element is not found in the array. The linear
search algorithm then sequentially scans each element of the array and compares it with the key
element. If the key element is found, the value of the found variable is set to 1 (true) and the search
is terminated. If the entire array is scanned and the key element is not found, the value of the found
variable remains 0.
The found variable is used later in the program to print a message indicating whether the key
element was found or not. If the found variable is 1, it means that the key element was found and the
program prints a message indicating the index at which it was found. If the found variable is still 0
after the entire array is scanned, it means that the key element was not found and the program prints
a message indicating that.
5.2.b Binary Search
Binary search is a search algorithm that works on sorted arrays. It works by repeatedly dividing the
search interval in half. The algorithm starts by comparing the target value to the middle element of
the sorted array. If the target value is equal to the middle element, the search is complete. If the target
value is less than the middle element, then the algorithm searches the left half of the array. If the target
value is greater than the middle element, then the algorithm searches the right half of the array. This
process continues until the target value is found or the search interval is empty.
Working of binary search
Consider the following sorted array.

Programming in C & Data Structure 80


kn Unäv

int arr[] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};


We want to search for the value 9 in this array using binary search.
2. We start by initializing the lower bound and upper bound of the search interval:
int low = 0, high = 9;
3. We then calculate the middle index of the search interval:
int mid = (low + high) / 2; // mid is 4
4. We compare the target value (9) with the middle element of the array (arr[4] is 9):
if (arr[mid] == 9) {
// search is complete, 9 is found at index 4
5. Since the target value is equal to the middle element, the search is complete. If the target value
were not found, we would repeat steps 2-4 on the left or right half of the search interval until the
target value is found or the search interval is empty.
Program to implement binary search is given below
#include <stdio.h>
int main(){
int arr[10] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
int key, found = 0;
int mid, low = 0, high = 9;
printf(“Enter the element to search: ”);
scanf(“%d”, &key);
while (low <= high) {
mid = (low + high) / 2;
if (arr[mid] == key) {
found = 1;
break;
}
else if (arr[mid] <key) {
low = mid + 1;
}
else {
high = mid - 1;
}
}

81 Programming in C & Data Structure


kn Unäv

if (found == 1) {
printf(“%d is found at index %d.\n”, key, mid);
}
else {
printf(“%d is not found in the array.\n”, key);
}
return 0;
}
5.3 Sorting
Sorting algorithms are algorithms that arrange elements in a certain order, usually in ascending
or descending order. There are various sorting algorithms available, each with its own strengths and
weaknesses. Here are some commonly used sorting algorithms:
1. Bubble Sort: This algorithm compares adjacent elements and swaps them if they are in the
wrong order. The algorithm repeats this process until no more swaps are required.
2. Selection Sort: This algorithm selects the smallest element and places it at the beginning of
the array. It then selects the next smallest element and places it in the second position, and so
on, until all elements are sorted.
3. Insertion Sort: This algorithm starts with the second element and compares it with the first
element. If it is in the wrong order, it is swapped with the first element. The algorithm then
proceeds to the third element and repeats the process until all elements are sorted.
4. Merge Sort: This algorithm uses the concept of divide and conquer. It divides the array into
two halves, sorts each half separately, and then merges the sorted halves.
5. Quick Sort: This algorithm also uses the concept of divide and conquer. It selects a pivot
element and partitions the array around the pivot, with all elements smaller than the pivot
to the left and all elements larger than the pivot to the right. It then sorts the left and right
partitions separately.
6. Heap Sort: This algorithm sorts the array by first creating a heap from the elements, and then
repeatedly extracting the maximum element from the heap and placing it at the end of the
array.
5.3.a Insertion sort
Insertion sort is a simple sorting algorithm that works by iteratively building up a sorted list. It
works by sorting one element at a time, starting from the beginning of the list.
The basic idea behind insertion sort is to take each element from the list, and insert it into its
correct position in the sorted list. To do this, compare the current element with the elements already
in the sorted list, and insert it in the correct position by shifting the larger elements to the right.
The step-by-step process for insertion sort:
1. Start with the second element in the list, and assume that the first element is already sorted.

Programming in C & Data Structure 82


kn Unäv

2. Compare the second element with the first element. If the second element is smaller, swap
them.
3. Move on to the third element, and insert it in the correct position in the sorted list by comparing
it with the elements already in the sorted list and shifting the larger elements to the right.
Repeat this process for all the remaining elements in the list.
The pseudocode for insertion sort is given below.(A is the array and length(A) is the length of the
array.)
for i = 1 to length(A) - 1
key = A[i]
j=i-1
while j >= 0 and A[j] > key
A[j+1] = A[j]
j=j-1
end while
A[j+1] = key
end for
An example of insertion sort algorithm in action is given below.
Consider an example: [5, 3, 4, 2, 1]
1. Start with the second element (i.e., index 1) and compare it with the first element (i.e., index
0). If the second element is smaller, swap it with the first element.
◦ Array after first pass: [3, 5, 4, 2, 1]
2. Move to the third element (i.e., index 2) and compare it with the elements before it (i.e., index
1 and 0). If the third element is smaller than any of the previous elements, shift those elements
to the right and insert the third element in its correct position.
◦ Array after second pass: [3, 4, 5, 2, 1]
3. Move to the fourth element (i.e., index 3) and compare it with the elements before it (i.e., index
2, 1, and 0). If the fourth element is smaller than any of the previous elements, shift those
elements to the right and insert the fourth element in its correct position.
◦ Array after third pass: [2, 3, 4, 5, 1]
4. Move to the fifth element (i.e., index 4) and compare it with the elements before it (i.e., index
3, 2, 1, and 0). If the fifth element is smaller than any of the previous elements, shift those
elements to the right and insert the fifth element in its correct position.
◦ Array after fourth pass: [1, 2, 3, 4, 5]
Therefore, the sorted array using insertion sort is [1, 2, 3, 4, 5].
5.3.b Merge sort
Merge sort is a divide-and-conquer algorithm that involves dividing an array into two halves,

83 Programming in C & Data Structure


kn Unäv

sorting each half, and then merging the two halves back together. The basic idea behind merge sort is
to repeatedly merge two sorted subarrays into a larger, sorted subarray until the entire array is sorted.
The merge sort algorithm can be described in the following steps:
1. Divide the unsorted array into two halves (left and right) at the middle index.
2. Recursively sort the left half using the merge sort algorithm.
3. Recursively sort the right half using the merge sort algorithm.
4. Merge the two sorted subarrays back together to form the final sorted array.
The merge step works by comparing the first elements of the two subarrays and selecting the
smaller one to add to the merged array. This process is repeated until one of the subarrays is exhausted,
at which point the remaining elements of the other subarray are added to the merged array.
The pseudocode for the merge sort algorithm is given below.
mergeSort(arr[], l, r)
if l < r
1. Find the middle point to divide the array into two halves:
middle = (l + r) / 2
2. Call mergeSort for first half:
mergeSort(arr, l, middle)
3. Call mergeSort for second half:
mergeSort(arr, middle+1, r)
4. Merge the two halves sorted in step 2 and 3:
merge(arr, l, middle, r)
Example of the merge sort algorithm applied to the array [5, 3, 4, 2, 1]:
1. Splitting: The array is recursively divided into two halves until the size becomes 1 or 0. In this
example, the array is divided into two halves [5, 3] and [4, 2, 1].
[5, 3, 4, 2, 1] -> [5, 3] [4, 2, 1]
2. Splitting and Merging: The two halves are further divided into sub-halves until the size
becomes 1 or 0. Then, they are merged back into a sorted array. In this example, the sub-
halves are [5] and [3] and [4] [2] [1], and they are merged back into [3, 5] and [1, 2, 4].
[5, 3] -> [5] [3] -> [3, 5]
[4, 2, 1] -> [4, 2] [1] -> [4] [2] [1] -> [2, 4] [1] -> [1, 2, 4]
3. Merging: The two sorted sub-arrays are merged back into a single sorted array. In this example,
the two sorted sub-arrays [3, 5] and [1, 2, 4] are merged back into [1, 2, 3, 4, 5].
[3, 5] [1, 2, 4] -> [1, 2, 3, 4, 5]
4. Result: The final sorted array is [1, 2, 3, 4, 5].

Programming in C & Data Structure 84


kn Unäv

5.3.c Bubble sort


Bubble sort is a simple comparison-based sorting algorithm. It compares adjacent elements of an
array and swaps them if they are in the wrong order until the entire array is sorted.
Here is the pseudocode for bubble sort
for i = 0 to n-1
for j = 0 to n-i-1
if a[j] > a[j+1]
swap(a[j], a[j+1])
In this pseudocode, n is the number of elements in the array, and a is the array to be sorted. The two
nested loops iterate over the array and compare adjacent elements. If the elements are in the wrong
order, they are swapped.
The outer loop controls the number of passes through the array. Since each pass places the largest
remaining element in its proper position, the number of passes required is n-1. The inner loop
compares adjacent elements and swaps them if they are out of order. After each pass, the largest
remaining element is moved to its proper position, so the inner loop can stop one element earlier than
the previous pass.
Example of the bubble sort algorithm applied to the array [5, 3, 4, 2, 1]:
Pass 1
Step 1: Compare the first two elements (5 and 3). Since 5 > 3, swap them. [3, 5, 4, 2, 1]
Step 2: Compare the next two elements (5 and 4). Since 5 > 4, swap them. [3, 4, 5, 2, 1]
Step 3: Compare the next two elements (5 and 2). Since 5 > 2, swap them. [3, 4, 2, 5, 1]
Step 4: Compare the next two elements (5 and 1). Since 5 > 1, swap them. [3, 4, 2, 1, 5]
One pass through the list is completed. Now, the last element is guaranteed to be the largest, so we
can ignore it in the next pass.
Pass 2
Step 5: Compare the first two elements (3 and 4). Since 3 < 4, do not swap them. [3, 4, 2, 1, 5]
Step 6: Compare the next two elements (4 and 2). Since 4 > 2, swap them. [3, 2, 4, 1, 5]
Step 7: Compare the next two elements (4 and 1). Since 4 > 1, swap them. [3, 2, 1, 4, 5]
Two passes through the list are completed. The last two elements are already in their correct
positions, so we can ignore them in the next pass.
Pass 3:
Step 8: Compare the first two elements (3 and 2). Since 3 > 2, swap them. [2, 3, 1, 4, 5]
Step 9: Compare the next two elements (3 and 1). Since 3 > 1, swap them. [2, 1, 3, 4, 5]
Three passes through the list are completed.
Pass 4:
Step 10: Compare the first two elements (2 and 1). Since 2 > 1, swap them. [1, 2, 3, 4, 5]
85 Programming in C & Data Structure
kn Unäv

Four passes through the list are completed. The list is now sorted in ascending order
5.3.d Selection sort
Selection sort is an algorithm that works by repeatedly finding the minimum element from the
unsorted part of the list and moving it to the beginning of the list. This algorithm maintains two
sublists, one which is already sorted and the other is unsorted. The algorithm works by selecting the
smallest element from the unsorted sublist and swapping it with the leftmost unsorted element, and
moving the sublist boundaries one element to the right.
The pseudocode for selection sort is
for i = 0 to n-1
min_index = i
for j = i+1 to n
if A[j] < A[min_index]
min_index = j
swap A[i] and A[min_index]
Here’s how selection sort works step-by-step with the given array [5, 3, 4, 2, 1]:
1. First, find the smallest element in the array. In this case, it is 1.
2. Swap the smallest element with the first element of the array. The array now becomes [1, 3,
4, 2, 5].
3. Repeat steps 1 and 2 for the remaining unsorted part of the array, i.e., [3, 4, 2, 5].
4. Find the smallest element in the unsorted part of the array, which is 2.
5. Swap the smallest element with the first element of the unsorted part of the array. The array
now becomes [1, 2, 4, 3, 5].
6. Repeat steps 4 and 5 for the remaining unsorted part of the array, i.e., [4, 3, 5].
7. Find the smallest element in the unsorted part of the array, which is 3.
8. Swap the smallest element with the first element of the unsorted part of the array. The array
now becomes [1, 2, 3, 4, 5].
9. Repeat steps 7 and 8 for the remaining unsorted part of the array, i.e., [4, 5].
10. Find the smallest element in the unsorted part of the array, which is 4.
11. Swap the smallest element with the first element of the unsorted part of the array. The array
now becomes [1, 2, 3, 4, 5].
12. Repeat steps 10 and 11 for the remaining unsorted part of the array, i.e., [5].
13. Find the smallest element in the unsorted part of the array, which is 5.
14. Swap the smallest element with the first element of the unsorted part of the array. The array
now becomes [1, 2, 3, 4, 5].

Programming in C & Data Structure 86


kn Unäv

15. The array is now sorted in ascending order.


5.4 Stack
A stack is a linear data structure that follows the Last In First Out (LIFO) principle, meaning that
the last element added to the stack is the first element to be removed.
The stack has two primary operations:
1. Push: This operation adds an element to the top of the stack. When an element is pushed onto
the stack, it becomes the topmost element of the stack.
2. Pop: This operation removes the topmost element from the stack. When an element is popped
from the stack, the element immediately below it becomes the new topmost element.
Other operations that can be performed on a stack include:
1. Peek or Top: This operation returns the topmost element of the stack without removing it.
2. Size: This operation returns the number of elements in the stack.
3. isEmpty: This operation returns a Boolean value indicating whether the stack is empty or not.
Stacks can be implemented using an array or a linked list. In an array implementation, the topmost
element of the stack is represented by the index of the last element added to the stack, while in a
linked list implementation, the topmost element is represented by the head of the linked list.
Working of Stack
Suppose we have a stack of integers, and perform the following operations:
1. Push the elements 5, 3, and 8 onto the stack.
2. Pop an element from the stack.
3. Push the element 10 onto the stack.
4. Pop an element from the stack.
5. Peek at the top element of the stack.
Here’s how the stack would look like after each operation:
1. Initially, the stack is empty: | |
2. After pushing 5, the stack becomes: | 5 |
3. After pushing 3, the stack becomes: | 3 | | 5 |
4. After pushing 8, the stack becomes: | 8 | | 3 | | 5 |
5. After popping an element from the stack, the topmost element (i.e., 8) is removed: | 3 | | 5 |
6. After pushing 10 onto the stack, the stack becomes: | 10 | | 3 | | 5 |
7. After popping an element from the stack, the topmost element (i.e., 10) is removed: | 3 | | 5 |
8. After peeking at the top element of the stack, we can see that the topmost element is 3, but it
is not removed from the stack: | 3 | | 5 |
9. So, the final state of the stack is: | 3 | | 5 |

87 Programming in C & Data Structure


kn Unäv

Stack underflow and overflow are two common errors that can occur when working with stacks.
1. Stack underflow: A stack underflow error occurs when a pop operation is performed on an
empty stack. In other words, when there are no elements in the stack, but we are trying to
remove an element from it.
For example, suppose we have an empty stack, and we try to pop an element from it: | |
After attempting to pop an element from the stack, we get a stack underflow error.
2. Stack overflow: A stack overflow error occurs when we try to add an element to a stack that
is already full. In other words, when we are trying to push an element onto the stack, but there
is no more space to add new elements. For example, suppose we have a stack of size 3, and
we try to push 4 elements onto it: | 3 | | 2 | | 1 |.
After attempting to push the fourth element (let’s say 4) onto the stack, we get a stack overflow
error.
To avoid these errors, we need to make sure that we always check the size of the stack before
performing any push or pop operations.
5.5 Queue
A queue is a linear data structure that follows the First In First Out (FIFO) principle. It is similar
to a real-life queue or line where the first person who joins the line is the first person to be served.
The queue has two primary operations:
1. Enqueue: This operation adds an element to the rear end of the queue.
2. Dequeue: This operation removes an element from the front end of the queue.
Other operations that can be performed on a queue include:
1. Peek or Front: This operation returns the frontmost element of the queue without removing
it.
2. Size: This operation returns the number of elements in the queue.
3. isEmpty: This operation returns a Boolean value indicating whether the queue is empty or
not.
Queues can be implemented using an array or a linked list. In an array implementation, the front
and rear ends of the queue are represented by two indices, while in a linked list implementation, the
front and rear ends are represented by the head and tail of the linked list, respectively.
Here’s an example to illustrate the working of the queue data structure:
Suppose we have a queue of customers waiting in line at a grocery store, and we want to perform
the following operations:
1. Three customers join the line.
2. The first customer in line is served and removed from the queue.
3. Two more customers join the line.
4. The next two customers in line are served and removed from the queue.
5. We check the number of customers remaining in the line.

Programming in C & Data Structure 88


kn Unäv

Here’s how the queue would look like after each operation:
1. Initially, the queue is empty:
◦ front -> null rear -> null
2. After three customers join the line, the queue becomes:
◦ front -> customer1 -> customer2 -> customer3 <- rear
3. After the first customer is served and removed from the queue, the frontmost customer (i.e.,
customer1) is removed:
◦ front -> customer2 -> customer3 <- rear
4. Two more customers join the line, and they are added to the rear end of the queue:
◦ front -> customer2 -> customer3 -> customer4 -> customer5 <- rear
5. After the next two customers are served and removed from the queue, the frontmost
customers (i.e., customer2 and customer3) are removed:
◦ front -> customer4 -> customer5 <- rear
6. Finally, we check the number of customers remaining in the queue, which is 2:
◦ front -> customer4 -> customer5 <- rear
7. So, the final state of the queue is:
◦ front -> customer4 -> customer5 <- rear
5.6 Linked List
A linked list is a linear data structure that consists of a sequence of nodes, each containing a data
field and a reference (or pointer) to the next node in the sequence. Unlike arrays, linked lists don’t
have a fixed size, and their size can grow or shrink dynamically during program execution.
The first node in the sequence is called the head of the linked list, and the last node is called the
tail. The tail node’s reference is typically set to NULL to indicate the end of the list.
Linked lists can be used to implement various data structures, including stacks, queues, and hash
tables. There are three types of linked lists:
1. Singly linked list: In this type of linked list, each node contains a data field and a reference to
the next node in the sequence.
2. Doubly linked list: In this type of linked list, each node contains a data field, a reference to
the previous node, and a reference to the next node.
3. Circular linked list: In this type of linked list, the last node’s reference points back to the first
node, creating a circular sequence.
Linked lists have some advantages over arrays, including dynamic size allocation and efficient
insertion and deletion of elements. However, they also have some disadvantages, including slower
access time for random elements and extra memory overhead for storing references to the next nodes.
Working of Singly Linked List
Suppose we have a singly linked list that contains the following elements:

89 Programming in C & Data Structure


kn Unäv

Head->1 -> 2 -> 3 -> 4 -> NULL


This linked list has four nodes, with values 1, 2, 3, and 4, respectively. The arrow (->) represents
the reference or pointer from one node to the next. The last node has a NULL reference, indicating
the end of the list.
Now, let’s perform some basic operations on this linked list:
1. Insertion at the beginning: Suppose we want to insert the value 0 at the beginning of the list.
To do this, we create a new node with the value 0 and a reference to the current head node.
Then, we update the head reference to point to the new node. The updated list looks like this:
◦ Head->0 -> 1 -> 2 -> 3 -> 4 -> NULL
2. Insertion at the end: Suppose we want to insert the value 5 at the end of the list. To do this,
we create a new node with the value 5 and a NULL reference. Then, we update the reference
of the last node to point to the new node. The updated list looks like this:
◦ Head->0 -> 1 -> 2 -> 3 -> 4 -> 5 -> NULL
3. Deletion at the beginning: Suppose we want to delete the first node from the list. To do this,
we update the head reference to point to the second node. The updated list looks like this:
◦ Head->1 -> 2 -> 3 -> 4 -> 5 -> NULL
4. Deletion at the end: Suppose we want to delete the last node from the list. To do this, we
traverse the list to find the second-to-last node and update its reference to NULL. The updated
list looks like this:
◦ Head->1 -> 2 -> 3 -> 4 -> NULL
5. Searching for an element: Suppose we want to search for the element 3 in the list. We start
from the head node and traverse the list until we find the node with value 3. In this case, it is
the third node in the list.
5.7 Tree
A tree data structure is a non-linear hierarchical data structure consisting of nodes connected by
edges. Each node in a tree represents a value, and the edges represent the relationship between the
nodes. Trees are commonly used to represent hierarchical structures, such as file systems, organization
charts, and family trees.
The topmost node in a tree is called the root node, and all other nodes are descendants of the root
node. Each node can have zero or more child nodes, and any node except the root node has exactly
one parent node. Nodes with no children are called leaf nodes.
There are several types of trees, including:
1. Binary tree: A binary tree is a tree in which each node has at most two child nodes, referred to
as the left child and the right child.
2. BST (Binary Search Tree): A binary search tree is a binary tree in which each node’s left child
is less than the node’s value, and the right child is greater than or equal to the node’s value.
3. AVL Tree: AVL tree is a self-balancing binary search tree in which the heights of the left and
right subtrees of any node differ by at most one.

Programming in C & Data Structure 90


kn Unäv

4. B-Tree: B-tree is a self-balancing tree data structure that can be used to store large amounts of
data on disk or other storage devices.
Here’s an example of a binary tree to illustrate the concept:
1
/ \
2 3
/\ /\
4 56 7
In this binary tree, the root node has a value of 1, and its left and right child nodes have values 2
and 3, respectively. The left child node has two child nodes with values 4 and 5, and the right child
node has two child nodes with values 6 and 7.
To traverse a tree, there are several algorithms, including depth-first search (DFS) and breadth-first
search (BFS). DFS can be performed using pre-order, in-order, and post-order traversal techniques,
while BFS visits all the nodes of a level before moving to the next level.
Trees have several advantages, including efficient insertion and deletion of nodes, easy traversal,
and easy representation of hierarchical structures. However, they also have some disadvantages,
including extra memory overhead and slower search time compared to other data structures like
arrays and hash tables.

5.7.a Tree Traversals


In a binary tree, there are three commonly used traversal methods that visit each node in a specific
order: inorder traversal, preorder traversal, and postorder traversal. Each of these methods specifies
when the parent node is visited relative to its child nodes.
1. Inorder traversal: In this traversal, we first visit the left subtree, then the root node, and
finally the right subtree. In other words, the left child is visited first, followed by the parent
node, and then the right child.
Here’s an example inorder traversal of the binary tree shown in the previous answer:
4
/ \
2 5
/\ /\
1 3 6 7
Inorder Traversal: 1 2 3 4 5 6 7
2. Preorder traversal: In this traversal, we first visit the root node, then the left subtree, and
finally the right subtree. In other words, the parent node is visited first, followed by the left
child and then the right child.
Here’s an example preorder traversal of the binary tree shown in the previous answer:

91 Programming in C & Data Structure


kn Unäv

4
/ \
2 5
/\ /\
1 36 7
Preorder Traversal: 4 2 1 3 5 6 7
3. Postorder traversal: In this traversal, we first visit the left subtree, then the right subtree, and
finally the root node. In other words, the left child is visited first, followed by the right child
and then the parent node.
Here’s an example postorder traversal of the binary tree shown in the previous answer:
4
/ \
2 5
/\ /\
1 36 7
Postorder Traversal: 1 3 2 6 7 5 4
These traversal methods are used in many applications of binary trees, such as finding the minimum
or maximum element, building an expression tree, or printing the nodes in a specific order.
5.8 Graph
A graph is a non-linear data structure that consists of a collection of nodes, also called vertices, and
a set of edges that connect the nodes. A graph is used to represent a network or a relationship between
entities, where the nodes represent the entities and the edges represent the relationships between them.
A graph can be directed or undirected, depending on whether the edges have a specific direction or
not. In a directed graph, the edges have a specific direction, and each edge connects a source node to a
destination node. In an undirected graph, the edges do not have a specific direction, and they connect
two nodes bidirectionally.
There are several types of graphs, including:
1. Weighted graph: A weighted graph is a graph in which each edge has a weight or a cost
associated with it. The weight can represent the distance between two nodes, the time it takes
to travel between two nodes, or any other measure of similarity or dissimilarity between two
nodes.
2. Connected graph: A connected graph is a graph in which there is a path between any two
nodes. In other words, every node in the graph is reachable from any other node.
3. Tree: A tree is a connected, acyclic graph, where each node has exactly one parent node,
except for the root node, which has no parent.
4. Bipartite graph: A bipartite graph is a graph in which the nodes can be partitioned into two sets
such that no two nodes within the same set are connected by an edge.
5. Complete graph: A complete graph is a graph in which each pair of nodes is connected by an
edge.

Programming in C & Data Structure 92


kn Unäv

Graphs can be represented in several ways, including adjacency matrix and adjacency list. In an
adjacency matrix, the graph is represented as a two-dimensional matrix of size N x N, where N is the
number of nodes in the graph. The rows and columns represent the nodes, and the matrix elements
represent the edges. In an adjacency list, the graph is represented as an array of lists, where each
element in the array represents a node, and the list associated with the element contains the nodes that
are adjacent to it.
Graphs can be used in many applications, such as social networks, transportation networks,
computer networks, and many more. They are used in algorithms such as Dijkstra’s algorithm for
finding the shortest path between two nodes, and Kruskal’s algorithm for finding the minimum
spanning tree of a weighted graph
Examples:
A common example of a graph is a social network. In a social network, the nodes represent the
users, and the edges represent the relationships between them. For example, suppose we have a
social network with four users: Alice, Bob, Carol, and Dave. The relationships between them can be
represented as a graph, as follows:
A - B
| |
C - D
In this graph, each node represents a user, and the edges represent the relationships between them.
For example, there is an edge between Alice and Bob, which represents that they are friends. One
application is to suggest a friend in the above example is to recommend a friend of a friend. For
example, if we want to suggest a friend for Alice, we can look at Alice’s friends (Bob and Carol) and
suggest a friend of theirs who is not already friends with Alice. Suppose that Bob has a friend named
Eve, and Carol has a friend named Frank. We can suggest Eve or Frank as a friend for Alice, because
they are friends of Alice’s friends, but they are not already friends with Alice.
5.8.a Graph Traversal Algorithms
Graph traversal algorithms are used to visit all the nodes in a graph. There are two main traversal
algorithms: Breadth-First Search (BFS) and Depth-First Search (DFS).
1. Breadth-First Search (BFS): In BFS, we visit all the nodes in a graph in a breadth-first
manner, i.e., we visit all the nodes at a given distance from the source node before moving to
the nodes at the next distance. BFS uses a queue data structure to keep track of the nodes to
be visited. The algorithm is as follows:
◦ Enqueue the starting node in the queue.
◦ Mark the starting node as visited.
◦ While the queue is not empty:
(a) Dequeue a node from the queue.
(b) Visit the dequeued node.
(c) Enqueue all its adjacent nodes that have not been visited yet.
(d) Mark the adjacent nodes as visited.

93 Programming in C & Data Structure


kn Unäv

2. Depth-First Search (DFS): In DFS, we visit all the nodes in a graph in a depth-first manner,
i.e., we visit all the nodes along a path from the source node before backtracking and visiting
other paths. DFS uses a stack data structure to keep track of the nodes to be visited. The
algorithm is as follows:
◦ Push the starting node onto the stack.
◦ Mark the starting node as visited.
◦ While the stack is not empty: a.
(a) Pop a node from the stack.
(b) Visit the popped node.
(c) Push all its unvisited adjacent nodes onto the stack.
(d) Mark the adjacent nodes as visited.
BFS and DFS can be used for different purposes. For example, BFS can be used to find the shortest
path between two nodes, while DFS can be used to find all the connected components in a graph.

References
1. Data Structures Using C, Reema Thareja, Oxford University Press India
2. Classic Data Structures, Samanta Debasis, Prentice Hall of India, 2nd ed.,

Programming in C & Data Structure 94


kn Unäv

95 Programming in C & Data Structure


kn Unäv

Programming in C & Data Structure 96

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