Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
20 views251 pages

C Programm

Uploaded by

Darshan B R
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)
20 views251 pages

C Programm

Uploaded by

Darshan B R
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/ 251

1

INDEX
Sessions C Fundamentals 64 Hours Page no
Session Basics of C 2 Hours 4–30
Introduction to programs 4
The constituents of any programming language 5
Algorithms, pseudocodes, and flowcharts 6
Introduction to C 14
History, features, and applications, Installation 17–26
Structure of C program (syntax) 26–29
Q&A and Summary 29–30
Session 2 Variables and Data Types 2 Hours 31–56
Overview of variables and data types in C 31–36
Understanding different data types and their usage 36–54
Declaring and initializing variables correctly 31–34
Using format specifiers (%d, %f, %c, %s, etc.) in printf() and 34–36
scanf()
Differentiating between implicit (automatic) and explicit 50–55
(manual) type conversions
Q&A and Summary 55–56
Session 3 Operators and Expressions 2 Hours 57–75
Introduction to Operators and Expressions 57
Types of Operators in C - 57–66
Arithmetic, Relational, Logical,
Bitwise, Assignment and
Compound Assignment Operators
Operator Precedence and Associativity 66–70
Q&A and Summary 70–71
Session 4 Input and output 2 Hours 72–85
Introduction to Input and Output 72–74
Using printf() and scanf() or Console I/O 76–77
Character Input and Output 77–79
File Input and Output Basics 79–83
Q&A and Summary 83–85
Session 5 Condition Statements and AI Code Generation 2 Hours 86–112
Introduction to Conditional Statements in C, if, If-else, Nested if 86–92
Switch Statement, Ternary Operator 92–96
AI-Assisted Code Generation for C Programming 96–98
AI Tools for C Code Generation, AI-Assisted Examples 99–104
Debugging & Optimization 104–110
Q&A and Summary 110–112
Session 6 Loops and AI Code Generation 2 Hours 113–133

2
Introduction to Loops, for Loop, while Loop, do-while Loop 113–126
Loop Control Statements 126–128
AI Code Generation in C 128–132
Q&A and Summary 132–133
Session 7 Arrays (One-dimensional & Two-dimensional) 2 Hours 134–145
Introduction to Arrays 134–135
One-Dimensional (1D) Arrays 135–138
Two-Dimensional (2D) Arrays 139–142
Q&A and Summary 143–145
Session 8 Pointers and AI Code Generation 2 Hours 146–180
Introduction to Pointers, Pointer Basics, Pointers and Arrays 146–169
Dynamic Memory Allocation 169–176
AI Code Generation for Pointers 176–178
Q&A and Summary 179–180
Session 9 Functions and AI Code Generation 2 Hours 181–200
Introduction to Functions 181–182
Defining and Using Functions 182–184
Function Types and Scope, Recursion in C 184–197
AI Code Generation for Functions 197–199
Q&A and Summary 199–200
Session 10 Strings 2 Hours 201–212
Introduction to Strings 199–200
Declaring and Initializing Strings 202–206
String Operations Using Built-in Functions 206–210
Q&A and Summary 211–213
Session 11 Advanced Data Types (Structures) and Sorting 2 Hours 214–229
Introduction to Structures, Declaring, Initializing, and Accessing 214–223
Structures
Sorting Concepts and Algorithms 224–230
225, 227,
Implementing Sorting Algorithms 229
Q&A and Summary 230–231
Session 12 File Handling 2 Hours 232–250
Introduction to File Handling 232–233
File Operations and Files Pointers, Reading from and Writing to 234–242
Files
Working with Binary Files 242–245
File Handling Best Practices 245–248
Q&A and Summary 248–250

3
SESSION 1
BASICS OF C

SESSION OBJECTIVES
• Learners will understand algorithms, pseudocode, and flowcharts, enabling them to
break down problems logically and represent solutions effectively.
• Learners will be able to differentiate between these concepts, develop structured
problem-solving skills, and visualize solutions using flowcharts.
• Learner will explore the evolution, key features, and real-world applications of C,
recognizing its importance in system-level programming.
• Learners will analyze the structure of a C program and grasp its compilation and
execution process, building a strong foundation for writing efficient and structured code.

Introduction to Programs
What is a Program?
A program is a set of instructions written in a programming language that a
computer can execute to perform a specific task or solve a problem.
Programs form the foundation of all computer operations, from running
software applications to controlling devices and processing data.

Purpose of Programming
• Automate tasks
• Solves complex problems
• Create applications (e.g., web, mobile, desktop)
• Manage data
• Control hardware devices

Key Concepts
• Input: Data provided to the program.
• Process: The computation or logic applied to the input.
• Output: The result after processing.

4
Constituents of a Programming Language
A programming language typically consists of the following elements:

1. Syntax
The set of rules defines the combinations of symbols considered correctly
structured programs in that language.

2. Semantics
The meaning behind syntactically correct statements—how they behave
when executed.

3. Keywords
Reserved words that have special meaning (e.g., if, while, for, return).

4. Variables and Data Types


Used to store and manage data. Data types define the kind of data (e.g.,
integer, float, string).

5. Operators
Symbols that perform operations on variables and values (e.g., +, -, ==, &&).

6. Control Structures
Used to control the flow of execution:

7. Conditional statements (if, else)


Loops (for, while)
Switch-case

8. Functions/Procedures
Reusable blocks of code are designed to perform a specific task.

9. Input/Output Statements
Allow interaction with the user or other programs/devices (e.g., print(),
scanf()).

5
Algorithms, Pseudocode, and Flowcharts
What is an Algorithm?
An algorithm is a well-defined, step-by-step sequence of instructions used
to solve a specific problem or accomplish a particular task. It provides a
logical approach to problem-solving, ensuring that a given input leads to a
correct and expected output through a finite number of well-structured
steps.

Characteristics of a Good Algorithm:


Definite: Each step must be clear and well-defined. Example: In a recipe,
"Chop onions finely" is a definite step, whereas "Prepare ingredients" is
vague.
• Finite: The algorithm must complete in a limited number of steps.
Example: A loop that runs indefinitely is not a good algorithm.
• Effective: Each step should be simple enough to be performed
efficiently. Example: Instead of checking every element in a list, a
binary search algorithm finds an item much faster.
• Input/output: An algorithm should accept inputs and produce
expected outputs. Example: A sorting algorithm takes an unordered
list as input and outputs an ordered list.

Example Algorithm: Find the Factorial of a Number


1. START
2. Read an integer N
3. Set factorial = 1
4. If N == 0 or N == 1, return factorial
5. Otherwise, repeat the following steps until N = 1:
o Multiply factorial by N

6
o Decrease N by 1
6. Print factorial
7. END
This algorithm computes the factorial of a number using iteration. For
example, if N = 5, the factorial is calculated as 5 × 4 × 3 × 2 × 1 = 120.

What is Pseudocode?

Pseudocode is a method of designing algorithms using plain English-like


statements rather than a specific programming language syntax. It helps
bridge the gap between human understanding and computer programming
by allowing developers to focus on the logic of a problem rather than the
exact syntax of a programming language.

Key Features of Pseudocode:

• Human-Readable: Pseudocode is written in a way that is easily


understood by humans, using plain language rather than complex
programming syntax.
• Language-Independent: Unlike programming languages, pseudocode
does not adhere to any specific syntax rules, making it universally
applicable.
• Structured Flow: It follows a clear, step-by-step process to outline the
logic of an algorithm before actual coding begins.
• Easily Convertible: Pseudocode can be easily translated into any
programming language because it focuses on logic rather than syntax.
• No Strict Rules: There are no rigid rules for writing pseudocode,
allowing flexibility in expressing logical steps.
• Improves Debugging: Since it focuses on logic rather than syntax, it
helps in identifying and fixing logical errors before writing actual
code.

7
• Efficient Problem-Solving: Helps programmers and developers plan
their solutions efficiently before implementing them in a
programming language.

Example:
Algorithm to find the sum of two numbers:

What is a Flowchart?
A flowchart is a visual representation of a sequence of steps in an
algorithm. It uses different symbols to represent different types of actions
or decisions, making it easier to understand how a process flows from start
to finish.
Flowcharts are widely used in programming and problem-solving as they
provide a clear and organized way to visualize complex processes. A
flowchart is a graphical representation of an algorithm using symbols.

Common Symbols:
• Terminator (Start/End): Represented by an oval, it marks the
beginning or end of a flowchart.
o Example: ⬭ Start / End

• Process: Represented by a rectangle, it shows an operation or


action in the process.
o Example: ▭ Perform Calculation
• Decision: Represented by a diamond, it indicates a decision point
that leads to different outcomes.
o Example: ◇ Is X > Y?

8
• Input/Output: Represented by a parallelogram, it shows data
input or output operations.
o Example: ▱ Read Data / Display Output
• Arrows: Show the flow direction of the process from one step to
another.
o Example: → (points to the next step)

Flowchart Example for Sum of Two Numbers:

4. Differentiate Between Algorithms, Pseudocode, and Flowcharts


Feature Algorithm Pseudocode Flowchart
Format Text (logical steps) Structured English- Visual diagram
like instructions
Language Natural/technical Semi-code, no Graphical symbols
language strict syntax
Easy to Yes Easier than code, Requires drawing
Write readable

9
Easy to Moderate High High
Read
Use Case Problem-solving, Initial program Visualizing
logic design design complex logic or
processes

5. Develop Logical Thinking by Designing Step-by-Step Solutions Using


Algorithms
Example Problem: Find the Largest of Three Numbers
Algorithm:
1. START
2. Read numbers A, B, and C
3. If A > B and A > C, then A is the largest
4. Else if B > A and B > C, then B is the largest
5. Else C is the largest
6. Print the largest number
7. END

This process trains your mind to:


• Break down a problem into smaller parts
• Analyze possible conditions and outcomes
• Plan a structured approach to any challenge

6. Represent Algorithms in a Structured Format Using Pseudocode


Pseudocode Example for Finding Largest of Three Numbers:

10
7. Visualize Problem-Solving Techniques Using Flowcharts
Flowcharts help break down problems into logical steps, making it easier to
understand and implement solutions effectively. They serve as a visual
guide for programmers, students, and problem-solvers to streamline
processes and improve efficiency.

Benefits of Using Flowcharts


1. Understanding Logic at a Glance
Flowcharts provide a clear and structured representation of a
problem-solving approach. By following the flow of arrows and
symbols, users can quickly grasp the logic behind a solution without
needing to read complex textual explanations.
Example: A flowchart for calculating the sum of two numbers visually
represents the steps involved, from taking input to displaying the
output.

2. Identifying Decision Points and Loops


Flowcharts highlight key decision-making steps (conditions) and
iterative processes (loops), making it easier to understand and
optimize the logic.
Example: In a flowchart for checking if a number is even or odd, a
decision symbol (diamond) helps determine the path based on
whether the number is divisible by 2.
11
3. Communicating Ideas Clearly
Flowcharts serve as a universal language for conveying complex logic
in a simple and structured manner. They help developers, students,
and professionals collaborate effectively by providing a visual
representation of processes.

Example: In team projects, a well-designed flowchart can help


different members understand the workflow, reducing confusion and
improving productivity.

Flowchart: Largest of Three Numbers

12
Programming Languages
Programming languages serve as the backbone of software development,
enabling programmers to communicate with computers effectively. There are
numerous programming languages, each designed with specific goals and
applications. This eBook explores the different types of programming languages,
categorized based on abstraction level, paradigm, execution, and usage.

1. Based on Abstraction Level


1.1 Low-Level Languages
Low-level languages are closer to machine code, offering high
performance but requiring deep technical knowledge.
• Machine Language: The most fundamental language,
consisting of binary code (0s and 1s), directly understood by
the computer.
• Assembly Language: Uses symbolic representations of
machine instructions, requiring an assembler to translate it
into machine code.

1.2 High-Level Languages


High-level languages are more human-readable and abstracted from
the hardware, making programming easier and more efficient.
• Examples: C, Java, Python, Ruby, JavaScript.

2. Based on Programming Paradigm


Programming paradigms define the approach to structuring and solving
problems in code.

2.1 Procedural Languages


Procedural programming is based on structured step-by-step
execution, using functions and procedures.
• Examples: C, Pascal, Fortran.

2.2 Object-Oriented Languages (OOP)


OOP is based on concepts of objects and classes, promoting code
reuse and modularity.

13
• Examples: Java, C++, Python, C#.

2.3 Functional Languages


Functional programming emphasizes immutability, pure functions,
and higher-order functions.
• Examples: Haskell, Lisp, Scala, Elixir.

2.4 Logic-Based Languages


Logic programming uses declarative rules and facts to solve
problems.
• Example: Prolog.

2.5 Scripting Languages


Scripting languages are usually interpreted and automate repetitive
tasks or enhance applications.
• Examples: Python, JavaScript, PHP, Perl.

3. Based on Execution
3.1 Compiled Languages
Compiled languages are translated into machine code before
execution, making them faster and more efficient.
• Examples: C, C++, Rust, Go.

3.2 Interpreted Languages


Interpreted languages execute code line-by-line, making debugging
easier but sometimes slower.
• Examples: Python, JavaScript, Ruby.

3.3 Hybrid Languages


Hybrid languages combine both compilation and interpretation for
optimized performance and flexibility.
• Examples: Java (compiles to bytecode, runs on JVM), C#.

4. Based on Usage
4.1 General-Purpose Languages

14
Designed for a wide range of applications, from web development to
machine learning.
• Examples: Python, Java, C++, JavaScript.

4.2 Domain-Specific Languages (DSLs)


Created for specialized tasks and industries.
• Examples:
o SQL (Databases)
o MATLAB (Scientific Computing)
o HTML/CSS (Web Development)

INTRODUCTION TO C
C is a middle-level, general-purpose programming language that is widely used for
system and application software development. It provides low-level access to
memory and system resources, making it efficient for performance-critical
HISTORY OF C
Year Event Explanation
1960 Development of ALGOL (Algorithmic Language) was
ALGOL developed as a standard for algorithms
and influenced many future languages,
including C.
1963 Birth of CPL CPL was created as an extension of ALGOL,
(Combined aiming for more flexibility but was too
Programming complex for practical use.
Language)
1967 BCPL (Basic BCPL was developed as a simplified version
Combined of CPL, focusing on system programming
Programming and portability. It introduced low-level
Language) by Martin programming constructs that influenced C.
Richards

15
1970 B Language by Ken Ken Thompson, at Bell Labs, developed B,
Thompson which was based on BCPL but removed
unnecessary complexities. It was used for
early UNIX development but had
limitations like inefficient data types.

1972 Birth of C by Dennis Dennis Ritchie at Bell Labs developed C by


Ritchie improving B. He added data types, better
control structures, and memory
manipulation capabilities. C was created
for writing system software, especially
UNIX.
1973 C used for UNIX UNIX was rewritten in C, making it portable
Kernel Development across different hardware platforms, a
major breakthrough in operating systems.

1978 K&R C (First Official Brian Kernighan and Dennis Ritchie


Description by published "The C Programming Language",
Kernighan & Ritchie) defining standard C syntax and best
practices, known as K&R C.

1983 ANSI C The American National Standards Institute


Standardization (ANSI) started the process of standardizing
Started C to ensure compatibility across compilers.

1989 ANSI C (C89) Standard The first official standard of C, known as


Released ANSI C (C89) or ISO C (C90), was released,
defining syntax, standard libraries, and
function prototypes.

1990 ISO C (C90) - The International Organization for


International Standardization (ISO) adopted ANSI C as
Standardization ISO C (C90), making it an internationally
recognized standard.

16
1995 C95 (Minor Updates The ISO committee released a small
to C90) update to C90, improving
internationalization support and adding
new library functions like wchar_t.
1999 C99 Standard This version introduced several
Released improvements, including variable-length
arrays (VLAs), inline functions, new data
types (long long int, _Bool), and restrict
keyword for optimization.

2011 C11 Standard Added multi-threading support, atomic


Released operations, type-generic macros, and safer
standard library functions (e.g., gets_s()
replacing gets()).

2018 C18 Standard Mostly a bug-fix update to C11, ensuring


Released better stability, but no major new features
were added.
Future C23 (Upcoming Expected to bring further standardization,
Version) better compatibility, and improvements in
security and performance.

FEATURES OF C

17
1. Structured Programming
• C supports structured programming, which emphasizes dividing.
• Programs into functions or modules, making code more organized,
readable, and maintainable.
• It encourages using control flow statements such as if, else, while, for,
and switch, which help structure logic.

2. Modularity and Reusability


• C supports the use of functions, allowing programmers to write
modular code that is reusable across different programs. This
promotes better organization and makes it easier to manage large
programs.

3. Portability
• Programs written in C are highly portable, meaning they can be
executed on different computer architectures with minimal
modifications. This is due to C's reliance on a small set of instructions
that can be implemented on virtually any hardware.

4. Powerful data structures


• In C, the feature of "powerful data structures" refers to the ability to
create and manage complex data structures that are essential for
solving problems efficiently.
• C provides the tools to implement various data structures, both built-
in and user-defined, offering flexibility and control over how data is
stored and manipulated.

18
APPLICATIONS

1. SYSTEM SOFTWARE
System software refers to the software designed to provide a
platform for running application software and managing hardware
resources.

• Operating Systems: C is used extensively in the development


of operating systems (e.g., UNIX, Linux). It helps manage
memory, process scheduling, file systems, and hardware
interfaces.
• Compilers and Interpreters: C is used to write compilers and
interpreters that translate high-level languages to machine
code.
• Utility Programs: System utilities like file management tools,
system monitor utilities, and disk management programs are
often written in C for their performance and portability.

2. EMBEDDED SYSTEMS
C is widely used in embedded systems programming, which involves
working with hardware and firmware. Microcontrollers and
microprocessors in devices like automotive systems, medical

19
equipment, home appliances, and consumer electronics often use C
for efficiency and control over hardware.

3. PORTABILITY
• Due to its portability, C is often used for developing cross-
platform software.
• C programs can be compiled on different platforms with
minimal changes, making them useful for applications that
need to run on various operating systems.

4. GAMES DEVELOPMENT
While modern game engines often use high-level languages, C is still
used for developing performance-critical components of games, such
as physics engines or low-level graphics rendering.
Many early video games and game consoles were programmed using
C.
5. EMBEDDED SOFTWARE FOR IOT (INTERNET OF THINGS)
C is used in the development of software for IoT devices, which often
have limited resources. The language’s efficiency in terms of memory
usage and performance is essential for these resource-constrained
systems.

INSTALLATION:
To install a C programming environment on Windows, you'll need two main
components:
• VS Code: A text editor to write your code,
• MinGW: A compiler that turns your C code into an executable
program.

Follow the steps below to install C on Windows:


1. Install VS Code
2. Download MinGW Compiler
3. Run the installer
4. Add MinGW to System PATH
5. Install C/C++ Extension in VS Code
Here's a detailed explanation of each of the steps.

20
Step 1: Install VS Code
Go to the VS Code Official website and download the Windows installer.
Once the download is complete, run the installer and follow the installation
process.
Click Finish to complete the installation process.

Step 2: Download MinGW Compiler

Visit the official MinGW website and download the MinGW installation
manager.

Step 3: Run the Installer Now, go to your downloads folder and run the
installer you just downloaded. You will be prompted to this screen.

21
• Click on Continue and wait till the download is completed.
• Include gcc-core package
• During installation, you will be prompted to select the components to
install.
• Mark mingw32-base for installation, click on installation and apply
changes.

22
Step 4: Add MinGW to System PATH
✓ Go to the folder and double click on the MinGW folder and copy its
location.
C:\MinGW\bin
✓ search environment variable on the terminal.
✓ In system properties, click on environment variables.
✓ You will be prompted to the screen below.

23
✓ Then, find the Path variable in the System variables section and click
on Edit.
✓ Click New and add the path to the bin directory within your MinGW
installation (i.e., C:\MinGW\bin)
✓ Finally, close all the dialogues with the Ok button.

Step 5: Install C/C++ Extension in VS Code


Open VS Code and click on Extensions on the left side of the window.
Then, search for C/C++ by Microsoft in the Extensions and click on install.

24
Now, you are all set to run C code inside your VS Code.
Note: Alternatively, you can use IDEs like
Code::Blocks or Visual Studio, which come with their own C compilers.

Run Your First C Program


First open VS Code, click on the File in the top menu and then select New
File.

25
Then, save this file with a .c extension by clicking on File again, then Save
As, and type your filename ending in .c. (Here, we are saving it as hello.c)
Now, write the following code into your file:

Then click on the run button on the top right side of your screen.

You should see Hello World printed to the command prompt.

STRUCTURE OF C PROGRAM (Syntax)

Remember these important things about printf:


• Everything you want to print should be kept inside parentheses ().
• The text to be printed is enclosed within double quotes "".
• Each printf statement ends with a semicolon ;.

26
Not following the above rules will result in errors and your code will not run
successfully.

Explanation: This is a preprocessor directive. The #include statement tells the C


preprocessor to include the contents of the specified file in the program before
the compilation starts.
Purpose: In this case, <stdio.h> is the standard input-output header file. It
contains the declarations of functions like printf, scanf, etc., that are used for
handling input and output operations. By including this file, the program can use
these functions.

This line defines the main function.


• int: This specifies that the function will return an integer value (usually used
to indicate if the program ran successfully or not). In this case, the int
means that the function will return an integer to the operating system when
it finishes.
• main: This is the name of the function. Every C program must have a main
function, which serves as the entry point of the program.
• (): Parentheses are used here to declare that the function doesn't take any
parameters.
• {: This curly brace starts the body of the function, where the actual code
inside main will go.

Explanation: This is a function call to printf, a function defined in the stdio.h


header file.
• printf: This is the function that prints text to the standard output (usually
the console or terminal).
• "Hello World": This is the string that will be printed. Text strings in C are
enclosed in double quotes.

27
• ; -> This semicolon marks the end of the statement in C, similar to a period
at the end of a sentence in English.

Purpose: The purpose of this line is to output the text Hello World to the console
or terminal where the program is run.

This statement ends the main function and returns a value to the operating
system.
• return: This is a keyword in C that returns a value from the function to its
caller.
• 0: This is the value being returned. In C programs, returning 0 typically
indicates that the program finished successfully. Nonzero values are usually
used to indicate errors.
• ; ->The semicolon marks the end of the statement.

Purpose: This line tells the operating system that the program has executed
successfully. Returning 0 is a standard way to signal success in C programs.

every C program we will write will follow this structure:

And, we will write out code inside curly braces {}.

COMMENTS
✓ A comment makes the program easier to read and understand. These are
the statements that are not executed by the compiler or an interpreter.
✓ Comments are hints that we add to our code, making it easier to
understand.
✓ Comments are completely ignored by C compilers.

28
Single-line comments
• They are used to comment out a single line of code or a part of it.
• These comments start with two forward slashes (//), and everything after
the slashes on that line is considered a comment.

Syntax:
// This is a single line comment

Multi line comments


✓ Multi-line comments are used for longer descriptions or for commenting
out multiple lines of code.
✓ These comments begin with /* and end with */. Everything between these
markers is treated as a comment.

Syntax:
/* This is a multi-line comment
which can span multiple lines */

Summary
This module provided a foundational understanding of programming, focusing on
key concepts essential for beginners. It introduced the basics of programs and the
fundamental components of a programming language, including syntax,
semantics, variables, and control structures. The importance of algorithms,
pseudocode, and flowcharts was highlighted as essential tools for designing logical
solutions before coding. Additionally, the C programming language was explored
in depth, covering its evolution, key features, real-world applications, and program
structure. The process of compilation and execution in C was also explained,
detailing how source code is translated into machine-executable instructions. By
mastering these concepts, learners develop problem-solving skills and gain the
ability to write efficient C programs, setting a strong foundation for advanced
programming concepts.

29
Check your knowledge:

• What is an algorithm? Write an algorithm to check if a number is even or


odd.
• What is the difference between syntax and semantics in programming?
• What are the key components of a C program? Explain the role of main()
function.
• Differentiate between compiled and interpreted languages. Where does
C fall in this classification?
• Explain the importance of #include <stdio.h> in a C program.
• What is a flowchart? Draw a simple flowchart for adding two numbers.
• List and explain any five features of the C programming language.
• Write a simple C program to take two numbers as input and print their
sum.
• Briefly describe the history of C programming. Who developed it, and
why?

30
SESSION 2
VARIABLES AND DATA TYPES
SESSION OBJECTIVES
To provide a foundational understanding of how variables and data types work in the C
programming language. By the end of this module, learners should be able to:

• Understand Variables and Data Types


• Correctly Declare and Initialize Variables
• Use Format Specifiers in Input and Output

Differentiate Implicit and Explicit Type Conversions

By mastering these concepts, learners will be well-equipped to handle data effectively in C


programs and avoid common errors related to type mismatches and incorrect variable usage.

Overview of variables and data types in C


VARIABLE:
✓ A variable in C is a named memory location that stores a value (data
container), which can be changed during program execution.
✓ It is a fundamental concept in programming as it allows the
manipulation and storage of data.
✓ Without variables, managing and processing data would be extremely
difficult, as programmers would have to work directly with memory
addresses.

Rules for Naming Variables in C


1. Must start with a letter (A-Z, a-z) or an underscore (_).
2. Can contain letters, digits (0-9), and underscores (_).
3. It cannot be a keyword (e.g., int, return).
4. Case-sensitive (total and Total are different variables).
5. No special characters (@, $, %) or spaces allowed.

31
Variable Declaration
A variable must be declared before it is used. The declaration tells the
compiler the variable name and data type.

Syntax:
Datatype variable_name;(declaring a variable)

Example:
int num;

Variable Initialization
Variable initialization in C refers to assigning an initial value to a variable at
the time of declaration. If a variable is not initialized, it contains garbage
values (random data already present in memory).

Syntax
data_type variable_name = value;

Example:
int x = 10; // Initialization of an integer variable

Here,
• int → Data type
• x → Variable name
• 10 → Initial value assigned to x
A simple C program that demonstrates the variable usage.
PROGRAM

32
Output:
10

✓ Basically, this program is printing the value of a variable num which is 10.
✓ The first line: #include<stdio.h>: includes the standard input/output
header file (stdio.h) that contains the functions printf and scanf that are
responsible for input and output.
✓ The execution starts from the main function and execute the
statements within the main function.
✓ In main: a variable num is declared and initialised to 10,
✓ Variable Initialization: num is explicitly assigned 10, so it does not
contain a garbage value.

Memory Usage: The variable num is stored in the stack and


deallocated when main() finishes execution.
Return 0: The program ends successfully, returning 0 to the OS.

A) Compile-Time Initialization (Explicit Initialization)


• The variable is initialized at the time of declaration.
• The value is known during compilation.

Example:
int a = 5;
char ch = 'A';
float pi = 3.14;

B) Run-Time Initialization (Dynamic Initialization)


• The variable is initialized during program execution.
• The value is not known during compilation.
• Example: shown below

33
Program

Explanation:
• #include<stdio.h>: inclusion of header file.
• main(): the point where execution starts.
• printf(): In this program, it is prompting the user to enter the number
• scanf(“%d”,&num): scanf() – standard input function

• scanf() is a library function in C that reads formatted input from the


user via the keyboard.
• It is defined in stdio.h (Standard Input-Output header file).

What actually %d means? What is its significance in the program as far we


come across %d in every printf and scanf statements?
The answer is %d is format Specifier

FORMAT SPECIFIER
✓ Format specifiers in C define the type of data to be read or printed.
✓ They are used with input (scanf()) and output (printf()) functions to tell
the compiler how to interpret variables.

scanf("%d", &num); reads an integer from the user and stores it in


num.
34
%d tells scanf() to expect an integer input.
&num is required to store the input at the correct memory
location.
Forgetting & leads to errors or unexpected behaviour.
Always handle incorrect input using input validation.

Format Specifiers in C
In C programming, format specifiers are used in input and output functions
(like printf() and scanf()) to specify the type of data that is being handled.
They tell the compiler how to interpret the value or how to display it.
Format specifiers ensure that the data is printed or inputted in the correct
format, and they are essential for the correct functioning of formatted I/O
operations.

Syntax of Format Specifiers


The general syntax for a format specifier is:

%[width][.precision][modifiers]specifier

Where:
• %: The percent symbol indicates the start of a format specifier.
• width: Specifies the minimum width of the printed output.
• precision: Used for controlling the number of decimal places (for
floating-point values).
• modifiers: Optional flags (such as l for long data types or h for
short data types).
• specifier: The character that tells the type of data to print (d, f, s,
etc.).

Examples of Format Specifiers:


1. %d: Prints an integer (base 10).
2. %f: Prints a floating-point number.
3. %s: Prints a string.

35
Specifier Description
%d Signed decimal integer
%i Signed integer (same as %d)
%u Unsigned decimal integer
%f Floating-point number
%lf Double precision floating-point number
%c Single character
%s String of characters
%x Hexadecimal (lowercase letters)
%X Hexadecimal (uppercase letters)
%o Octal number
%p Pointer address
%e Scientific notation (lowercase)
%E Scientific notation (uppercase)
%g General format for floating-point numbers

Understanding different data types and their usage


Datatypes
Each variable in C has an associated data type.
• It specifies the type of data that the variable can store like integer,
character, floating, double, etc.
• Each data type requires different amounts of memory and has
some specific operations which can be performed over it.

36
Basic datatypes in C

Primitive Datatypes
Primitive data types are the most basic data types that are used for
representing simple values such as integers, float, characters, etc.

Integer Datatype
The integer datatype in C is used to store the integer numbers (any
number including positive, negative and zero without decimal part).
✓ Octal values, hexadecimal values, and decimal values can be
stored in int data type in C.
We use int keyword to declare integer variable.

Syntax:
int variable_name;
int variable_name = value;

Example:
int a = 10;
✓ Size: 4 bytes
✓ Format Specifier: %d

37
The illustration of integer datatype

Output: 10

Size of int
Size:
• The size of an int depends on the system architecture (compiler
and OS).
• The range of a data type in C refers to the minimum and
maximum values that can be stored in a variable of that data type.

Formula for Range

Signed range: −2(n−1)-2^{(n-1)}−2(n−1) to 2(n−1)−12^{(n-1)} -


12(n−1)−1

Unsigned range: 0 to 2n−12^n - 12n−1

Common sizes:
▪ 16-bit system: int is 2 bytes (range: -32,768 to 32,767).
▪ 32-bit system: int is 4 bytes (range: -2,147,483,648 to
2,147,483,647).
▪ 64-bit system: usually 4 bytes.

To check the size of an int datatype:


we use the operator called sizeof(): which returns the size of particular
datatype
38
Syntax:
sizeof(datatype/variablename);

Program

Output: 4

Sign modifiers:
The sign modifier controls whether a variable can hold both positive and
negative values or only non-negative (positive and zero) values.

Types:
• signed → Allows both positive and negative values (default for
int and char).
▪ Format specifier: %d
• unsigned → Allows only non-negative values (positive and
zero).
▪ Format specifier: %u

Size modifiers
The size modifier changes the amount of memory allocated for a data
type, affecting its range and precision.

Types:
• short → Uses less memory than a standard int.
39
o format specifier: %d , %i
• long → Uses more memory than a standard int.
o format specifier : %ld
• long long → Uses even more memory than a long int.
o format specifier: %lld.

Why to use it?


• short int: Saves memory when you know the values are small.
• long int: Allows storing larger integers.

1.short int and unsigned short int


Program

• short int can hold negative values within its range (-32,768 to
32,767).
• unsigned short int can hold only positive values (0 to 65,535).

Output:

40
2.int and unsigned int:
Program

• int supports negative and positive values.


• unsigned int extends the range only for positive values.

Output:

3. long int and unsigned long int


• long int may have a larger size than a standard int (platform-
dependent).
• unsigned long int holds larger positive values.

Program

41
4. Long long int and unsigned long long int
• long long int is designed for large integer values.
• unsigned long long int has a very large positive range.

Program

• long long int is designed for large integer values.


• unsigned long long int has a very large positive range.

Data Type Size Range Format


(bytes) Specifier
short int 2(16bits) -32,768 to 32,767 %hd
unsigned 2(16bits) 0 to 65,535 %hu
short int
Int 4(32 bits) -2,147,483,648 to %d or %i
2,147,483,647
unsigned int 4(32 bits) 0 to 4,294,967,295 %u
42
long int (4 or -2,147,483,648 to %ld
8)(32 /64 2,147,483,647 (on
bits) 32-bit)
unsigned 4 (or 8) 0 to 4,294,967,295 %lu
long int (on 32-bit)
long long int 8(64 bits) -(2^63) to (2^63)-1 %lld
unsigned 8(64 bits) 0 to %llu
long long int 18,446,744,073,709
,551,615

Character Datatype
Character data type allows its variable to store only a single character.
• It stores a single character and requires a single byte of memory in
almost all compilers.

Range:
• (-128 to 127) or
• Signed char(0 to 255)
Size: 1 byte
Format Specifier: %c

Syntax of char:
The char keyword is used to declare a variable of character type:
char variable_name;

In C, a char is essentially an integer type — it holds ASCII values (or other


character encodings). The ASCII value of a character is just its numeric
representation. For example:
• 'A' → ASCII value 65.
• 'a' → ASCII value 97.
• '0' → ASCII value 48.

43
Signed char:

Attribute Signed char Unsigned char


Storage 1 byte 1 byte
Size
Range -128 to 127 0 to 255
Format %c (for printing %c (for printing
Specifier character) character)
Usage Used for storing Used for storing
individual characters characters or small
or small integer values integer values, especially
in the signed range. when the value cannot
be negative.
• Range: -128 to 127 (because 1 bit is reserved for the sign).
• Can store both negative and positive values.

Unsigned char:
• Can store only non-negative values.
• Range: 0 to 255.

Program that illustrates character datatype.

Output: A

44
Points
char is essentially a small integer type!
• A char in C is stored as a 1-byte (8-bit) integer.
• Internally, characters are represented by their ASCII values (a
standardized mapping of characters to integers).
• The character 'A' has the ASCII value 65.
• The character 'a' has the ASCII value 97.
• So, when you assign a character to a char variable, it’s actually storing
the integer ASCII code of that character.
Let us print the ascii value of respective character in C

Example

ASCII Value Table:


ASCII ASCII Character ASCII Character ASCII Character
Value Character Value Value Value

0 NUL 1 SOH 2 STX 3 ETX


4 EOT 5 ENQ 6 ACK 7 BEL
8 BS 9 TAB 10 LF 11 VT
12 FF 13 CR 14 SO 15 SI
16 DLE 17 DC1 18 DC2 19 DC3
20 DC4 21 NAK 22 SYN 23 ETB

45
24 CAN 25 EM 26 SUB 27 ESC
28 FS 29 GS 30 RS 31 US
32 SPACE 33 ! 34 " 35 #
36 $ 37 % 38 & 39 '
40 ( 41 ) 42 * 43 +
44 , 45 - 46 . 47 /
48 0 49 1 50 2 51 3
52 4 53 5 54 6 55 7
56 8 57 9 58 : 59 ;
60 < 61 = 62 > 63 ?
64 @ 65 A 66 B 67 C
68 D 69 E 70 F 71 G
72 H 73 I 74 J 75 K
76 L 77 M 78 N 79 O
80 P 81 Q 82 R 83 S
84 T 85 U 86 V 87 W
88 X 89 Y 90 Z 91 [
92 93 ] 94 ^ 95 _
96 ` 97 a 98 B 99 C
100 D 101 e 102 F 103 G
... ... 252 ü 253 Ý 254 Þ
255 Ÿ

FLOAT AND DOUBLE DATATYPE


Float Datatype
In C programming, the float datatype is used to store floating-point values. It is
commonly used to represent decimal and exponential values with single precision.
• Purpose: To store decimal numbers (numbers with fractional parts).
• Size: 4 bytes
• Range: Approximately 1.2E-38 to 3.4E+38

46
The float type is suitable when memory efficiency is more important than
precision.

• Format Specifier: %f

Syntax
The float keyword is used to declare the variable as a floating point:
float var_name;

1. Size of float in C
• The size of a float in C is typically 4 bytes (32 bits).
• This size is system-dependent but standard on most platforms.

2. Range of float
• Range: ±1.5 × 10⁻⁴⁵ to ±3.4 × 10³⁸ (approximately)
• Precision: Up to 6-7 decimal digits.

Data Type Size (Bytes) Range Precision


Float 4 ±1.2 × 10⁻⁴⁵ to 3.4 × 10³⁸ 6-7 digits

Example Program

47
• %f formats the number in standard decimal notation.
• %e formats the number in scientific notation.
• %g uses the shortest representation between %f and %e.

Restrict the precision


• %.2f prints the float with 2 digits after the decimal point.
• %.5f prints with 5 digits.
• %.10lf and %.15lf restricts the precision of a double.

Program

Double
The double keyword in C is used to declare variables that can hold floating-point
numbers with double precision. It is used when a higher precision is required for
numeric calculations that involve fractional values.

Range:
• The range of the double type is typically much larger than the float type.
• A double typically occupies 8 bytes (64 bits) in memory.
• Its range can vary based on the system architecture, but typically:
• Minimum value: around 2.225 x 10^-308.
• Maximum value: around 1.797 x 10^308.
• Precision: Typically, 15-16 decimal digits.

48
Program

Output

Overview Table: Characteristics of Float and Double


Attribute Float Double long double
Storage 4 bytes 8 bytes 10, 12, or 16 bytes (depends on
Size system)
Format %f, %e, %g %lf, %e, %g (for %Lf (for printing)
Specifier (for printing) printing)
Range Approximate Approximately ±5.0 × Varies depending on system;
ly ±1.5 × 10⁻³² to ±1.7 × 10³⁰ typically, ±1.0 × 10⁻³²to ±1.1 ×
10⁻⁴⁵ to ±3.4 10³⁰
× 10³⁸
Precision 6-7 decimal 15-16 decimal digits 18-19 decimal digits (higher
digits precision)
Default 0.0 0.0 0.0
Value
Usage Used when Used for most Used for higher precision,
memory is general-purpose especially in scientific
limited, for floating-point computations.
less precise calculations.
calculations.
Example float x = double y = long double z =
3.14f; 3.141592653589793; 3.141592653589793238462643;

49
Void Datatype
The void data type in C is used to specify that no value is present. It does not
provide a result value to its caller.
• It has no values and no operations. It is used to represent nothing
• Void is used in multiple ways as a function return type, function arguments
as void.

Differentiating between implicit (automatic) and explicit (manual) type


conversions
In programming, type casting is a way to convert data from one type to another.
Implicit type casting happens automatically, while explicit type casting requires
manual intervention. This article explores the differences between implicit and
explicit type casting, their uses, benefits, and considerations in programming.

What is Type Casting?


Type casting is a concept in programming where you change the data type of a
variable from one type to another. It's like changing a piece of clay from one shape
to another.
There are two types of type casting: implicit and explicit.
• Implicit type conversion (Coercion)
• Explicit type conversion (Casting)

Implicit Type casting


Implicit type conversions, also known as type casting or type transformation, are
automatic type conversions performed by the compiler. Most programming
languages have compilers that handle type transformation automatically.
When operands are of different data types, the compiler automatically performs
implicit type conversions by converting the smaller data type into a larger one.

For example, if you assign an integer value to a float variable, the programming
language will automatically perform an implicit type conversion, converting the
integer to a float without requiring any manual intervention.

50
Advantages:
• Convenience: Implicit casting saves time and effort because you don't have
to manually convert data types.
• Automatic: It happens automatically, reducing the chance of errors due to
forgetting to convert types.

Disadvantages:
1. Loss of Precision: Sometimes, when converting between data types, there
can be a loss of precision. For example, converting from a float to an integer
may result in losing the decimal part of the number.
2. Unexpected Results: Implicit casting can sometimes lead to unexpected
results if the programmer is not aware of how the conversion rules work.

Example: Printing Lowercase Letters


In the example below, we print lowercase letters from 'a' to 'z' by using ASCII
values 97 to 122. The prinf() function converts and displays each value as a
character.

Following is an example of implicit type conversion.

Example: Implicit Integer to Float


Let's demonstrate implicit type conversion by assigning an integer value to a float
variable. This C program shows this process and prints the float value.

51
Explicit Type Conversion
Explicit type conversion is performed by the user by using (type) operator. Before
the conversion is performed, a runtime check is done to see if the destination type
can hold the source value.

Explanation:
1. int a, c; – Declares two integer variables a and c.
2. float b; – Declares a floating-point variable b.
3. c = a + (int)b; –
o b is being explicitly cast to an integer using (int)b, which means its
decimal part will be truncated (not rounded).
o Then a (int) and (int)b (also int now) are added.
o The result is assigned to c (an integer).

Advantages:
• Control: Explicit type casting gives the programmer more control over the
conversion process, allowing for precise manipulation of data types.
• Clarity: By explicitly indicating the type conversion, the code becomes more
readable and understandable to other developers.

52
• Avoidance of Loss of Precision: In cases where precision is crucial, explicit
type casting allows the programmer to handle the conversion carefully to
avoid loss of precision.

Disadvantages:
• Complexity: Explicit type casting can introduce complexity to the code,
especially when dealing with multiple data type conversions.
• Potential Errors: If the programmer incorrectly performs explicit type
casting, it may result in runtime errors or unexpected behaviour.
• Additional Syntax: Explicit type casting requires additional syntax or
function calls, which may increase code verbosity.

Example: Printing Lowercase Letters


Here is an example of explicit type conversion. This C program prints lowercase
letters 'a' to 'z' by explicitly casting ASCII values 97 to 122 from int to char.

Let us see the difference between the two types of conversions with examples.
Example: Converting an Integer to Short
Here, we convert an integer I to a short explicitly, then print the value of a. It
specifies type casting and basic output/input operations.

53
Best Practices for Type Casting:
When choosing whether to use implicit or explicit type casting, it is important to
consider the following best practices:
• Prefer implicit casting when it is safe and does not result in data loss.
• Use explicit casting for narrowing conversions or to clarify intent.
• Avoid unnecessary casts that clutter the code and reduce readability.
• Be cautious with downcasting (e.g., float to int) to prevent data loss.
• Do not mix signed and unsigned types without understanding the
implications.
• Use fixed-width types (int32_t, uint8_t, etc.) for portability and clarity.
• Limit pointer type casting to low-level code and use with care.
• Never cast away const unless absolutely necessary and safe.
• Avoid casting inside macros or complex expressions—prefer inline
functions.
• Enable compiler warnings (-Wall, -Wconversion) to detect unsafe casts.

When to Use Implicit Type Casting


Use implicit type casting when you are confident that the compiler will correctly
determine the correct data type for a variable.
Use implicit type casting when you are converting between compatible data types.
For example, you can implicitly cast an integer to a double, but you cannot
implicitly cast a double to an integer.

When to Use Explicit Type Casting

54
Use explicit type casting when you want to ensure that a variable is converted to a
specific data type. Use explicit type casting when you are converting between
incompatible data types. For example, you can explicitly cast a double to an
integer, but you cannot implicitly cast an integer to a double.

Avoiding Common Pitfalls


• Avoid using implicit type casting when you are not sure whether the
compiler will correctly determine the correct data type for a variable.
• Avoid using explicit type casting when you are converting between
incompatible data types.
• Avoid using type casting to convert between objects of different classes

Conclusion:
In conclusion, understanding implicit and explicit type casting is essential in
programming. Implicit type casting happens automatically when converting data
types, while explicit type casting requires a manual instruction from the
programmer to convert a value from one type to another. Both methods have
their uses and importance in coding. Developers must grasp these concepts to
ensure the accuracy and efficiency of their programs. By mastering implicit and
explicit type casting, programmers can write more robust and error-free code,
leading to better software development practices.

Summary
In C programming, understanding data types like int, float, double, and char is
essential, as each serves a specific purpose based on the kind of data being
stored. Variables must be declared with the correct type and can be initialized
during or after declaration. Input and output operations use format specifiers such
as %d for integers, %f for floats, %c for characters, and %s for strings in functions
like printf() and scanf(). Type conversions occur either implicitly (automatically,
such as converting int to float) or explicitly (manually, using casting like (int)x).
Proper handling of data types and conversions ensures accuracy and efficiency in
C programs.

55
Check your knowledge:
• What is the difference between float and double?
• Which data type would you use to store a single character?
• Can you declare multiple variables of the same type in one line? Give an
example.
• What is the difference between declaration and initialization of a
variable?
• What will happen if you use a variable without initializing it?
• What format specifier would you use to print a float value?
• Why do we not use & in scanf() for strings?
• What does %lf mean, and when should it be used?
• What is the difference between implicit and explicit type conversion?
• What will be the value of int x = (int)3.9; and why?
• Is float f = 10; an example of implicit or explicit conversion?

56
SESSION 3
Operators and Expressions
SESSION OBJECTIVES
• Understand operators and their role in C.
• Classify and apply different types of operators.
• Analyze operator precedence and associativity.
• Implement operator-based programs
• Optimize expressions for efficient computations.
• Solve operator-based problems and MCQs

Introduction to Operators and Expressions


• An operator in C can be defined as the symbol that helps us to
perform some specific mathematical, relational, bitwise, conditional,
or logical computations on values and variables.
• The values and variables used with operators are called operands.
• So, we can say that the operators are the symbols that perform
operations on operands.

Types of Operators in C
These operators are classified into various types based on the kind of
operations they perform:
• Arithmetic Operators
• Relational Operators
• Logical Operators
• Bitwise Operators
• Assignment Operators
• Unary Operators

ARITHMETIC OPERATOR:
In C programming, binary operators are operators that require two
operands to perform an operation. Arithmetic operators are a subset
of binary operators that perform mathematical operations on
numeric data types like int, float, double, etc.

57
The basic arithmetic operators in C are:
• Addition (+): Adds two operands.
• Subtraction (-): Subtracts the right operand from the left
operand.
• Multiplication (*): Multiplies two operands.
• Division (/): Divides the left operand by the right operand.
• Modulo (%): Returns the remainder of the division of the left
operand by the right operand.

Example

OUTPUT:

Points:
o While performing modulo arithmetic operation what if
numerator is less than the denominator? in this case
numerator is returned.
o Float division is not supported in C instead type casting float
into int datatype will returns the result.
o There is a function called fmod() that return exact remainder
after dividing two float values in C.

58
o For to use fmod() in program we need to
include math.h(header file) to program.
o because fmod() is included in math header file

Example Program

Output:

RELATIONAL OPERATOR
Relational operators are used to compare two values or expressions.
These operators help evaluate the relationship between the
operands (values or variables) and return a boolean value (either
true or false), where:
• true is represented by 1
• false is represented by 0

Example Program

59
Output:

• a < b: Checks if a is less than b. Result: 0 (false).


• a > b: Checks if a is greater than b. Result: 1 (true).
• a <= b: Checks if a is less than or equal to b. Result: 0 (false).
• a >= b: Checks if a is greater than or equal to b. Result: 1 (true).
• a == b: Checks if a is equal to b. Result: 0 (false).
• a != b: Checks if a is not equal to b. Result: 1 (true).

LOGICAL OPERATOR
Logical Operators are used to combine two or more conditions/constraints
or to complement the evaluation of the original condition in
consideration. The result of the operation of a logical operator is a Boolean
value either 1(true) or 0(false).

There are three logical operators


• Logical AND (&&)
• Logical OR(||)
• Logical Not(!)

Logical AND (&&):


• Returns true (1) if both conditions are true. If either or both
conditions are false, the result is false (0).
Logical OR (||):
• Returns true (1) if at least one condition is true. If both
conditions are false, the result is false (0).
• Syntax: condition1 || condition
Logical NOT (!):

60
• Reverses the boolean value of the condition. If the condition is
true (1), it returns false (0); if the condition is false (0), it returns
true (1).

Syntax:
!condition

Example Program

Output:

BITWISE OPERATOR:
Bitwise operators in C are used for manipulating individual bits of
integer values. These operators allow you to perform logical
operations directly on bits, which can be useful for tasks like
optimizing performance, working with low-level data, or performing
hardware-related tasks

There are 6 bitwise operators in C


• Bitwise AND operator (&)
• Bitwise OR operator (|)
• Bitwise XOR operator (^)
• Bitwise left-shift operator (<<)
• Bitwise right shift operator (>>)

61
• Bitwise compliment operator (~)
Bitwise operators perform operations directly on the binary
representation of numbers, which are sequences of bits (0s and
1s). Every number in the computer's memory is represented as a
series of bits. These operators allow us to manipulate the
individual bits of integers and perform bit-level operations.

1.Bitwise AND operator (&)


The bitwise AND operator compares the corresponding bits of two
operands. For each pair of bits, the result is:
• 1, if both bits are 1.
• 0, if at least one of the bits is 0.

Bit 1 Bit 2 Result


0 0 0
0 1 0
1 0 0
1 1 1

5&3
// Binary of 5: 0101
// Binary of 3: 0011
// Result: 0001 (which is 1 in decimal)

2.Bitwise OR operator (|)


• The bitwise OR operator compares each corresponding bit of two
operands.
• For each pair of bits, the result is 1 if at least one of the bits is 1.
Otherwise, the result is 0.

Truth Table for OR (|):


Bit 1 Bit 2 Result
0 0 0
0 1 1
1 0 1
1 1 1

62
5|3
// Binary of 5: 0101
// Binary of 3: 0011
// Result: 0111 (which is 7 in decimal)

3.Bitwise XOR operator (^)


The bitwise XOR (exclusive OR) operator compares each corresponding
bit of two operands. The result is 1 if the bits are different (i.e., one is 1
and the other is 0), and 0 if the bits are the same.

Truth Table for XOR (^):


Bit 1 Bit 2 Result
0 0 0
0 1 1
1 0 1
1 1 0

5^3
// Binary of 5: 0101
// Binary of 3: 0011
// Result: 0110 (which is 6 in decimal)

4.Bitwise left shift operator (<<)


The left shift operator shifts the bits of the operand to the left by a
specified number of positions.
• For each shift, the bits are shifted left, and 0 is inserted at the
rightmost bit.
• This is equivalent to multiplying the number by 2^n, where n is
the number of positions shifted.

a = 10
a<<2 shifting a by two bits

63
Step 01: First, we must find the binary representation of the value of
the variable
0 0 0 0 1 0 1 0

0 0 1 0 1 0

Step 02: Take the leftmost 2 bits and remove them and fill the blank
with the remaining bits

0 0 1 0 1 0

Step 03: Fill the rightmost blank spaces with zeroes

128 64 32 16 8 4 2 1

0 0 1 0 1 0 0 0

The value of shifting a by 2 bits is 40.

2. Bitwise Right shift operator (>>)


• The bitwise right shift operator shifts the bits of the operand to
the right by a specified number of positions. Each right shift by 1
position is equivalent to dividing the number by 2.

How it works:
• The bits of the operand are shifted right, and the leftmost bits are
typically filled with 0 (for positive numbers).
• Shifting right by n positions is equivalent to dividing the number
by 2^n.

Step 01: Convert into binary representation


a=10, a>>2
0 0 0 0 1 0 1 0

64
Step 02: Remove the rightmost two bits (number of bits should be
shifted)
0 0 0 0 0 0 0 1 0

0 0 0 0 1 0

Step 3: Fill blank spaces with the remaining bits


The decimal value of a>>2 is 2.
128 64 32 16 8 4 2 1

0 0 0 0 0 0 1 0

Bitwise compliment (~)


• The bitwise complement operator (~) is a unary operator that
inverts or flips all the bits of its operand.
• This means it changes every 1 bit to 0 and every 0 bit to 1.
• The bitwise complement flips every individual bit of the operand.
• For example, if the binary representation of a number is 0101,
after applying the complement operator, it becomes 1010.
• The result of the bitwise complement operation is computed using
two's complement notation. In two's complement, the result of the
bitwise NOT operation on a number is the negative of the number
minus 1.

1. Understanding the ~ Operator


• The ~ operator is a bitwise NOT operator in C.
• It inverts (flips) each bit of the operand.
2. Step-by-Step Process
• Start with a number:
• Choose the integer value you want to perform the bitwise
complement on.
• Convert to binary:
• Express the integer in binary (base 2).
• Example: For the integer 5, the binary representation in an
8-bit system is 00000101.
• Flip all the bits:
• Invert every bit in the binary number:

65
• Every 0 becomes a 1, and every 1 becomes a 0.
• Continuing the example of 5, the binary representation after
flipping all bits would be 11111010.
Result:
• The resulting number after the complement operation is now a
new integer.
• In the example, the bitwise complement of 5 (00000101) becomes
-6 in decimal, because in a signed 2’s complement representation,
the binary number 11111010 corresponds to -6.

Operator Precedence and Associativity


In programming, expressions often involve multiple operators, understanding
which operations are evaluated first and how ties are resolved is crucial for writing
correct and efficient code. This is where operator precedence and associativity
come into play.

What is Operator Precedence?


Operator precedence determines the order in which different operators are
evaluated in an expression.

For example, in the expression:


x = 3 + 4 * 5;
Multiplication (*) has higher precedence than addition (+), so the
multiplication is performed first:
x = 3 + (4 * 5);
If you want addition to occur first, parentheses must be used:
x = (3 + 4) * 5;

Common Precedence Levels (Simplified)


Precedence Level Operators Description
Highest () Parentheses
High *, /, % Multiplicative
Medium +, - Additive
Low ==, !=, >, < Relational

66
Lower &&, `
=, +=, -=
Lowest Assignment
etc.

1. What is Operator Associativity?


When an Expression has two or more operators with the same precedence,
we use Associativity to determine which operator will be executed first and
which will be executed later.

For example, 10 * 2/5, in this example, the multiplication (*) and division (/)
operators have equal precedence, so in which case should we run the
operator first so that the result is correct? Will the operator with first
multiplication (*) be correct, or will the operator with division (/) be
correct?

To know all this, we also have to check the Associativity of those operators.
Seeing the associativity of these operators, when we solve the Expression,
the result is correct. The associativity of the operator in the C language
plays a very important role in such conditions.
In this Expression (10 * 2/5), the Associativity of Multiplication (*) and
Division (/) operators is left to Right, so we will first execute 10 * 2, then,
after that, we will divide the result by 5.

Let’s understand it with a program

Look at this example (10 * 20 + 110/5). In this the Precedence of


multiplication (*) and division (/) operator is more than “+” operator,

67
So, it is clear that the + operator will run after the * and / operators.
But in this expression, first-run multiplication (*) operator or run division (/)
operator? To know this, we have to read the association of these operators.

The Associativity of the stipulated multiplication (*) and division (/)


operators is left to right, so the first * operator (10 * 20) will run, whose
result will be 200.
After that, the “/” operator (110/5) will run, whose result will be 22, and
then the “+” operator will run last, which will result in the total result 222.
Associativity defines the direction of evaluation when two operators of the
same precedence level appear in an expression.
The output of this program will be like this:

Output -:

68
• Left-to-Right (Left Associative)
Most binary operators (like +, -, *, /) are left-associative.
x = 10 - 5 - 2;
• Right-to-Left (Right Associative)
Assignment operators and the ternary?: are right-associative.

69
3. Parentheses Override Everything
Parentheses have the highest precedence. They force certain parts of an
expression to be evaluated first, regardless of default precedence or
associativity.
x = (2 + 3) * 4;

Precedence and Associativity Table (C-style)


Operator Category Operators Associativity
Postfix (), [], . , -> Left-to-Right
Unary +, -, !, ++, -- Right-to-Left
Multiplicative *, /, % Left-to-Right
Additive +, - Left-to-Right
Relational <, >, <=, >= Left-to-Right
Equality ==, != Left-to-Right
Logical AND && Left-to-Right
Logical OR `
Conditional ?: Right-to-Left
Assignment =, +=, -=, etc. Right-to-Left

Summary
Operators and expressions are fundamental in programming, allowing
manipulation of data and control over program flow. Operators are symbols that
perform specific tasks on operands, forming expressions that evaluate to values.
Common types include arithmetic operators (+, -, *, /, %) for mathematical
calculations, relational operators (>, <, ==, etc.) for comparisons, logical operators
(&&, ||, !) for combining conditions, bitwise operators (&, |, ^, etc.) for low-level
binary operations, and assignment operators (=, +=, etc.) for storing values.
Understanding operator precedence and associativity is crucial as they determine
the order in which operations are executed in complex expressions. These
concepts are essential for writing correct and efficient code, and each type of
operator can be demonstrated through simple example programs.

70
Check Your Knowledge
• What is the difference between an operator and an operand in C? Provide
examples.
• Why is operator precedence important when evaluating expressions in C?
• Explain the difference between the == and = operators with examples.
• What is the purpose of the modulo % operator, and what happens when the
numerator is less than the denominator?
• Why can’t the % operator be used with float or double values directly in C?
What is the alternative?
• Describe the function of the logical operators &&, ||, and! in terms of boolean
output.
• How does the bitwise AND (&) operator work at the binary level? Give a simple
example.
• What is short-circuit evaluation, and how does it apply to && and || operators
in C?
• Explain how the left shift (<<) and right shift (>>) operators affect the value of
an integer.
• What is the result of the bitwise complement (~) operation, and why does it
often return a negative value in C?
• Write a program that takes two integers as input and prints their sum,
difference, product, quotient, and remainder.
• Write a C program to calculate the area and perimeter of a rectangle
Use: area = length * breadth, perimeter = 2 * (length + breadth)
• Given the code below, predict the output and explain:

• Write a program to input a float and an integer, then use fmod() to print the
remainder of their division.
• Write a program to shift a number by 2 bits to the left and to the right and
print both results.
• Write a C program that converts temperature from Celsius to Fahrenheit
Use formula: F = (C * 9/5) + 32

71
SESSION 4
INTRODUCTION TO INPUT AND OUTPUT

SESSION OBJECTIVES
To provide a foundational understanding of how to use printf() and scanf() functions in C and
how to work with files

• Understand how data is received from the user and displayed on the screen.
• Learn about standard input (stdin) and standard output (stdout) streams
• Learn how to use printf() to display formatted output on the console. Understand how
scanf() reads formatted input from the user.
• Use getchar(), putchar(), gets(), and puts() for handling character-based input and
output.Understand the differences between formatted and unformatted input/output
functions.
• Learn how to read from and write to files using functions like fopen(), fclose(), fscanf(),
and fprintf().
• Understand file handling modes (r, w, a, etc.).
• Explore basic file operations such as reading, writing, and appending data.
• By mastering these concepts, learners will be well-equipped to use print the result in the
desired pattern and also, they will understand how to write and read data from files

Input and Output Functions in C Programming


Every C program typically performs three primary tasks: accepting input,
processing data, and producing output.

• Input refers to the reception of data, often entered by the user.


• Output refers to the display or presentation of data after it has been
processed.

In most programs, input is accepted from the keyboard, and output is


displayed on the screen. Input-output (I/O) operations are among the most
common tasks in any programming language, and C provides a variety of
functions to perform them efficiently.

The C language supports different types of input and output functions.


These functions can broadly be categorized into formatted and
unformatted input/output operations. In this section, we will primarily
focus on these two categories.

72
Formatted Input and Output Functions
Formatted input/output functions allow the programmer to specify the
format in which data is read or displayed. These functions are part of the C
standard library and are powerful tools for handling various data types such
as integers, floating-point numbers, characters, and strings.

Key Functions:
• printf() – Used to output data in a formatted manner.
• scanf() – Used to read data in a specific format.

Both printf() and scanf() allow formatting control using format specifiers
like %d, %f, %c, %s, etc., and they can be used to input or output almost
any standard data type.

Unformatted Input and Output Functions


Unformatted input/output functions do not provide control over the
formatting of data while reading or writing. They represent the most basic
form of input and output operations in C and are primarily used when
format control is not necessary.

These functions are divided into two main categories:


• Character Input/Output Functions
• String Input/Output Functions

1. Character Input/Output Functions


These functions deal with reading and writing a single character at a time.

Input Functions:
getch() – Reads a character from the keyboard without echoing it to the
screen.
getche() – Reads a character from the keyboard and echoes it on the
screen.
getchar() – Reads a character from standard input (keyboard).

Output Functions:
• putch() – Writes a character to the screen.

73
• putchar() – Also writes a character to the screen, commonly used for
simple output.

2. String Input/Output Functions


In C programming, a string is a collection of characters, usually stored in a
character array. To read and display strings, C provides unformatted string
input/output functions.

String Input Function:


gets() – Reads a string from standard input.

Note: gets() is considered unsafe and has been deprecated in modern C


standards because it does not perform bounds checking, which can lead to
buffer overflow vulnerabilities.

String Output Function:


puts() – Displays a string on the screen, automatically appending a newline
character at the end.

Using printf() and scanf() for Console I/O


Input operations take input from the user and store the values or data into
specific memory locations.

As we already know, a variable is a memory location used to store data.

Output operations are used to display information to the user after


processing.

In C language, printf() is used for output and scanf() is used for input.
Both printf() and scanf() are library functions defined in the header file
<stdio.h>.

Using printf() and scanf() for Console I/O


How to use the printf( ) function?
• printf() function: output function.
o Ex .1: printf(“Message to Printed on Monitor”);

74
o In example 1, the message enclosed within the double
quotes “ “ is going to be printed on the console.
• So, whatever you want to print on the console, you need to
enclose that message within double quotes.
• This statement needs to terminate with a semicolon (;)

Here the sample program to print a message “Welcome to C Programming


Lab”

Escape Sequence Characters:


In printf() statements, we use escape sequence characters to format output
properly. These special characters help with cursor movement, spacing, and
other formatting tasks.

Character Meaning Description

\n New Line Used to shift the cursor to the new line

Used to shift the cursor to a couple of


\t Horizontal Tab
spaces to the right in the same line

\0 Null Character Use to indicate end of the string

Input and Output (I/O) operations are essential parts of any programming
language. In C, I/O operations allow programs to interact with the user,

75
read data from devices (like a keyboard or a file), and display information
on the screen or write to files.

There are two main categories of I/O:


• Standard I/O (Console I/O) – Interacting with the user via the
terminal.
• File I/O – Reading from and writing to files stored on disk.

C provides a powerful and flexible I/O system via standard libraries, mainly
through functions declared in stdio.h.

Using printf() and scanf() for Console I/O


printf() Function
The printf() function is used to display output to the console.

Syntax:

Example:

Format Specifiers:
Specifier Description
%d Integer
%f Floating point
%c Character
%s String

scanf() Function
The scanf() function is used to take input from the user via the keyboard.

76
Syntax:

Example:

Note: Always use & (address-of operator) with variables in scanf().

Character Input and Output


When working with C programming, there are times when handling single
characters is more appropriate than dealing with strings or formatted data.
This is particularly useful in lower-level operations, such as building your
own input systems, text processing, or reading input character by
character.

To handle character-level input and output, C provides two simple but


powerful functions:
• getchar(): Reads a single character from input.
• putchar(): Writes a single character to output.

getchar() Function
The getchar() function is used to read a single character from the standard
input (usually the keyboard). It does not require any parameters and
returns the ASCII value of the character entered.

Syntax:

Example:

77
How It Works:
• The function waits for the user to press a key and then returns the
character.
• Since it returns an int, it can also handle special values like EOF (End Of
File).

Example:

Explanation:
ch = getchar();
• This line uses the getchar() function to read a single character
from the standard input (keyboard).
• Whatever character the user types (followed by Enter) is stored in
the variable ch.
• If the user types multiple characters, only the first character is
captured.

putchar() Function
The putchar() function is used to display a single character to the
standard output (usually the screen). It takes one character as an
argument and returns the character written.

Syntax:

78
How It Works:
You pass a character to putchar(), and it prints it to the console.
It returns the character printed as an int.

Output:

File Input and Output Basics


A file is a container in computer storage devices used for storing data.
C allows you to read and write files using the standard file I/O functions
declared in stdio.h.

File I/O in C
In C programming, File Input and Output (File I/O) refers to reading data
from files and writing data to files stored on the computer's disk. Instead of
interacting with the user through the keyboard and screen, file I/O allows
programs to store data permanently, making them much more useful for
real-world applications.

The C language provides a set of standard library functions in the stdio.h


header file to work with files. These functions allow you to:
• Creating a new file
• Opening an existing file
• Closing a file
• Reading from and writing information to a file

79
Working with files
When working with files, you need to declare a pointer of type file. This
declaration is needed for communication between the file and the
program.

Opening a File
Opening a file is performed using the fopen() function defined in the stdio.h
header file.

The syntax for opening a file in standard I/O is:

Explanation:
fopen():
This is a standard library function defined in stdio.h. It is used to open a file
for reading, writing, or appending. It returns a pointer to a FILE object (of
type FILE *), which is then used to access the file.

"fileToOpen":
This is the name of the file you want to open. It should be a string literal
(enclosed in double quotes). It can be just a filename (e.g., "data.txt") or a
full path (e.g., "C:\\Users\\user\\data.txt"). If the file doesn't exist and
you’re opening in read mode ("r"), it will return NULL.

"mode":
This defines the mode in which the file is opened. It’s also a string (enclosed
in quotes). Some common file modes are:

Mode Meaning
"r" Open file for reading (file must exist)
"w" Open file for writing (creates or overwrites)
"a" Open file for appending
"r+" Open for reading and writing (file must exist)
"w+" Open for reading and writing (creates or overwrites)

80
"a+" Open for reading and appending

ptr:
This is a variable (typically of type FILE *) that holds the file pointer
returned by fopen().

Example:
FILE *ptr;

Return Value:
If the file is successfully opened, fopen() returns a valid file pointer. If the
file cannot be opened (e.g., doesn’t exist in read mode), it returns NULL.

Example Usage:
Use fopen() to open a file.

Reading and writing to a text file


For reading and writing to a text file, we use the functions fprintf() and
fscanf().

They are just the file versions of printf() and scanf(). The only difference is
that fprintf() and fscanf() expects a pointer to the structure FILE.

Reading and Writing


fgetc(fp): Reads a character from the file.
fputc(char, fp): Writes a character to the file.
fgets(str, size, fp): Reads a string.
fprintf(fp, ...): Writes formatted output (like printf).
fscanf(fp, ...): Reads formatted input (like scanf).

81
Example 1: Program to write the data to the file output.txt using fprintf()

Example: Program to read the data to the file output.txt using fscanf()

82
Content of output.txt file:

Example: Program to append the data to the file output.txt using fprintf()

Content of output.txt file:

83
Closing a File
The file (both text and binary) should be closed after reading/writing.
Closing a file is performed using the fclose() function.

Here, fp is a file pointer associated with the file to be closed.

Example: Writing and Reading a File

File I/O in C uses a special file pointer (FILE *), which acts as a connection
between the program and the file.

Using file I/O, you can:


• Save program output to a file instead of displaying it on the screen.
• Load input from a file instead of typing it manually.
• Maintain data across program runs (persistent storage).

Summary
In C programming, input and output (I/O) operations are essential for interacting
with users and handling data. Console I/O is performed using the printf() and
scanf() functions, which allow formatted output to the screen and input from the
keyboard. These functions use format specifiers like %d, %f, %s, and %c to handle
various data types. For simpler, character-by-character operations, C also

84
provides getchar() and putchar(), which are useful for reading or displaying
individual characters.

Beyond console interactions, C supports file input and output, enabling data to be
saved to or read from files on disk. File operations use a file pointer (FILE *) and
functions such as fopen(), fprintf(), fscanf(), fgets(), fputs(), and fclose(). Files can
be opened in modes like "r" (read), "w" (write), and "a" (append), among others.
File I/O is powerful for storing program output, logging data, or loading large
input sets, making it an essential feature for real-world applications.

Check Your knowledge


• Explain the difference between scanf() and fscanf(). When would you use
each?
• What are format specifiers in C? List any four commonly used ones and
their purposes.
• Why is it important to close a file after reading or writing? What function is
used for this?
• Differentiate between getchar() and fgetc(FILE *fp).
• What will happen if you open a file in "w" mode that already exists?
• Explain the purpose of the FILE * pointer. How is it used in file operations?
• Describe the difference between text I/O and binary I/O in C.
• What is the significance of return values from fopen() and scanf()? How
should they be handled?
• List and describe three file modes supported by fopen(). Give a practical use
case for each.
• Can printf() and fprintf() be used interchangeably? Explain with an example.
• Write a C program to read a student's name, roll number, and marks from
the user and print them in a formatted report.
• Create a program that reads characters from the user one by one using
getchar() and echoes them using putchar(), until the user enters a period
(.).
• Write a program to calculate the sum, average, and product of three
floating-point numbers entered by the user.
• Write a C program to read a student's name, roll number, and marks from
the user and print them in a formatted report.

85
SESSION 5
CONDITION STATEMENTS AND AI CODE GENERATION

SESSION OBJECTIVES
• Understand and implement conditional statements in C.
• Learn the use of if statements.
• Learn the use of if-else statements.
• Learn the use of nested if statements.
• Learn the use of switch statements.
• Learn the use of the ternary (? :) operator.
• Introduction to AI tools for C code generation.
• Use AI to write C code.
• Use AI to debug C code.
• Use AI to optimize C code.
• Combine traditional coding with AI assistance.
• Enhance programming skills using both manual and AI-assisted approaches.

Control Flow Statements


Control flow statements are used in programming to determine the order in
which instructions or statements are executed in a program. They allow the
program to make decisions, repeat actions, or control the flow of execution based
on specific conditions or logic.

There are 3 types of control flow statements

• Conditional statements
These statements allow a program to make decisions and execute certain
blocks of code based on whether a condition is true or false. These statements
are fundamental in guiding the program’s execution by providing paths
depending on different situations.
• Looping statements
These statements are used when we need to repeatedly execute a block of
code as long as a condition remains true. These statements allow us to
perform repetitive tasks without writing redundant code.
• case control statements
The switch-case control statement in C allows for decision-making based on
multiple possible conditions for a single variable or expression. It is typically
used when you have many conditions to check, and you want to avoid long if-
else chains.
86
Introduction to Conditional Statements in C: if, if-else, Nested if
In C, programs can choose which part of the code to execute based on some
condition. This ability is called decision making and the statements used for it are
called conditional statements. These statements evaluate one or more conditions
and make the decision whether to execute a block of code or not

1. If Statement:
• If statement is the simplest decision-making statement.
• It is used to decide whether a certain statement or block of
statements will be executed or not
• i.e if a certain condition is true then a block of statements is executed
otherwise not.
• A condition is any expression that evaluates to either a true or false
(or values convertible to true or false).

Syntax:

FLOWCHART

87
How if statement works?
The if statement evaluates the test expression inside the parenthesis ().
• If the test expression is evaluated to true, statements inside the body
of if are executed.
• If the test expression is evaluated to false, statements inside the body
of if are not executed.

1.if ( 3 + 2 % 5 )
printf ( “This works” ) ;
2.if ( a = 10 )
printf ( "Even this works" ) ;
3.if ( -5 )
printf ( "Even this work”);

Note that in C a non-zero value is considered as true, whereas a 0 is


considered to be false. In the first if, the expression evaluates to 5 and since
5 is non-zero it is considered as true. Hence the printf( ) gets executed in
the second if, 10 gets assigned to a so the if is now reduced to if (a)or if
(10). Since 10 is non-zero, it is true hence again printf( ) goes to work. In the
third if, -5 is a non-zero number, hence true. So again printf( ) goes to work.
In place of -5 even if a float like 3.14 were used it would be considered as
true

88
PROGRAM

When the user enters -2, the test expression number<0 is evaluated to
true. Hence, you entered -2 is displayed on the screen.

Outputs:

IF-ELSE STATEMENT
The if statement may have an optional else block. The syntax of the if else
statement is:

Syntax:
if (condition) {
// Code to execute if the condition is true
}
else {
// Code to execute if the condition is false

89
}

HOW IF-ELSE WORKS?


• If the test expression is evaluated to true,
• statements inside the body of if are executed.
• statements inside the body of else are skipped from execution.
• If the test expression is evaluated false,
• statements inside the body of else are executed
• statements inside the body of if are skipped from execution.

Program
When the user enters 7, the test expression number%2==0 is evaluated
false. Hence, the statement inside the body of else is executed.

90
Output

Nested If Statement
It is possible to include an if...else statement inside the body of another
if...else statement.

Program:

Output:

91
ELSE IF LADDER STATEMENT
▪ The if...else statement executes two different codes depending upon
whether the test expression is true or false. Sometimes, a choice has
to be made from more than 2 possibilities.
▪ The if...else ladder allows you to check between multiple test
expressions and execute different statements.

SYNTAX FLOW CHART FOR (IF-ELSE)

92
Program

Output:

SWITCH STATEMENT
A switch statement in C is a control flow construct that allows a variable or
expression to be tested for equality against multiple constant values. It
serves as an efficient alternative to using multiple if-else statements,
particularly when handling several possible conditions. By enabling the
execution of one specific block of code based on the value of an expression,
the switch statement enhances code readability and maintainability,
making it a preferred choice for managing multi-way branching in a clean
and structured manner.

93
• Expression inside the switch must be an integer or character type.
• Each case label must contain a constant expression (e.g., numbers,
characters).
• The break statement is used to exit the switch block;
• otherwise, execution falls through to the next case.
• The default case is optional but executes when no case matches.

WORKING OF SWITCH:

94
TERNARY OPERATOR
The Conditional (Ternary) Operator in C
The conditional operator in C, commonly referred to as the ternary
operator, is a compact and efficient way to perform conditional logic. As its
name suggests, the ternary operator operates on three operands.

Why Use the Conditional Operator?


The conditional operator serves as a concise alternative to the traditional if-
else statement. While it performs the same logical function as if-else, it
allows developers to write more compact and readable code, particularly
for simple conditional assignments.

General Syntax
The syntax of the conditional operator follows this structure:

Depending on your use case, there are a few variations of this syntax:

95
1. Direct Assignment

• If expression1 evaluates to true, expression2 is assigned to the


variable.
• If expression1 is false, expression3 is assigned.

2. With Explicit Condition

Clearer and more common in practice, this form explicitly separates the
condition for better readability.

3. Assignment Inside the Operator

This form allows for more complex logic but may be less readable in certain
contexts.

Flowchart for Ternary Operator

96
Program to Find the Largest of Two Numbers Using Ternary Operator

C Program to Find the Largest of Three Numbers Using Ternary Operator

AI-Assisted Code Generation for C Programming

AI-Assisted Code Generation refers to the use of Artificial Intelligence (AI) tools
and models to automatically write, complete, and optimize code based on natural
language instructions, partial code, or even pseudocode. These tools are trained
on vast datasets that include open-source code, documentation, and
programming patterns, enabling them to understand syntax, logic, and best
practices across multiple programming languages—including C. By interpreting
what a developer wants to achieve, AI can generate relevant code snippets,
suggest improvements, identify bugs, and provide explanations, making coding
more efficient and accessible.

The primary goal of AI-assisted code generation is to enhance developer


productivity, reduce common programming errors, and support learning,
especially for beginners. It helps streamline the coding process, allowing
developers to focus more on problem-solving and design while the AI handles
repetitive or boilerplate code tasks.

97
The process of AI-assisted code generation typically involves four key steps. First,
the user provides a clear prompt—a simple, goal-based instruction that tells the
AI what kind of code to generate. For example, a user might say, "Write a C
program to check if a number is even." The clearer and more specific the prompt,
the better the results.

Next, the AI processes the request. Using natural language processing (NLP), the
AI interprets the instruction, understands the task, and matches it with patterns
and examples it has learned from a vast amount of code data. It then uses this
knowledge to generate an appropriate solution.

In the third step, the AI generates the code. It creates a complete, working C
program that meets the request. The output usually includes properly structured
code, and it may also provide comments or brief explanations to help the user
understand the logic.

Finally, the user reviews and tests the code. You can copy the code into a C
compiler like Code::Blocks, GCC, or any IDE of your choice. After compiling and
running the program, you can check the output to make sure it works as expected
and make any adjustments if needed.

The process of AI-assisted code generation typically involves several key steps to
help users efficiently generate and refine code with the support of artificial
intelligence.

1. Write a Clear Prompt


It all begins with a simple, goal-based instruction that clearly describes what
you want the AI to generate. For example: “Write a C program to check if a
number is even.” Clear and direct prompts lead to more accurate and relevant
code.
2. AI Processes the Request
The AI uses natural language processing (NLP) to interpret your instruction. It
identifies patterns in your prompt and draws from its training on large datasets
of programming examples, tutorials, and documentation to understand what
the code needs to do.
3. AI Generates Code
Based on your prompt, the AI produces a complete, working C program. The
output is typically well-structured and may include comments or brief

98
explanations that clarify how the code works, making it easier for learners to
understand.
4. User Reviews and Tests Code
Once the code is generated, you copy it into your preferred C compiler or IDE
(like Code::Blocks, GCC, or Dev C++). You run the program, observe the output,
and test for correctness. It's important to check if the logic holds true for
various inputs, including edge cases.
5. Ask for Modifications or Enhancements
After testing the initial output, you can ask the AI to improve or modify the
code. For example, you might say: “Now add input validation,” “Convert this to
use a ternary operator,” or “Explain the logic.” The AI can then adjust the code
or provide more details to suit your learning or project needs.
6. Refine and Learn
The final step is all about learning and growth. You can manually tweak the
code, test it with unusual or unexpected inputs, and apply what you've learned
to solve similar problems. This hands-on experience helps reinforce coding
concepts and deepens your understanding over time.

Prompt: "Write a C program to check even or odd"


⬇️
AI Response: (Generates working code)
⬇️
Student: “Now add explanation comments.”
⬇️
AI: Adds inline comments for learning
⬇️
Student: Copies code into IDE, tests it, and understands the logic

AI-Assisted Tools for Programming


AI-assisted tools are software applications that use artificial intelligence, especially
natural language processing (NLP) and machine learning, to help developers write,
debug, and understand code. These tools can automate repetitive coding tasks,
explain complex logic, and generate full programs from simple instructions. One of
the most popular tools in this space is ChatGPT by OpenAI.

99
1. ChatGPT (by OpenAI)

What it is:
ChatGPT is a conversational AI model developed by OpenAI. It understands
and responds to natural language inputs, making it an effective assistant for
generating code, explaining concepts, and solving programming problems in
real time.

How it helps in C programming:


• Write full C programs based on problem descriptions or plain English
prompts.
• Debug code by identifying syntax and logical errors and suggesting
fixes.
• Modify or optimize existing C code for better performance or
readability.
• Generate practice examples for topics like loops, arrays, functions,
and pointers.
• Explain C code line-by-line to help beginners understand what it does.

Example Prompt:

"Write a C program to check if a number is even."

Sample Output:

100
2. Replit AI

Replit AI is an integrated AI assistant built into Replit, a popular online


coding platform that supports over 50 programming languages, including C.
It combines the power of an AI coding assistant with a real-time
development environment, all accessible from a web browser—no setup
required. How it helps in C programming:
Instantly write and run C code in the browser — no need to download
compilers or configure environments. This makes it incredibly beginner
friendly.
AI-powered code generation and explanations — just type your problem
description or question, and Replit AI can generate C code, explain existing
code, or fix bugs.
Debugging support — the AI can help identify syntax or logic errors and
offer clear suggestions for correction.
Interactive feedback loop — you can continue chatting with the AI to refine
code, explore variations, or add features.

Example Usage:
Type a prompt like:
“Write a C program using switch case to create a simple calculator.”

Then click “Generate Code”, and the AI will provide a complete C program
that runs directly in your browser.

Sample Output:

101
AI-ASSISTED EXAMPLES: AI Prompt-Based C Programs

1. if Statement
Prompt: Write a C program to check if a number is positive.

2. if-else Statement
Prompt: Write a C program to check whether a number is even or odd using
if-else.

102
3. Nested if Statement
Prompt: Write a C program to find the largest among three numbers using
nested if.

103
4. if-else-if Ladder
Prompt: Write a C program to classify a student's grade based on marks
using if-else-if ladder.

5. Switch Statement
Prompt: Write a C program using switch case to display the day of the week
(1 to 7).

104
What is Debugging?
Debugging is the process of identifying, analyzing, and correcting errors—
commonly referred to as bugs—in your C program. These bugs can prevent
a program from compiling, cause it to crash, or produce incorrect results.
Debugging ensures that your code behaves as expected and delivers the
correct output under all conditions.
Whether you're a beginner writing your first C program or an experienced
developer working on a large project, debugging is an essential part of the
software development process.

105
Why Debugging is Important
Effective debugging plays a crucial role in the development cycle. Here's
why:
• Fixes Syntax Errors: These are errors related to incorrect use of C
language rules, such as missing semicolons, brackets, or incorrect
function declarations.
• Corrects Logical Errors: These occur when the syntax is correct, but
the program doesn't perform the intended task. For example, using
the wrong condition in an if statement.
• Improves Program Reliability: A well-debugged program is more
stable, reliable, and less likely to crash or produce unexpected results.
• Enhances Learning: By debugging your own code, you gain a deeper
understanding of how your program works—and why it sometimes
doesn’t.

Types of Bugs in C Programming


Understanding different types of bugs is the first step to effective
debugging. Each type of bug affects your program in a different way and
requires a different approach to fix.

Bug Type Example What Happens


Syntax Error Missing ; or incorrect if The compiler will throw an
syntax error and won’t compile your
program. These are often easy
to spot.
Logical Error Using = instead of == in The program compiles
a condition successfully, but the output is
incorrect or unexpected.
These are harder to catch.
Runtime Dividing by zero, The program compiles but
Error accessing out-of-bounds crashes during execution or
array index shows strange behavior. Often
occurs with bad input or faulty
logic.

106
1. Debugging with GDB
GDB (GNU Debugger) is a powerful tool for debugging C programs. It allows
you to run your program step-by-step, inspect variables, and find out where
things go wrong.

Basic GDB Commands


• Starting GDB
To start GDB, run the following command in your terminal:
Copygdb ./your_program
Replace ./your_program with the path to your compiled
executable.

• Setting Breakpoints
A breakpoint is a marker that tells GDB to pause execution at a
certain point.
(gdb) break main

This sets a breakpoint at the start of the main function.

• Running the Program


(gdb) run

This starts running your program until it hits a breakpoint or


finishes.

• Stepping Through Code


To execute the program line by line:
(gdb) step

• To execute the program until the next breakpoint:


(gdb) next

• Inspecting Variables
To check the value of a variable:
(gdb) print variable_name

• Continuing Execution

107
To resume execution until the next breakpoint:
(gdb) continue

• Exiting GDB
To exit GDB:
(gdb) quit

108
OPTIMIZATION
Optimization means making your C program run faster, use less memory, or
perform better, without changing what it does.
Think of it like cleaning and improving your code so it’s smarter and more
efficient

Here’s why optimization is important:


Scenario Why optimize?

Slow program execution Make it faster to improve the


user experience
High memory consumption Save RAM, especially in
embedded systems
Repeated or unnecessary calculations Reduce CPU load

Mobile/IoT/Embedded environments Improve battery life and


performance

Types of Optimizations
1. Compile-Time Optimization refers to the process where the C
compiler automatically improves your code during compilation to
make it:
• Run faster
• Use less memory
• Be more efficient
• All this happens before the program runs – at compile time.
• Because these optimizations are done by the compiler (like gcc,
clang)

when you compile the code — not during runtime.


gcc -O2 mycode.c -o optimized_program

The -O2 flag tells the compiler:


“Please optimize my code during compilation.”

109
2. Runtime Compilation
Runtime Optimization refers to the techniques and practices that help your
program behave more efficiently while it's running — even after
compilation.

Unlike compile-time optimization, runtime optimization is about writing


smarter code that makes decisions and adjusts behaviour during program
execution.

Technique Explanation

Constant Folding Replacing constant expressions with


precomputed values
Dead Code Elimination Removing code that will never run

Loop Unrolling Expanding loops to reduce overhead

Inlining Functions Replacing function calls with the function


body (avoids call overhead)
Strength Reduction Replacing expensive operations (like
multiplication) with cheaper ones (like
addition or bit-shifts)

Example: Constant Folding

110
Example: Dead Code Elimination

Enable Compile-Time Optimizations in GCC

Summary
In this session, we explored conditional statements in C, which are essential for
decision-making in programs. We started with the if, if-else, and nested if
structures, which allow code execution based on whether conditions are true or
false. Then we looked at the switch statement, a cleaner alternative to multiple if-
else chains when dealing with fixed values, and the ternary operator, a shorthand
version of if-else used for simple decisions.
We also introduced AI-assisted code generation tools that help programmers write
C code more efficiently. Tools like ChatGPT, GitHub Copilot, and others can
generate code from natural language prompts, suggest corrections, and even
optimize logic. Practical examples showed how AI can create basic programs like
checking if a number is even or odd. Finally, we covered debugging and
optimization techniques, emphasizing the use of tools like GDB for finding bugs
and applying compiler optimizations to enhance performance.

Check Your Knowledge


• Explain the syntax and working of the if statement in C. Provide an example.
• Differentiate between if-else and switch statements. When should each be
used?
• What is a nested if statement? Describe a real-life scenario where it might
be applied.

111
• List the rules and limitations of the switch statement in C. Why can't we use
floating-point expressions in switch?
• How does the ternary operator work in C? Rewrite a simple if-else using the
ternary operator.
• Discuss the advantages of using conditional statements in a program. How
do they improve program logic and flow?
• What is AI-assisted coding tools? How do they support a C programmer
during development?
• Mention three AI-based tools that can generate or assist in writing C code.
How do these tools integrate with IDEs?
• Explain the process of debugging in C. How do tools like GDB help in
identifying logical or runtime errors?
• What are some common techniques to optimize C code for performance?
How does compiler optimization work?
• Write a C program that checks whether a number entered by the user is
even or odd using if-else.
• Create a program that takes an integer input for day (1–7) and prints the
corresponding day name using a switch statement.
• Write a C program using nested if statements to check if a number is
positive, negative, or zero and also if it's even or odd.
• Use the ternary operator to determine and print the greater of two
numbers input by the user.
• Write a menu-driven calculator program using a switch statement with
options for addition, subtraction, multiplication, and division.

112
SESSION 6
LOOPS AND AI CODE GENERATION
SESSION OBJECTIVES
By the end of this session, students will be able to:
• Understand the concept and importance of loops in programming.
• Differentiate between for, while, and do-while loops.
• Apply loop control statements to manipulate loop flow.
• Write efficient loop-based programs in C.
• Explore how AI tools can assist in writing, debugging, and improving C code.

Introduction to Loops, for Loop, while Loop, do-while Loop


The versatility of the computer lies in its ability to perform a set of instructions
repeatedly. This involves repeating some portion of the program either a
specified number of times or until a particular condition is being satisfied. This
repetitive operation is done through a loop control instruction.

There are three looping statements


• While loop
• For loop
• Do while loop

Types of Loops in C:
• Entry-controlled loop: The condition is checked before execution.

• Exit-Controlled Loop: The condition is checked after the loop body is


executed.

Entry-Controlled Loop

• The condition is checked before the loop body executes.


• If the condition is false initially, the loop body doesn’t
execute at all.

Examples in C:

▪ for loop
▪ while loop

113
Exit-Controlled Loop

• The condition is checked after the loop body is executed.


• The loop body executes at least once, even if the
condition is false on the first check.

Example:
• do-while Loop

While Loop
The general form of while is as shown below.

Note the following points about while...


• The statements within the while loop would keep getting executed
till the condition being tested remains true. When the condition
becomes false, the control passes to the first statement that follows
the body of the while loop.
• In place of the condition there can be any other valid expression. So
long as the expression evaluates to a non-zero value the statements
within the loop would get executed.
• The initialization statement is executed only once.
• Then, the test expression is evaluated. If the test expression is
evaluated to false, the for loop is terminated.
• However, if the test expression is evaluated to true, statements
inside the body of the for loop are executed, and the update
expression is updated.

114
• Again, the test expression is evaluated.

The condition being tested may use relational or logical operators as


shown in the following examples:

The statements within the loop may be a single line or a block of


statements. In the first case, the braces are optional. For example,

This program initializes a counter i to 1 and uses a while loop to print


the numbers from 1 to 5 by incrementing i after each iteration until i
exceeds 5.

OUTPUT:

115
Do While Loop
The do-while loop is an exit control loop in C that executes the loop
body first, then checks the condition. This ensures that the loop runs
at least once, even if the condition is initially false.

SYNTAX:

Why is do-while Exit-Controlled?


• The loop executes first, then checks the condition.
• If the condition is true, it runs again.
• If the condition is false, it stops.

Program:
Here, even though i < 5 is false, "Hello" is printed once. This confirms
that do-while is exit-controlled.

116
Output:

For Loop
A for loop is a control structure that executes a block of code multiple times
until a specified condition is met.
• It is commonly used when the number of iterations is known.
• The loop checks the condition before executing the loop body.

The for loop consists of three parts:


▪ Initialization: This part initializes the loop variable (executes
only once).
▪ Condition: The loop checks this condition before each
iteration.
• If it's true, the loop continues;
• If false, the loop stops.
▪ Updation: After executing the loop body, the loop variable is
updated (incremented or decremented).

117
Basic Points on For Loop

Output

Points:
• The initialization, testing and incrementation of loop counter is done
in the for statement itself.
• Instead of i = i + 1, the statements i++ or i += 1 can also be used.
• Since there is only one statement in the body of the for loop, the pair
of braces have been dropped.

Here, the incrementation is done within the body of the for loop and not
in the for statement. Note that, in spite of this, the semicolon ( ; ) after
the condition is necessary.

118
This rule applies:
1.This works: Here the initialization is done in the declaration statement
itself, but still the semicolon before the condition is necessary.

2.This works: Here, neither the initialization, nor the incrementation is


done in the for statement, but still the two semicolons are
necessary.

3.This works:

• Here, the comparison as well as the incrementation is done through the


same expression, i++ < 5.
• Since the ++ operator comes after i, first comparison is done, followed
by incrementation. Note that it is necessary to initialize i to 0.

Nested For Loop


Understanding Nested for Loops
• A nested loop is a loop inside another loop.
• The outer loop controls the number of times the inner loop
executes.
• The inner loop runs completely for each iteration of the outer loop.

119
Program:

Execution Flow of Nested Loops


• Outer loop starts (i = 1)
o Enters inner loop (j = 1 to 2).
o Executes inner loop completely before going back to outer loop.
• Outer loop increments (i = 2)
o Enters inner loop (j = 1 to 2).
o Executes inner loop completely.
• Outer loop increments (i = 3)
o Enters inner loop (j = 1 to 2).
o Executes inner loop completely.
• Outer loop increments (i = 4), condition (i <= 3) fails
o Loop terminates.

Infinite Loops in C
What is an Infinite Loop?

An infinite loop is a loop that never terminates on its own. It keeps


executing the same block of code repeatedly, either intentionally or due to
a missing or incorrect condition.

In C programming, infinite loops are used when a program needs to run


continuously until a specific action occurs — for example, a menu system
waiting for user input, a background service, or an embedded system that
must always stay active.

120
Writing Infinite Loops in C
C offers several ways to write an infinite loop. Here are the most common
patterns:

Why Use Infinite Loops?


• Infinite loops are useful in situations where:
• The number of repetitions is unknown or undefined.
• The loop should run until a user action or external event stops it.
• You're building a system that needs to stay active (like device
firmware or servers).

while(1) Loop

• 1 always evaluates to true, so the loop never exits.

• This is one of the clearest and most readable ways to implement


an infinite loop.

for(;;) Loop

• The for loop here has no initialization, condition, or increment —


effectively turning it into an infinite loop.
• It's shorter but might be less readable to beginners.

do-while(1) Loop

121
• A do-while loop runs the block at least once, then continues as long
as the condition is true.
• Since 1 is always true, this loop becomes infinite as well.

Breaking Out of an Infinite Loop


Sometimes infinite loops need a way to exit based on a certain condition.
This is done using the break statement.

Here, the loop will only stop if the user enters -1.
This is a controlled infinite loop — common in menu systems or interactive
programs.

Risks of Unintentional Infinite Loops


Be careful when writing loops in C. Forgetting to update a condition or logic
error can lead to an unintended infinite loop, causing:

• High CPU usage


• Crashed or frozen programs
• Power drain on devices

Always ensure there's a valid exit condition if the loop isn’t meant to run
forever.

122
1. Right Half Pyramid Pattern in C
The right-half pyramid is nothing but a right-angle triangle whose
hypotenuse is in the right direction. We can print the right half pyramid
pattern using numbers, alphabets, or any other character like a star (*).

Below is an example for right half pyramid of star (*):

Program

123
Output:

Explanation:
• Outer loop: Controls the number of rows.
• Inner loop: Controls the number of columns (here in this problem stars
(*) printed in each row).
• Print * inside the inner loop row times.
• After the inner loop finishes (i.e., a row is complete), print a newline \n.

1. Full Pyramid Pattern in C


The Full Pyramid pattern looks similar to the Equilateral triangle. We can
see this as the combination of the Left Half and Right Half pyramids
patterns. The following example demonstrates how to print this pattern
using alphabets, numbers, or a star (*).

124
2. Inverted Left Half Pyramid Pattern in C
This pattern is the 180° flipped version of the left half pyramid pattern we
discussed earlier.
Example:

125
Output

Loop Control Statements in C Explained


Loop control statements in C are essential tools that allow programmers to
manage the flow of loops more effectively. The two primary loop control
statements are break and continue. Understanding how to use these statements
can help you write more efficient and readable code.

The break Statement


The break statement is used to exit a loop immediately, regardless of the
loop's condition. It is often used when a specific condition is met, and
continuing the loop is no longer necessary.

126
Syntax

Example

Explanation
In the example above, the loop prints numbers from 0 to 4. When i
becomes 5, the break statement is executed, and the loop terminates. This
is useful when you need to stop the loop based on a condition that occurs
within the loop.

The continue Statement


The continue statement skips the current iteration of the loop and
proceeds to the next iteration. It is useful when you want to skip certain
iterations based on a condition.

Syntax

Example

127
Explanation
In this example, the loop prints numbers from 0 to 9, except for 5. When i is
5, the continue statement is executed, skipping the printf statement for
that iteration. This allows you to bypass specific conditions within the loop
without terminating it.

Practical Applications
• break: Use the break statement to exit loops early when a condition is
met. This is particularly useful in search operations where you can stop
the loop once the desired element is found.
• continue: Use the continue statement to skip over certain iterations.
This is helpful in scenarios where you want to ignore specific values or
conditions within the loop.

Summary
• Loop control statements enhance the flexibility and control you have
over loops in C. By using break and continue effectively, you can write
more efficient and readable code.
• In the C programming language, there are times when you'll want to
change the looping behaviour. And the continue and the break
statements help you skip iterations and exit from loops under certain
conditions.

AI in Coding:
Modern AI tools like ChatGPT and GitHub Copilot help in generating C code by
understanding prompts, reducing syntax errors, suggesting logic, and even
explaining complex code snippets.

128
How AI Helps with Loops:
• Quick code generation for loops in any language
• Fixing loop logic errors (e.g., infinite loops)
• Optimizing performance (e.g., minimizing nested loops)
• Converting loop types (for ↔ while)
• Explaining loop flow visually or step-by-step

When using AI tools like ChatGPT for coding, you can just say:
"Generate a C program that uses a for loop to print numbers 1 to 10"
And it will give you:

Prompt: "Write a for loop in C to print even numbers from 2 to 20"


Output:

Fixing Loop Logic Errors (e.g., Infinite Loops)

Prompt: "My C program is stuck in an infinite loop. Here's the code. What's
wrong?"

int i = 1;
129
for (; i != 10; ) {
printf("%d ", i);
i += 2;
}

Explaining Loop Flow Visually or Step-by-Step

Prompt: "Explain this nested loop step-by-step"


for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 2; j++) {
printf("i=%d, j=%d\n", i, j);
}
}

AI Explanation:

130
Loop Flow:
• Outer loop runs 3 times (i = 1 to 3)
• For each i, inner loop runs 2 times (j = 1 to 2)
• Total = 3 x 2 = 6 iterations

Optimizing Performance (Minimizing Nested Loops)


Prompt: "Optimize this C code that counts duplicates in an array"
Original (Inefficient):

131
Converting Loop Types (for ↔ while)
Prompt: "Convert this for loop into a while loop"
for Loop:

Summary

Loops in programming allow code to be repeated based on conditions, making


programs efficient and concise.

• for Loop: Used when the number of iterations is known.


• while Loop: Checks the condition before entering the loop.
• do-while Loop: Executes the loop body at least once and then checks
the condition.
• Loop Control Statements:
o break: Terminates the loop immediately.
o continue: Skips the current iteration and proceeds to the next.
o goto: Jumps to a labelled statement (use with caution).

132
Check Your Knowledge
• What is the difference between entry-controlled and exit-controlled loops?
Give examples.
• Can we replace a for loop with a while loop in all situations? Justify with
an example.
• What are nested loops? What are the time complexity implications of using
them?
• Explain how break and continue affect nested loops.
• How does an infinite loop impact memory and CPU usage? How can such a
loop be safely terminated?
• How can AI-generated code sometimes lead to logical errors, even if
syntactically correct?
• Write a C program that prompts the user to enter a positive integer. It then
calculates and prints the factorial of that number using a while loop.
• Write a C program that calculates and prints the sum of cubes of even
numbers up to a specified limit (e.g., 20) using a loop.
• Write a C program that implements a program to check if a given number is a
palindrome using a while loop.
• Write a C program to find and print the first 10 Fibonacci numbers using a
while loop.
• Write a C program that prompts the user to enter a positive integer. Use a
while loop to print the multiplication table for that number up to 10.
• Write a program in C to display a pattern like a right-angle triangle using an
asterisk.

The pattern like:

133
SESSION 7
ARRAYS (ONE-DIMENSIONAL & TWO-DIMENSIONAL

SESSION OBJECTIVES
• By the end of this session, students will be able to:
• Understand the concept and purpose of arrays in C programming.
• Declare, initialize, and access elements in one-dimensional (1D) arrays.
• Perform basic operations using 1D arrays, such as input/output, searching, and summing
elements.
• Understand the structure and use of two-dimensional (2D) arrays.
• Declare, initialize, and manipulate elements in 2D arrays using nested loops.
• Apply arrays to solve simple real-life problems programmatically.

Introduction to Arrays in C++


An array in C is one of the most used data structures in C programming. It is a
simple and fast way of storing multiple values under a single name.
An array in C is a fixed-size collection of similar data items stored in contiguous
memory locations. It can be used to store the collection of primitive data types
such as int, char, float as well as derived and user-defined data types like pointers
and structures. Arrays simplify the management and manipulation of large
volumes of data, and their elements are accessed using index numbers, starting
from 0.

134
Why we Need Arrays?
The need for arrays arises when handling large amounts of related data. For
example, imagine storing the marks of 100 students. Instead of creating 100
separate variables such as mark1, mark2, ..., mark100, we can simply use a single
array like marks[100]. This approach not only reduces code complexity but also
makes it easier to manage, access, and manipulate the data efficiently.

Types of Arrays in C
There are two types of arrays based on the number of dimensions it has. They are
as follows:
• One Dimensional Arrays (1D Array)
• Two dimensional Arrays (2D arrays)

One Dimensional Array in C


The One-dimensional arrays, also known as 1-D arrays in C are those arrays that
have only one dimension.

Array Declaration
In C, we must declare the array like any other variable before using it.
We can declare an array by specifying its name, the type of its elements, and
the size of its dimensions. When we declare an array in C, the compiler
allocates a memory block of the specified size to the array name.

135
Array Initialization
In C, initialization is the process of assigning an initial value to a variable. When
an array is declared or memory is allocated for it, its elements initially contain
garbage values. Therefore, it is important to initialize the array with meaningful
values before using it. Array initialization can be done in multiple ways,
primarily through compile-time initialization, where values are assigned at the
time of declaration, and run-time initialization, where values are assigned
during program execution. Proper initialization ensures reliable and predictable
behaviour of the program.

There are multiple ways in which we can initialize an array in C.


• Compile-time initialization
• Run time initialization

Compile Time Initialization


• In this method, we initialize the array along with its declaration.
• We use an initializer list to initialize multiple elements of the array.
• An initializer list is the list of values enclosed within braces { }
separated by a comma.

int arr[5] ={10,20,30,40,50};

136
Run-Time Initialization
Run-time initialization refers to assigning values to array elements during
the execution of the program, typically through user input using
functions like scanf or through logical operations within the program.
In this approach, the values to be stored in the array are not known in
advance. Instead, they are provided or calculated as the program runs.
Although memory for the array is allocated at compile time, the actual
values are set during run time using loops or input mechanisms. This
method is useful when the data to be stored is dynamic or based on user
interaction.

137
Access Array Elements
We can access any element of an array in C using the array subscript
operator [ ] and the index value i of the element.
array_name [index];

One thing to note is that the indexing in the array always starts with 0,
i.e., the first element is at index 0 and the last element is at N – 1
where N is the number of elements in the array.

138
Two-Dimensional Array in C
A Two-Dimensional array or 2D array in C is an array that has exactly two
dimensions. They can be visualized in the form of rows and columns organized
in a two-dimensional plane.
A two-dimensional array or 2D array, is the simplest form of the
multidimensional array. We can visualize a two-dimensional array as one-
dimensional arrays stacked vertically, forming a table with ‘m’ rows and ‘n’
columns. In C, arrays are 0-indexed, so the row number ranges from 0 to (m-1)
and the column number ranges from 0 to (n-1).

Declaration of 2D Array
A 2D array with m rows and n columns can be created as:
type arr_name[m][n];

• type: Type of data to be stored in each element.


• arr_name: Name assigned to the array.
• m: Number of rows.
• n: Number of columns.

For example, we can declare a two-dimensional integer array with the


name ‘arr’ with 10 rows and 20 columns as:

139
Example:

Initialization of 2D arrays

Explanation:
We can initialize a 2D array by using a list of values enclosed inside ‘{ }’ and
separated by a comma as shown in the example below:

The elements will be stored in the array from left to right and top to bottom. So,
the first 4 elements from the left will be filled in the first row, the next 4 elements
in the second row, and so on. This is clearly shown in the second syntax where
each set of inner braces represents one row.

In array initialization, the number of rows can be omitted; the compiler will
deduce it based on the number of values and the specified number of columns.
So, the below declaration is valid.

type arr_name[][n] = {…values…};

It is still compulsory to define the number of columns.


140
Example:

This program declares and initializes a 2D integer array with 2 rows and 4
columns. Each row is defined using inner braces, and the compiler automatically
infers the number of rows based on the initialization.

Accessing 2D Array Elements


You access elements in a 2D array by specifying the row and column indices:

Accessing a Two-Dimensional Array


To access a two-dimensional array, two index values are used: the first index
specifies the row number, and the second index specifies the column number.
This allows you to directly refer to any specific element in the array using the
Syntax:
array[row][column].

Here’s an example that demonstrates how to access and assign values in a two-
dimensional array using indices:

141
Since array indexes are integer value, hence you can also wire a loop to access
two-dimensional array. Two-dimensional array needs two index values to access
any array element. Therefore, you need two loops. One outer loop to access for
each row of the matrix, second loop for each column of the matrix.

142
Program to Print 2-D array

Summary
• An array in C is a collection of elements of the same data type, stored in
contiguous memory locations.
• Arrays can be one-dimensional (1D), like a list, or two-dimensional (2D), like
a table (matrix).
• Array elements are accessed using indices starting from 0.
A 1D array holds multiple values in a single row.
• Declared as:

• Common operations: traversing, updating, finding max/min, summing


elements.

A 2D array is like a matrix with rows and columns.


• Declared as:

• Accessed using two indices (row and column).

143
Check Your Knowledge
• What is an array in C? Why and when would you use one?
• How is memory allocated for arrays in C?
• What are the limitations of using arrays in C?
• How is a 1D array different from a 2D array?
• What is the default initial value of elements in an uninitialized array?
• Can the size of an array be changed at runtime in C? Why or why not?
• Write a program in C to read n number of values in an array and display them
in reverse order.
• Write a program in C to count the total number of duplicate elements in an
array.
Test Data:
Input the number of elements to be stored in the array: 3
Input 3 elements in the array:
element - 0: 5
element - 1: 1
element - 2: 1

Expected Output:
The total number of duplicate elements found in the array is: 1
• Write a program in C to print all unique elements in an array.
Test Data :
Print all unique elements of an array:
------------------------------------------
Input the number of elements to be stored in the array: 4
Input 4 elements in the array :
element - 0: 3
element - 1: 2
element - 2: 2
element - 3: 5
Expected Output :
The unique elements found in the array are: 3 5

144
• Write a program in C to merge two arrays of the same size, sorted in
descending order.
Test Data:
Input the number of elements to be stored in the first array: 3
Input 3 elements in the array :
element - 0: 1
element - 1: 2
element - 2: 3
Input the number of elements to be stored in the second array: 3
Input 3 elements in the array:
element - 0: 1
element - 1: 2
element - 2: 3
Expected Output :
The merged array in descending order is : 3 3 2 2 1 1
• Write a program to find the transpose of a matrix.
• Write a program to multiply two matrices.

145
SESSION 8
POINTERS AND AI CODE GENERATION
SESSION OBJECTIVES
By the end of this session, you will be able to:
• Understand what pointers are and how they work in memory.
• Declare and use pointers for different data types.
• Access and manipulate array elements using pointers.
• Understand the relationship between arrays and pointers.
• Perform dynamic memory allocation using malloc(), calloc(), realloc(), and free().
• Avoid common pointer-related issues like wild pointers, dangling pointers, and memory
leaks.

POINTERS
Pointers are powerful features of C and C++ programming. Before we learn
pointers, let's learn about addresses in C programming.

Address in C
If you have a variable var in your program, &var will give you its address in
the memory. We have used address numerous times while using
the scanf() function.

Here, the value entered by the user is stored in the address of var variable.
Let's take a working example.

Note: You will probably get a different address when you run the above code.
146
C Pointers
A pointer is a variable that stores the memory address of another variable.
Instead of holding a direct value, a pointer holds an address pointing to a
location in memory.

POINTER DECLARATION AND INITIALIZATION


A pointer variable must be declared before use:
Pointer Syntax:
data_type *pointer_name;

Example:

Here, we have declared a pointer p of int type. You can also declare pointers
in these ways.

Here, we have declared a pointer p1 and p2.

Assigning addresses to Pointers


Let's take an example.

Here, 5 is assigned to the c variable. And the address of c is assigned to


the pc pointer.

Get Value of Thing Pointed by Pointers


To get the value of the thing pointed by the pointers, we use the * operator. For

147
example:

• Here, the address of c is assigned to the pc pointer. To get the value stored
in that address, we used *pc.
• Note: In the above example, pc is a pointer, not *pc. You cannot and should
not do something like *pc = &c;
• By the way, * is called the dereference operator (when working with
pointers). It operates on a pointer and gives the value stored in that pointer.

Changing Value Pointed by Pointers


Let's take an example.

We have assigned the address of c to the pc pointer. Then, we changed the value of
c to 1. Since pc and the address of c is the same, *pc gives us 1. Let's take another
example.

We have assigned the address of c to the pc pointer. Then, we changed *pc to 1


using *pc = 1;. Since pc and the address of c is the same, c will be equal to 1.
148
Let's take one more example.

Initially, the address of c is assigned to the pc pointer using pc = &c;. Since c is


5, *pc gives us 5. Then, the address of d is assigned to the pc pointer using pc = &d;.
Since d is -15, *pc gives us -15.

The format specifier %p is used in C (and C-like languages) to print a pointer


address—that is, the memory address that a pointer variable holds.

Here's a breakdown:
• %p stands for "pointer".
• When you use printf("%p", ptr);, it prints the address stored in the pointer
variable ptr.
• The output is typically in hexadecimal format, often prefixed with 0x.

Size: 8 bytes
• On a 64-bit system, pointers are 8 bytes (64 bits) in size.
• That means any pointer, whether it's pointing to an int, char, float, or a
custom structure, occupies 8 bytes in memory.
• This size allows it to hold any address within a 64-bit address space.

149
Example: Working of Pointers
Let's take a working example.

150
Explanation of the program
1. int* pc, c;

Here, a pointer pc and a normal variable c, both of type int, is


created. Since pc and c are not initialized at initially, pointer pc points
to either no address or a random address. And, variable c has an
address but contains random garbage value.

2. c = 22;

This will assign 22 to the variable c. That is, 22 is stored in the


memory location of variable c.

3. pc = &c;

This assigns the address of variable c to the pointer pc.

4. c = 11;

This assign 11 to variable c.

151
5. *pc = 2;

This changes the value at the memory location pointed by the


pointer pc to

Memory Representation:
int num = 10;
int *ptr = &num;

Example Program:

Logic Breakdown:
• num is an integer variable initialized with 10.
• ptr is a pointer that stores the address of num.

The program prints:


▪ The value of num.
▪ The memory address of num.
▪ The memory address stored in ptr.
▪ The value at the memory location stored in ptr (dereferencing).

152
Common mistakes when working with pointers
Suppose you want pointer pc to point to the address of c. Then,

Here's an example of pointer syntax beginners often find confusing.

Why didn't we get an error when using int *p = &c;?


It's because

is equivalent to

In both cases, we are creating a pointer p (not *p) and assigning &c to it. To
avoid this confusion, we can use the statement like this:

153
Relationship Between Arrays and Pointers
An array is a block of sequential data. Let's write a program to print the addresses
of the array elements.

• There is a difference of 4 bytes between two consecutive elements of the


array x. It is because the size of int is 4 bytes (on our compiler).
• Notice that, the address of &x[0] and x is the same. It's because the variable
name x points to the first element of the array.

Relation between Arrays and Pointers


From the above example, it is clear that &x[0] is equivalent to x. And, x[0] is
equivalent to *x.

Similarly,
• &x[1] is equivalent to x+1 and x[1] is equivalent to *(x+1).

154
• &x[2] is equivalent to x+2 and x[2] is equivalent to *(x+2).
• ...
• Basically, &x[i] is equivalent to x+i and x[i] is equivalent to *(x+i).

Example 1: Pointers and Arrays

When you run the program, the output will be:

Here, we have declared an array x of 6 elements. To access elements of the array,


we have used pointers. In most contexts, array names decay to pointers. In simple
words, array names are converted to pointers. That's the reason why you can use
pointers to access elements of arrays. However, you should remember that pointers
and arrays are not the same. There are a few cases where array names don't decay
to pointers.

155
Example 2: Arrays and Pointers

In this example, &x[2], the address of the third element, is assigned to


the ptr pointer. Hence, 3 was displayed when we printed *ptr.
And, printing *(ptr+1) gives us the fourth element. Similarly, printing *(ptr-1) gives
us the second element.

C Pass Addresses and Pointers


In C programming, it is also possible to pass addresses as arguments to functions.
To accept these addresses in the function definition, we can use pointers. It's
because pointers are used to store addresses. Let's take an example:

156
Example: Pass Addresses to Functions

The addresses of num1 and num2 are passed to the swap() function
using swap(&num1, &num2);. Pointers n1 and n2 accept these arguments in the
function definition. When *n1 and *n2 are changed inside
the swap() function, num1 and num2 inside the main() function are also changed.
Inside the swap() function, *n1 and *n2 swapped. Hence, num1 and num2 are
also swapped. Notice that swap() is not returning anything; its return type is void.

Example 2: Passing Pointers to Functions

Here, the value stored at p, *p, is 10 initially. We then passed the pointer p to the
addOne() function. The ptr pointer gets this address in the addOne() function.

157
Inside the function, we increased the value stored at ptr by 1 using (*ptr)++;. Since
ptr and p pointers both have the same address, *p inside main() is also 11.

Pointer Arithmetic
What is Pointer Arithmetic?
Pointer arithmetic refers to performing arithmetic operations (like +, -, ++, --) on
pointers. This is especially useful when working with arrays or dynamic memory.
Because pointers "point to" memory addresses, arithmetic operations on them
manipulate the memory address they store, taking into account the size of the
data type they point to.
Basic Pointer Arithmetic Operations
1. Increment: ptr++
What it does: Moves the pointer to the next element in memory. How: It
increases the address stored in the pointer by sizeof(data_type).

Example:

If sizeof(int) is 4 bytes, ptr++ moves the pointer by 4 bytes.

2. Decrement: ptr--
• What it does: Moves the pointer to the previous element in memory.

Example:

Again, the pointer moves back by sizeof(data_type) bytes.

3. Addition: ptr + n
• What it does: Moves the pointer forward by n elements.
• Note: This doesn't change the original pointer unless assigned.

158
Example:

4. Subtraction: ptr - n
• What it does: Moves the pointer backward by n elements.

Example:

Important Notes
• Pointer arithmetic is type-aware:
▪ If ptr is of type int *, ptr + 1 actually adds sizeof(int) to the
address.
▪ If it's a char *, then ptr + 1 adds just 1 byte.

o You can also subtract two pointers pointing into the same array:

Out-of-bound pointer arithmetic (e.g., going beyond an array) leads


to undefined behaviour.

Visual Example:

159
Arithmetic Operations on Pointers
• Pointer arithmetic includes: Increment (ptr++) – Moves the pointer to
the next memorylocation.Decrement (ptr--) – Moves the pointer to
the previous memory location.
• Addition (ptr + n) – Moves the pointer forward by n locations.
Subtraction (ptr - n) – Moves the pointer backward by n locations.

Types of Pointers in C
Depending on the parameters, pointers can be divided into a wide variety of
types. The following types of pointers are based on the type of variable that is
kept in the memory location that the pointer is pointing to.

Integer Pointers
The memory location of an integer variable is stored in an integer pointer.

Syntax

Example of Integer Pointers in C


160
NULL POINTER
A NULL pointer is a special pointer that does not point to any valid memory
location. It is typically used to indicate that a pointer is not assigned to a
valid object or memory.

Purpose of NULL Pointers


• Indicates an Uninitialized Pointer: Helps prevent accidental access to
garbage memory.
• Used in Error Handling: Functions often return NULL to indicate
failure.

Declaring a NULL Pointer


int *ptr = NULL; // ptr is a NULL pointer

161
PROGRAM: NULL Pointer Usage

Output:

Logic Breakdown:
• Declare a pointer ptr and initialize it to NULL.
• Use an if condition to check if the pointer is NULL.
• Print a message indicating whether the pointer is NULL or not.

VOID POINTER
A void pointer (also known as a generic pointer) is a pointer that has no
specific data type associated with it. It can hold the address of any data
type, making it flexible for general-purpose programming.

Declaration and Initialization


void *ptr; // Declaring a void pointer
int num = 10;
ptr = &num; // Assigning address of an integer variable
Here, ptr can store the address of num, but since it is a void pointer,
dereferencing it requires typecasting.

Example Program: Using Void Pointers

162
Logic Breakdown:
1. Declare a void *ptr that can point to any data type.
2. Assign different variables (int, float, char) to ptr.
3. Before dereferencing, explicitly typecast ptr to the correct data type.

CONSTANT POINTER
A constant pointer is a pointer whose value (i.e., the memory address it
holds) cannot be changed after initialization. Once a constant pointer is
assigned an address, it must always point to the same memory location.

Syntax:

Here, ptr is a constant pointer to an integer, meaning it must always point


to num1. However, we can modify the value stored at num1 via *ptr.

163
Example Program:

Key Points:
▪ Cannot change the address stored in ptr.
▪ Can change the value at the address using *ptr.
▪ ptr = &num2; results in a compilation error.

Pointer to Pointer
A pointer to a pointer, also called a double pointer, is a variable that stores
the address of another pointer. This allows for multiple levels of indirection
and is commonly used in complex data structures, dynamic memory
management, and function arguments that modify pointers.

How It Works
• x contains the value 100
• ptr contains the address of x
• pptr contains the address of ptr

164
Accessing Values:

Use Cases:
• Dynamic memory allocation for multi-dimensional arrays
• Modifying a pointer inside a function
• Parsing command-line arguments (char **argv)
• Working with linked lists and trees

Wild Pointer
A wild pointer is a pointer that has been declared but not initialized, and
thus it points to an unknown or random memory location. Dereferencing
such a pointer can lead to unpredictable results and may cause a program
to crash.

Issues Caused by Wild Pointers:


• Program crashes
• Memory corruption
• Security vulnerabilities
• Segmentation faults

165
Best Practices to Avoid Wild Pointers:
• Always initialize pointers:
int *ptr = NULL;

• Only dereference after proper assignment


• Use static analyzers to detect uninitialized pointers

Array of Pointers
An array of pointers is a collection where each element is a pointer. This
allows you to store references to multiple variables, arrays, or even strings,
providing greater flexibility in memory management.

Syntax:

Accessing Data:

Array of Strings Example:

Use Cases:
• Arrays of strings or variable-length arrays
• Jagged (non-uniform) multi-dimensional arrays
• Dynamic data structures like lists of arrays or arrays of objects

166
Array Pointer
The initial element of an array may be referenced by array pointers.

Syntax

Example of Array Pointer in C

Pointer to an Array
A pointer to an array is a pointer that holds the address of an entire array
rather than just a single element. This allows efficient traversal and
manipulation of the array using pointer arithmetic.

167
Key Concept:
• When an array is declared, its name acts as a pointer to the first
element.
• However, a pointer to an array explicitly stores the address of the
whole array.

Syntax:

Here, ptr is a pointer to an array of size elements.

Example Program: Pointer to an Array

Output:

Logic Breakdown:
• Declaring an Array
• int arr[5] = {10, 20, 30, 40, 50};
• Creates an array of 5 integers.
• Declaring a Pointer to an Array
• int (*ptr)[5] = &arr;
• ptr stores the address of the entire array, not just the first
element.

• Accessing Array Elements


• Using (*ptr)[index], we can retrieve elements from the array.

168
Dynamic Memory Allocation (DMA)
Dynamic Memory Allocation (DMA) in C is the process of allocating memory during
runtime using pointers. This allows a program to allocate memory based on the
actual requirements during execution rather than during compile time. The
memory is allocated using library functions like malloc(), calloc(), realloc(), and
free(). Here's a breakdown of each concept, including logic and example code for
each type of dynamic memory allocation:

DMA for Variables


In this case, memory is allocated dynamically for a single variable.
Functions used:
• malloc(size_t size): Allocates a block of memory of size bytes and
returns a pointer to it.
• free(pointer): Frees the memory that was allocated using malloc or
calloc.

How it works:
• A pointer is declared, and memory for the variable is allocated
dynamically using malloc().
• Once done with the memory, free() is called to deallocate it and
prevent memory leaks.

169
Example

Output:

Logic Breakdown:
1. malloc(sizeof(int)): Allocates memory for one integer
(sizeof(int) returns the size of an integer in bytes).
2. *ptr = 42;: Assigns the value 42 to the dynamically allocated
memory.
3. free(ptr);: Frees the memory once we're done with it,
preventing memory leaks.

Dynamic memory allocation allows programs to request memory during


runtime instead of compile time. The stdlib.h library provides four key
functions for memory management:

1. malloc() - Memory Allocation


The malloc() function dynamically allocates a specified number of bytes
and returns a pointer to the allocated memory. The allocated memory
contains garbage values (uninitialized memory).

170
Syntax:

Example:

2. calloc() - Continuous Allocation


The calloc() function allocates memory for multiple elements and
initializes them to zero.

Syntax:

Example:

171
Output

3. realloc() - Resize Memory Block


The realloc() function is used to change the size of previously allocated
memory.

Syntax:

Example:

4.

free() - Deallocate Memory


The free() function releases dynamically allocated memory, preventing
memory leaks.

Example:

172
Main Logic:
• First, processData is called with the printElement callback to
print each element of the array.
• Then, we loop through the array and use the sumElement
callback to accumulate the sum of the elements.
• We pass different behaviour (printing or summing) to the
same processData function by changing the callback
function.

DMA for Arrays


Dynamic memory allocation can also be used for arrays. This is
particularly useful when the size of the array is not known
beforehand, and it can change during program execution.
How it works:
• Allocate memory for an array using malloc() or calloc().
• After using the array, free the allocated memory.

Example Program:

173
Output:

Logic Breakdown:
1. malloc(n * sizeof(int)): Allocates memory for n integers, where
n is input by the user.
2. arr[i]: Array elements are accessed and modified just like in a
statically declared array.
3. free(arr): Frees the memory allocated for the array.

DMA for Structures


Dynamic memory allocation is often used for structures when you
don't know how many structures you will need or when the number
of structures can vary during runtime.
How it works:
• Allocate memory for one or more structures using malloc() or
calloc().
• Use pointers to access and modify the structure’s members.
• Free the memory once done.

174
Example Program:

Output:

Logic Breakdown:
• malloc(sizeof(struct Student)): Allocates memory for one struct
Student object. The size of the structure is obtained using
sizeof(struct Student).
• studentPtr->name and studentPtr->age: Access the structure's
members using the pointer (studentPtr).
• free(studentPtr): Frees the memory allocated for the structure.

175
AI Code Generation
PROMPT 1: Basic Pointer Access
Prompt: Write a C program to:
• Declare an integer variable.
• Declare a pointer and assign it the address of the variable.
• Print the value and address of the variable using both the variable
and the pointer.

Answer:

PROMPT 2: Swap Two Numbers Using Pointers


Prompt: Write a function void swap(int *a, int *b) that swaps the values of
two integers using pointers.

Answer:

176
PROMPT 3: Dynamic Array Using malloc()
Prompt: Write a C program to:
• Dynamically allocate memory for an integer array of size n (e.g., 5).
• Initialize and print the elements.
• Free the memory.
Answer:

177
PROMPT 4: Pointer to Pointer
Prompt: Create a program that uses a pointer to a pointer to store and
print the value of an integer.
Answer:

PROMPT 5: Pointer with Struct


Prompt: Define a struct Person with name and age. Create a pointer to a
struct and access its members using ->.
Answer:

178
Summary
Pointers are powerful features in C that allow direct access and manipulation of
memory. A pointer stores the address of another variable, and using the
dereference operator (*), you can access or modify the value at that address.
Pointers are closely related to arrays, as the array name itself acts like a pointer to
its first element, allowing for efficient array traversal and manipulation.
Understanding pointers also lays the foundation for dynamic memory allocation,
where functions like malloc(), calloc(), realloc(), and free() are used to manage
memory at runtime. Proper use of pointers enables flexible and efficient
programming, but care must be taken to avoid issues like memory leaks, dangling
pointers, or wild pointers.

Check Your Knowledge:

• What is a pointer? How do pointers differ from regular variables?


• What is a NULL pointer? Why is it used?
• What is the size of a pointer? Does it vary with data type?
• What are wild pointers?
• What is the difference between *ptr and &ptr?
• How is pointer arithmetic performed?
• How are arrays and pointers related in C?
• Explain the difference between a pointer to an array and an array of
pointers.
• What functions are used for dynamic memory allocation in C?
• What is the difference between malloc(), calloc(), realloc(), and free()?
• What happens if you don't free() dynamically allocated memory?
• What is a memory leak, and how can it be prevented?
• Can you explain what void* means in the context of memory allocation?
• What are the best practices for dynamic memory management?
• Write a C program to swap two numbers using pointers.
• Implement a function that returns the maximum of two numbers using
pointers.
• Write a program to reverse an array using pointers.

179
• Create a function that counts the number of vowels in a string using pointer
traversal.
• Given an array, print all elements using pointer notation.
• Write a function that takes a 2D array and prints its elements using pointers.
• Dynamically allocate an array of integers, take input, and print the sum of
all elements.
• Implement a simple version of strcpy() using dynamic memory allocation.
• Create a dynamic 2D matrix (MxN), take input, print it, and deallocate the
memory.
• Create a program that dynamically reads a string of unknown length from
the user (like with getline() behavior).

180
SESSION 9
FUNCTIONS AND AI CODE GENERATION
SESSION OBJECTIVES
The objective of this module is to provide a foundational understanding of functions in C
programming, covering their definition, usage, types, and scope. Learners will explore recursive
functions and understand how they differ from iterative approaches. Additionally, the module
introduces the concept of AI-assisted code generation, demonstrating how artificial intelligence
tools can aid in writing and optimizing function-based code in C.

Introduction to Functions
• A function is a self-contained block of statements that performs a coherent
task of some kind.
• Every C program can be thought of as a collection of these functions.
• Using a function is something like hiring a person to do a specific job for
you.
• A program is just a set of definitions of variables and functions.
Communication between the functions is by arguments and values returned
by the functions, and through external variables.

Syntax of Functions in C
The syntax of function can be divided into 3 aspects:
• Function Declaration
• Function Definition
• Function Calls

Function Declarations/Function prototype


In a function declaration, we must provide the function name, its return type,
and the number and type of its parameters.
A function declaration tells the compiler that there is a function with the given
name defined somewhere else in the program.
181
Syntax:
return_type name_of_the_function (parameter_1, parameter_2);
The parameter name is not mandatory while declaring functions. We can also
declare the function without using the names of the data variables.

Function Definition
The function definition consists of actual statements that are executed when the
function is called (i.e., when the program control comes to the function). A C
function is generally defined and declared in a single step because the function
definition always starts with the function declaration, so we do not need to declare
it explicitly.

Function Call
A function call is a statement that instructs the compiler to execute the function.
We use the function name and parameters in the function call.

182
• In the below example, the first sum function is called and 10,30 are passed
to the sum function. After the function call sum of a and b is returned and
control is also returned back to the main function of the program.
• A function call is necessary to bring the program control to the function
definition. If not called, the function statements will not be executed.

2. Returning a value: Returning a value is the step where the calculated


value after the execution of the function is returned. Exiting the function
is the final step where all the allocated memory to the variables,
functions, etc is destroyed before giving full control back to the caller.

Example Program:

183
This C program defines a sum function that adds two integers, then calls it in
main, storing the result in add and printing the sum.

Some important points:


• A C program is a collection of one or more functions. If a C program
contains only one function, it must be main( ).
• If a C program contains more than one function, then one (and only
one) of these functions must be main( ), because program execution
always begins with main( )
• There is no limit on the number of functions that might be present in a
C program.
• Each function in a program is called in the sequence specified by the
function calls in main( ).
• After each function has done its thing, control returns to main( ). When
main( ) runs out of statements and function calls, the program ends.
• A function can be called any number of times.
• The order in which the functions are defined in a program and the order
in which they are called need not necessarily be the same.
• A function can be called from another function, but a function
• cannot be defined in another function.

Types of Functions
There are two types of functions in C:

184
1. Library Function:
It is also referred to as a “built-in function”. A compiler package already
exists that contains these functions, each of which has a specific meaning
and is included in the package.
Built-in functions have the advantage of being directly usable without being
defined, whereas user-defined functions must be declared and defined
before being used.

Example: pow(),sqrt(),strcmp(),strcpy() etc.

2. User-Defined Functions
• Functions that the programmer creates are known as User-Defined
functions. User-defined functions can be improved and modified
according to the needs of the programmer.
• Whenever we write a function that is case-specific and is not defined
in any header file, we need to declare and define our own functions
according to the syntax.

Passing Parameters to Functions


1. The data passed when the function is being invoked is known as the
Actual parameters.
2. In the below program, 10 and 30 are known as actual parameters.
3. Formal Parameters are the variable and the data type as mentioned
in the function declaration.
4. In the below program, a and b are known as formal parameters.

185
Program:

Output:

Explanation:
Function Declaration: The line void print(); is a function prototype that
declares the print function, indicating that it takes no parameters and does
not return any value.
Main Function: Inside the main() function:

• The print() function is called, which executes the code within the
print() function definition.

186
• The print() function prints "Welcome to Cranes Varsity" on the
screen.
• After calling the print() function, the program prints "let us learn C
Programming" on the screen.

Function Definition:The print() function is defined later in the program with


the actual code that gets executed when the function is called. It prints the
message "Welcome to Cranes Varsity".

PROGRAM 2: program that calculates all arithmetic operation through


functions

OUTPUT:

187
We can pass arguments to the C function in two ways:

• Pass by Value
• Pass by Reference

1. Pass by Value:
• Parameter passing in this method copies values from actual
parameters into formal function parameters.
• As a result, any changes made inside the functions do not reflect in
the caller’s parameters.
Program:

Output:

188
Explanation:
Function Definition (modifyvalue):
• Takes an integer num, doubles it, prints the modified value, and
returns it.

Main Function:
• Prompts user for input and stores it in num.
• Prints the value of num before calling modifyvalue().
• Calls modifyvalue(num), which modifies a copy of num and prints the
doubled value, returning the modified value.
• Prints the original value of num after the function call (unchanged).

Pass by Reference
• Pass by reference is done by passing the address of the variable (using
pointers) to a function.
• This allows the function to directly modify the original value of the
argument, rather than working with a copy of it.
• The function gets the address (reference) of the variable, allowing it to
modify the original variable directly.

189
Program:

Output:

Scope of variable
A scope in any programming is a region of the program where a defined variable
can have its existence and beyond that variable, it cannot be accessed. There are
three places where variables can be declared in C programming language −

• Inside a function or a block, which is called local variables.


• Outside of all functions, which are called global variables.
Let us understand local and global variables.
Local Variables
Variables that are declared inside a function or block are called local variables.
They can be used only by statements that are inside that function or block of
code. Local variables are not known to functions outside their own. The following
example. shows how local variables are used. Here all the variables a, b, and c are
local to main() function.

190
Global Variables
Global variables are defined outside a function, usually on top of the program.
Global variables hold their values throughout the lifetime of your program, and
they can be accessed inside any of the functions defined for the program. A global
variable can be accessed by any function. That is, a global variable is available for
use throughout your entire program after its declaration.

The following program shows how global and local variables are used in a
program.

Storage Class Specifiers in C


Storage class specifiers control a variable:
• Storage: Where the variable is stored (e.g., stack, data segment, CPU
registers)
• Scope: Where the variable is accessible within the program
• Lifetime: How long the variable exists during program execution

Memory Segments Overview


Stack:
A part of RAM managed by the CPU during program execution.

191
Stores:
• Function calls
• Function arguments
• Local variables
• Return addresses

CPU Registers:
Small, high-speed memory locations within the CPU. Used to store temporary
data. Accessing data from registers is faster than accessing from RAM. Helps
improve execution speed.

1. auto Storage Class Specifier


It is the default storage class for all local variables declared inside a function or
block. Implicitly applied (you don’t need to write auto—it’s assumed).

• Storage: Stack
• Scope: Local to the block or function
• Lifetime: Created when the function is called, destroyed when the function
ends (along with the stack frame)
• Uninitialized Variables: Contain garbage values
• Access: Cannot be accessed outside the block

Syntax:
auto datatype var_name;

192
Output:

2. register Storage Class Specifier


Suggests to the compiler that the variable should be stored in a CPU register
instead of RAM. The compiler may ignore the suggestion if no registers are
available. Faster access due to direct CPU access. Cannot use the address-of
operator (&) on a register variable, since it may not have a memory address.
• Storage: Register (if available; otherwise, RAM)
• Scope: Local to the block
• Lifetime: Same as auto (within the block or function)

Syntax:
register datatype var_name;

Program

Output:

193
3. Static Storage Class Specifier
The static keyword modifies both the scope and lifetime of a variable. It retains
the value of the variable across multiple function calls.
• Limits Scope:
o If declared inside a function, the variable has local scope but retains
its value between calls.
o If declared outside a function, the variable’s access is restricted to the
file (i.e., file scope).
• Storage: Data Segment
• Lifetime: Entire program execution
• Scope: Depends on where the variable is declared

Explanation:
“Retain” means the variable does not lose its value when the function exits.
Useful when you need to preserve state between function calls.

Memory Segments in Program Execution:


• Code Segment: Stores compiled code (instructions)
• Data Segment: Initialized Data Segment: Stores static variables with explicit
values
• Uninitialized Data Segment (BSS): Stores static variables without initial
values (default to 0)
• Heap: Dynamic memory (via malloc, calloc, etc.)
• Stack: Function call-related data

194
Program

Output:

4. extern Storage Class Specifier


Used to declare a variable or function that is defined in another file.
Tells the compiler: “The actual definition exists elsewhere.” Commonly used for
global variables shared across multiple files.
• Scope: Global
• Lifetime: Entire program execution
• Storage: Data Segment

195
Program:

What is Recursion?
Recursion in C is a technique where a function calls itself to solve smaller
instances of the same problem. Recursion typically consists of two components:
• Base case: This is the condition where the recursion stops.
• Recursive case: This is the part where the function calls itself to break the
problem into smaller subproblems.
Recursion is typically used to solve problems that can be broken down into
smaller instances of the same problem, like factorial, Fibonacci numbers, tree
traversals, etc.

How Recursion Works


When a function calls itself:
• A new instance of the function is created on the call stack.
• The program keeps adding instances of the function to the stack until it
reaches the base case.
• Once the base case is met, the function starts returning the values, and the
stack unwinds, providing the solution.

196
The recursive process involves:
• Recursive call: The function calls itself.
• Base case: A condition that stops further recursion and starts returning
values.

Program: Factorial of a number:

Output:

AI Code Generation for Functions


Artificial intelligence tools can now assist in writing and improving functions.
These tools can auto-generate function code based on natural language prompts,
provide suggestions, and help debug or optimize code, making development
faster and more efficient.

Code Explanation
AI can break down and explain C functions line by line in plain English,
making it easier to understand what a piece of code does.

Example:
You write this C function:

197
AI can explain:
"This function add takes two integers as input and returns their sum."

Code Completion & Suggestions


When you're writing C code, AI tools (like GitHub Copilot or ChatGPT) can
suggest entire functions, fix syntax errors, or even write boilerplate code for
you.

Debugging Help
AI can analyze C functions and:
• Spot logical or syntax errors
• Suggest corrections
• Explain why something is not working

Generating Practice Problems


AI can generate custom practice questions for learning functions, such as:
• Write a function to calculate factorial
• Write a recursive function for Fibonacci
• Implement a string reversal function
And even check your answer.

Unit Test Generation


AI can write test cases to check if your C functions are working correctly. For
example, it can generate tests for different inputs to your add() function.

198
Code Conversion
AI can convert functions between languages. Want to see how a C function
would look in Python or JavaScript? AI can translate that for you.

Concept Reinforcement
AI can quiz you or summarize topics like:
• Function prototypes
• Recursion
• Scope (local vs global)
• Call by value/reference

Summary
Functions are modular units of code designed to perform specific tasks. They help
organize programs logically, making code reusable, maintainable, and easier to
debug.
In C, functions are defined using a return type, a function name, and an optional
parameter list. Once defined, they can be called from the main() function or other
functions to perform specific operations.
This avoids code repetition and promotes a structured and efficient programming
approach.

C supports different types of functions:


• User-defined functions: Created by programmers to handle specific tasks.
• Library functions: Built-in functions provided by C (e.g., printf, scanf).

Regarding scope, variables can either be local (declared inside functions and
accessible only there) or global (declared outside all functions and accessible
throughout the program).

Recursion in C
Recursion occurs when a function calls itself. It is commonly used for problems
that can be broken down into smaller, similar subproblems, such as calculating
factorials or performing tree traversals. A base condition is essential to stop the
recursive calls and prevent infinite loops.

199
Check Your Knowledge
• What are the different types of functions in C? Provide examples.
• Differentiate between call by value and call by reference. Which one does C
use by default?
• What is variable scope? Explain with examples (local, global, static).
• What is the lifetime of a static variable declared inside a function?
• What is the use of extern keyword in the context of function and variable
scope?
• Write a program in C to convert a decimal number to a binary number using
the function.
• Write a program in C to check whether a number is a prime number or not
using the function.
• Write a program with a global variable and a local variable with the same
name. Print their values inside and outside of a function.
• Write a program in C to find the sum of the series
1!/1+2!/2+3!/3+4!/4+5!/5 using the function.
Expected Output : The sum of the series is : 34

200
SESSION 10
STRINGS

SESSION OBJECTIVES
• By the end of this session, you should be able to:
• Understand the concept and structure of arrays and strings in C programming.
• Learn how to declare and initialize 1D and 2D arrays in C.
• Understand how strings are represented as character arrays in C.
• Perform basic operations on strings using built-in string functions from the C Standard
Library (<string.h>).
• Apply practical problem-solving techniques using arrays and strings in C.
• Write simple C programs involving arrays and string manipulation.

Introduction to Strings
What is a String in C?
In C programming, a string is a sequence of characters stored in a
character array and terminated by a special null character ('\0').
This null character marks the end of the string, since arrays in C do not
inherently store their own length.

Important:
A string is not just an array of characters — it’s a text data sequence ending
with '\0'. Without the null terminator, C cannot detect where the string
ends, which can lead to undefined behaviour or memory errors.

201
Think of a string like a series of boxes lined up in a row. Each box contains
one character, and the last box contains the null character ('\0'). The null
character acts like a flag to tell the program where the string ends, so it
knows where to stop reading the characters.

Declaring and Initializing Strings


How to declare a string?
char s[5];

The declaration char s[5]; in C (or C++) means:


• You're creating an array of characters.
• The array is named s.
• It can hold 5 characters.
So, it allocates space for 5 char elements in a row in memory.

How to initialize strings?


You can initialize strings in a number of ways.

All of these lines are C declarations defining and initializing character arrays
(strings), but there are subtle differences in how they're written and what
they mean:

202
1. char c[] = "abcd";
• This declares an array c of length 5 (4 characters + 1 null terminator).
• The size is automatically determined by the compiler
• Equivalent to: char c[5] = {'a', 'b', 'c', 'd', '\0'};

2. char c[50] = "abcd";


• Declares an array c of fixed size 50.
• Initializes the first 5 elements as 'a', 'b', 'c', 'd', '\0', and the remaining
45 elements are initialized to '\0' (zero).
• Useful if you want to modify the string later or store longer strings.

3. char c[] = {'a', 'b', 'c', 'd', '\0'};


• Similar to the first one, but uses explicit character initialization.
• The size of the array is 5, deduced from the initializer list.

Not using a string literal, but it still represents a valid C string because of
the '\0' terminator.

4. char c[5] = {'a', 'b', 'c', 'd', '\0'};


• Same as above, but the array size is explicitly set to 5.
• Fully initialized, and it's a valid null-terminated string.

Why is the Null Character Important?


In C, the null character ('\0') serves as a sentinel value that marks the end of
a string. Without it, C wouldn’t know where the string ends, leading to
potential memory corruption or undefined behaviour.
• For example, if a string in C is represented as an array without '\0' at
the end, functions that work with strings (like printf() or strlen()) would
not know where the string ends, and they may end up reading random
memory, causing unexpected results.

203
Assigning Values to Strings
Arrays and strings are second-class citizens in C; they do not support the
assignment operator once it is declared. For example,

Note: Use the strcpy() function to copy the string instead.

Read String from the user


You can use the scanf() function to read a string. The scanf() function reads
the sequence of characters until it encounters whitespace (space, newline,
tab, etc.).

Example 1: scanf() to read a string

Even though Dennis Ritchie was entered in the above program,


only "Dennis" was stored in the name string. It's because there was a space
204
after Dennis. Also notice that we have used the code name instead
of &name with scanf().

This is because name is a char array, and we know that array names decay to
pointers in C. Thus, the name in scanf() already points to the address of the
first element in the string, which is why we don't need to use &.

How to read a line of text?


You can use the fgets() function to read a line of string. And, you can use
puts() to display the string.

Example 2: fgets() and puts()

Here, we have used fgets() function to read a string from the user.
fgets(name, sizeof(name), stdlin); // read string
The sizeof(name) results to 30. Hence, we can take a maximum of 30
characters as input which is the size of the name string. To print the string,
we have used puts(name);.

205
Note:
• The gets() function can also be to take input from the user. However,
it is removed from the C standard.
• It's because gets() allows you to input any length of characters.
Hence, there might be a buffer overflow.

String Operations Using Built-in Functions


1. strlen() - Calculate the Length of a String
Usage: The strlen() function is used to determine the length of a string
(excluding the null terminator \0).

Syntax:
strlen(const char *str);

1. str: The string whose length is to be calculated.


2. Return Value: The number of characters in the string, excluding the null
character (\0).

Program:

Output:

Logic Breakdown:
1. What happens behind the scenes: strlen() works by iterating through
the string one character at a time and counting the characters until it
encounters the null terminator \0.

206
2. In this example, The string "Hello, World!" has 13 characters, so strlen()
returns 13.

2. strcpy() - Copy a String


Usage: The strcpy() function is used to copy a string from one location to
another.

Syntax: strcpy(dest,src)
1. dest: The destination string where the contents of the source string
will be copied.
2. src: The source string that is to be copied.
3. Return Value: It returns a pointer to the destination string (dest).

Program

Output:

Logic Breakdown:
• What happens behind the scenes: strcpy() copies each character from
the source string (src) to the destination string (dest), including the null
terminator \0.
• In this example, "Hello" is copied from source to destination, and the
output is Hello.

207
3. strcmp() - Compare Two Strings
Usage: The strcmp() function is used to compare two strings lexicographically
(in dictionary order).

Syntax:
int strcmp(const char *str1, const char *str2);

• str1: The first string.


• str2: The second string.
• Return Value:
• 0 if the strings are equal.
• A negative value if str1 is lexicographically less than str2.
• A positive value if str1 is lexicographically greater than str2.

Program:

Logic Breakdown:
• What happens behind the scenes: strcmp() compares both strings
character by character until it finds a difference or reaches the null
terminator \0. It returns 0 if the strings are identical, or a non-zero
value based on the lexicographical order.
• In this example: Since "Hello" is compared with "Hello", strcmp()
returns 0, and the output is "Strings are equal.

208
4. STRCAT()- Concatenate Two Strings
Usage: The strcat() function concatenates (appends) one string to the end of
another.

Syntax:
Strcat(dest,src)
1. dest: The destination string to which the source string (src) will be
appended.
2. src: The source string that will be appended to dest.
3. Return Value: It returns a pointer to the destination string (dest).

Program:

Logic Breakdown:
1. What happens behind the scenes: strcat() appends the source string
(src) to the end of the destination string (dest). It also takes care of the
null terminator, ensuring the destination string remains properly
terminated after concatenation.
2. In this example: "Hello, " is concatenated with "World!", and the
output is "Hello, World!".

5. strchr() - Find the First Occurrence of a Character in a String


Usage: The strchr() function is used to locate the first occurrence of a
character in a string.

209
Syntax:
char *strchr(const char *str, int c);
1. str: The string to be searched.
2. c: The character to find.
3. Return Value: It returns a pointer to the first occurrence of the
character c in str, or NULL if the character is not found.

Program:

Logic Breakdown:
• What happens behind the scenes: strchr() searches the string for the
first occurrence of the specified character. If the character is found, it
returns a pointer to it; otherwise, it returns NULL.
• In this example, The first occurrence of the character 'o' is found at the
second position in the string "Hello, World!". The output will be "o,
World!"

6. strstr() - Find the First Occurrence of a Substring


Usage: The strstr() function is used to find the first occurrence of a substring
in a string.

210
Syntax:
char *strstr(const char *haystack, const char *needle);
• haystack: The string to be searched.
• needle: The substring to search for.
• Return Value: It returns a pointer to the first occurrence of the
substring needle in haystack, or NULL if the substring is not found

Program:

Output:

Logic Breakdown:
• What happens behind the scenes: strstr() searches for the first
occurrence of the substring needle in the string haystack. If the
substring is found, it returns a pointer to the substring's first character
in haystack; otherwise, it returns NULL.
• In this example, the substring "World" is found within "Hello, World!",
and the output will be "World!.

211
Summary
In C, a string is a character array terminated with a null character '\0'.
Declared as:

Strings can be read and printed using scanf(), gets(), printf(), or puts().
• Declaring and Initializing Strings
Declaration:

Initialization:

or directly:

• String Operations Using Built-in Functions


C provides string handling functions in <string.h>, such as:
strlen() — find length of a string
strcpy() — copy one string to another
strcat() — concatenate two strings
strcmp() — compare two strings
strrev() (non-standard in some compilers) — reverse a string

These functions help perform common operations on character arrays


(strings) efficiently.

212
Check Your Knowledge

• How are 1D and 2D arrays declared and accessed in C? Give practical use
cases for each.
• Explain memory allocation of arrays in C. What does it mean for array
elements to be stored in contiguous memory?
• What is the difference between a character array and a string in C?
• What will happen if you go out of bounds while accessing an array in C?
• How is a string represented in C? Why is the null character '\0' important?
• What are the differences between gets() and fgets() in C when reading
strings?
• How do built-in string functions like strlen(), strcpy(), strcat(), and strcmp()
work internally?
• Write a C program to reverse a string without using strrev().
• Count the number of vowels and consonants in a string using a C program.
• Write a function to manually concatenate two strings (without using
strcat()).
• Given a 2D array of integers, find the largest element and its position.
• Write a function in C to check whether a string is a palindrome.

213
SESSION 11
ADVANCED DATA TYPES (STRUCTURES) AND SORTING

SESSION OBJECTIVES
By the end of this session, students should be able to:
• Understand the purpose and use of structures in C/C++ (or other programming
languages, if applicable).
• Declare, initialize, and access data within a structure.
• Explain the basic concepts of sorting and their significance in programming.
• Describe how key sorting algorithms such as Bubble Sort, Selection Sort, and Insertion
Sort work.
• Write and implement sorting algorithms to sort data stored within structures.

Introduction to Structures, Declaring, Initializing, and Accessing


Structures
Structures (often called structs) are user-defined data types in C/C++ (and other
languages like Rust, Go, etc.) that allow grouping variables of different data types
under one name.

A structure in C is a collection of variables of different data types grouped


together under a single name. Each item in a structure is called a member or field.

Why Use Structures?


When you want to store and manage multiple related variables (like student
details: name, age, roll number), structures help keep them organized and
manageable.
• To represent real-world entities, e.g., an employee’s name, age, and salary.
• To store data of different types together.
• To organize complex data efficiently in a program.

Syntax of Structure Definition:

214
• struct: Keyword used to define a structure.
• structure_name: Name given to the structure.
• member1, member2, ...: Members (variables) of the structure, each having a
specific data type.

Example:

Here, a derived type struct Person is defined. Now, you can create variables of this
type.

Create struct Variables


When a struct type is declared, no storage or memory is allocated. To allocate
memory of a given structure type and work with it, we need to create variables.
Here's how we create structure variables:

215
Another way of creating a struct variable is:

In both cases, person1 and person2 are struct Person variables p[] is a struct
Person array of size 20.

Access Members of a Structure


There are two types of operators used for accessing members of a structure.
. - Member operator
-> - Structure pointer operator
Suppose you want to access the salary of person2. Here's how you can do it.

Example:

216
In this program, we have created a struct named Person. We have also created a
variable of Person named person1. In main(), we have assigned values to the
variables defined in Person for the person1 object.

Notice that we have used strcpy() function to assign the value to person1.name.

This is because the name is a char array (C-string) and we cannot use the
assignment operator = with it after we have declared the string.
Finally, we printed the data of person1.

Example: Defining and Using a Structure

Logic Breakdown:
1. Structure Definition: struct Student defines a structure with three members:
name (string), age (integer), and marks (float).
2. Structure Variable: student1 is declared as a variable of type struct Student.

217
3. Accessing Members: We access the members of the structure using the dot (.)
operator.

Nested Structures
A nested structure is a structure that contains another structure as a member. This
is useful when you need to model hierarchical or complex data.

Syntax of Nested Structures:

Example: Nested Structure

Logic Breakdown:
1. Nested Structure: The Employee structure contains another structure Address
as a member.
2. Accessing Nested Members: The dot operator is used twice to access
members of the nested structure: emp.addr.street.

218
Array of Structures
An array of structures allows you to store multiple instances of a structure in an
array.

Syntax of Array of Structures:

Example: Array of Structures

OUTPUT:

219
Logic Breakdown:
1. Array of Structures: An array of students of type struct Student is created with
3 elements.
2. Accessing Array Members: A loop is used to iterate through each student, and
the dot operator is used to access individual members of each structure.

Array of Structure
An array having a structure as its base type is known as an array of structure. To
create an array of structure, first structure is declared, and then an array of
structure is declared just like an ordinary array.

Example: Array of Structure


If the structure is declared like:

Then an array of structures can be created like:

Explanation
In this example, the first structure employee is declared, then the array of
structures is created using a new type, i.e., struct employee. Using the above array
of structure, 10 sets of employee records can be stored and manipulated.
A similar array of structure can also be declared like:

220
Accessing Elements from an Array of Structure
To access any structure, index is used. For example, to read the emp_id of the first
structure, we use scanf(“%d”, emp[0].emp_id); as we know in C array indexing
starts from 0.

Similar array of structure can also be declared like:

C program to read records of three different students in structure having member


name, roll and marks, and displaying it.

221
Pointers to struct
Here's how you can create pointers to structs.

Here, ptr is a pointer to struct.

Example: Access members using Pointer


To access members of a structure using pointers, we use the -> operator.

222
In this example, the address of person1 is stored in the personPtr pointer using
personPtr = &person1;. Now, you can access the members of person1 using the
personPtr pointer.

By the way,
• personPtr->age is equivalent to (*personPtr).age
• personPtr->weight is equivalent to (*personPtr).weight

223
Sorting Concepts and Algorithms and Implementing Sorting Algorithms

What are Sorting Algorithms?


Sorting algorithms in data structure are methods used to arrange data in a
specific order, like ascending or descending. Imagine you have a list of
numbers or names, and you want to organize them from smallest to largest,
or alphabetically. Sorting algorithms help you do that efficiently.

Bubble Sort
Bubble Sort is a simple sorting algorithm that repeatedly steps through the
list to be sorted, compares adjacent elements, and swaps them if they are
in the wrong order. The process is repeated until the list is sorted. It is called
Bubble Sort because smaller elements "bubble" to the top of the list.

Example: Consider the list [4, 2, 7, 1].

First pass:
Compare 4 and 2, swap to get [2, 4, 7, 1]
Compare 4 and 7, no swap
Compare 7 and 1, swap to get [2, 4, 1, 7]

Second pass:
Compare 2 and 4, no swap
Compare 4 and 1, swap to get [2, 1, 4, 7]

Third pass:
Compare 2 and 1, swap to get [1, 2, 4, 7]

Fourth pass:
List is already sorted, no swaps needed
Final sorted list: [1, 2, 4, 7].

224
Use Cases of Bubble Sorting

Used to teach the basics of sorting algorithms and algorithm analysis due to
its simplicity. Suitable for small datasets where its simplicity outweighs its
inefficiency. Performs well on data that is already partially sorted, as it can
quickly detect the order and terminate early

225
Selection Sort

Selection Sort is a simple comparison-based sorting algorithm. It divides the


list into two parts: the sorted part at the beginning and the unsorted part at
the end. The algorithm repeatedly selects the smallest (or largest,
depending on sorting order) element from the unsorted part and swaps it
with the first element of the unsorted part, effectively growing the sorted
part by one element with each iteration.

226
Example: Consider the list [4, 2, 7, 1].

First pass:
Find the minimum element in [4, 2, 7, 1], which is 1
Swap 1 with 4 to get [1, 2, 7, 4]

Second pass:
Find the minimum element in [2, 7, 4], which is 2
Swap 2 with 2 to get [1, 2, 7, 4] (no change)

Third pass:
Find the minimum element in [7, 4], which is 4
Swap 4 with 7 to get [1, 2, 4, 7]

Fourth pass:
The last element 7 is already in place, no need to swap
Final sorted list: [1, 2, 4, 7].

227
Insertion Sort
Insertion Sort is a simple comparison-based sorting algorithm that builds
the final sorted list one element at a time. It works similarly to the way you
might sort playing cards in your hands.
The algorithm takes one element from the unsorted portion of the list and
inserts it into its correct position in the sorted portion. This process is
repeated until the entire list is sorted.

Example: Consider the list [4, 2, 7, 1].

First pass (i = 1):


Key is 2. Compare 2 with 4.
2 is less than 4, so move 4 to the right and insert 2 at the beginning to get
[2, 4, 7, 1].

Second pass (i = 2):


Key is 7. Compare 7 with 4.
7 is greater than 4, so no movement needed. List remains [2, 4, 7, 1].

Third pass (i = 3):


Key is 1. Compare 1 with 7, 4, and 2.
1 is less than 7, move 7 to the right.
1 is less than 4, move 4 to the right.
1 is less than 2, move 2 to the right.
Insert 1 at the beginning to get [1, 2, 4, 7].
228
Final sorted list: [1, 2, 4, 7].

229
Summary
In this session, we introduced the concept of structures in programming—an
essential data type that allows grouping variables of different types under a single
name. We explored how to declare, initialize, and access members of a structure,
laying the groundwork for more complex data handling.
Following that, we discussed sorting concepts, explaining why sorting is important
in computer science and real-world applications. We covered basic sorting
algorithms like Bubble Sort, Selection Sort, and Insertion Sort, and explored how
they function through implementation examples. The session focused on
understanding the logic behind each algorithm and how to implement them
efficiently using structures.

Check Your Knowledge

• What is a structure in C and how does it differ from an array and a union?
• How is memory allocated for structures in C, and how does padding affect
structure size?
• Explain how you can pass a structure to a function in C. What are the
differences between passing by value and by reference?
• Can a structure contain a pointer to itself? Justify your answer with an
example.
230
• Describe how to initialize nested structures. What are the advantages of
nesting?
• What are the key differences between bubble sort, selection sort, and
insertion sort in terms of time complexity and use cases?
• Why is quicksort generally considered better than other O(n²) sorting
algorithms in practice?
• Explain stability in sorting algorithms. Which common sorting algorithms
are stable?
• How would you sort an array of structures based on one of the structure’s
fields? What challenges might arise?
• What are the benefits and limitations of using structures in sorting
algorithms, particularly when handling large datasets?
• Write a C program to define a structure Student with fields name, roll_no,
and marks. Take input for 5 students and display their details.
• Write a function in C to sort an array of integers using insertion sort. Also
write a main() to test it.
• Given a structure Employee with fields id, name, and salary, write a
program to sort the employees in descending order of salary using bubble
sort.
• Write a C function to swap two structure variables using pointers. Use it to
sort an array of structures.
• Implement quicksort in C to sort an array of integers. Include a function to
print the array before and after sorting.

231
SESSION 12
FILE HANDLING
SESSION OBJECTIVES
By the end of this session, learners will be able to:
• Understand the importance and purpose of file handling in programming.
• Describe different file operations such as creating, opening, reading, writing, and closing
files.
• Explain the concept of file pointers and how they are used to track the position in a file.
• Perform reading from and writing to text files using appropriate functions and modes.
• Work with binary files for storing and retrieving non-text data.
• Apply best practices in file handling to ensure safe, efficient, and error-free file
operations.

Introduction to File Handling

In programming, file handling refers to the process of creating, opening, reading,


writing, modifying, and managing files stored on a storage device like a hard drive,
SSD, or external storage. Files provide a way for programs to store information
permanently so that the data can be retrieved or modified even after the program
has been closed.

What is a File?
A file is a collection of data or information that has a name and is stored in a
storage location. Files can contain different types of data.

Why are files needed?


When a program is terminated, the entire data is lost. Storing in a file will
preserve your data even if the program terminates. If you have to enter a
large number of data, it will take a lot of time to enter them all. However, if
you have a file containing all the data, you can easily access the contents of
the file using a few commands in C. You can easily move your data from
one computer to another without any changes.

232
Types of Files
When dealing with files, there are two types of files you should know
about:
• Text files
• Binary files

Text files
Text files are the normal .txt files. You can easily create text files
using any simple text editors such as Notepad. When you open those
files, you'll see all the contents within the file as plain text. You can
easily edit or delete the contents. They take minimum effort to
maintain, are easily readable, and provide the least security and
takes bigger storage space.

Binary files
Binary files are mostly the .bin files in your computer. Instead of
storing data in plain text, they store it in the binary form (0's and 1's).
They can hold a higher amount of data, are not readable easily, and
provides better security than text files.

How file handling works


Once we compile and run a program, it gets the output, but the result isn’t
saved anywhere in the framework as details.
What if we want to store the outcome for future references? After all, most
tech companies compose programmes to store the results as records. By
integrating file handling in C, this issue can easily be overcome. Since
most computer systems use files to, store information, C offers this
advantage of file handling.

Need for File Handling in C


There was a moment when the result generated when the software is
compiled, and output is not expected. If we wish to review the
performance many times, compiling and running the same software,
several times is a repetitive job. It is where the files handling falls into
effect.

233
Below are some of the following explanations for file management’s
popularity:
• Reusability: helps to retain the data collected after the software is
run.
• Huge storage capacity: you don’t need to think about the issue of
mass storage using data.
• Save time: Unique applications need a lot of user feedback. You can
quickly open some aspect of the code using special commands.
• Portability: You can quickly move file material from one operating
device to another without thinking about data loss.

File handling is essential in situations like:


• Saving user data (like usernames, passwords, preferences)
• Storing application settings and configurations
• Recording log files or error messages
• Working with large data collections (like CSV, JSON, XML, or binary
files)
• Reading from or writing to databases
• Handling media files (images, videos, sounds) or binary data
• Text Files — contain readable characters (e.g., .txt, .csv)
• Binary Files — contain data in binary format, which is not human-
readable (e.g., .exe, .jpg, .mp3)

File Operations and Files Pointers, reading from and Writing to Files

File Operations and File Pointers

What are File Operations?


File operations are the basic actions performed on a file to work with its
contents. Every programming language provides ways to:
• Open a file
• Read data from a file
• Write data to a file
• Close a file

234
File Operations and File Pointers in C
In C programming, file handling is done using functions from the stdio.h
header file. Files are used to store data permanently, and a file pointer is
used to keep track of the file being used.

235
FILE Pointer (File*)
While working with file handling, you need a file pointer to store the
reference of the FILE structure returned by the fopen() function. The file
pointer is required for all file-handling operations.

The fopen() function returns a pointer of the FILE type. FILE is a predefined
struct type in stdio.h and contains attributes such as the file descriptor,
size, and position, etc.

Declaring a File Pointer (FILE*)


Below is the syntax to declare a file pointer –

Opening a File
A file must be opened to perform any operation. The fopen() function is
used to create a new file or open an existing file. You need to specify the
mode in which you want to open. There are various file opening modes
explained below, any one of them can be used during creating/opening of a
file.
Opening a file is performed using the fopen() function defined in the stdio.h
header file. The fopen() function returns a FILE pointer which will be used
for other operations such as reading, writing, and closing the files.

The syntax for opening a file in standard I/O is:

236
Explanation:
fopen():
This is a standard library function defined in stdio.h. It is used to open a file
for reading, writing, or appending. It returns a pointer to a FILE object (of
type FILE *), which is then used to access the file.

"fileToOpen":
This is the name of the file you want to open. It should be a string literal
(enclosed in double quotes). It can be just a filename (e.g., "data.txt") or a
full path (e.g., "C:\\Users\\user\\data.txt"). If the file doesn't exist and
you’re opening in read mode ("r"), it will return NULL.

"mode":
This defines the mode in which the file is opened. It’s also a string (enclosed
in quotes). Some common file modes are:

Mode Meaning
"r" Open file for reading (file must exist)
"w" Open file for writing (creates or overwrites)
"a" Open file for appending
"r+" Open for reading and writing (file must exist)
"w+" Open for reading and writing (creates or overwrites)
"a+" Open for reading and appending

ptr:
This is a variable (typically of type FILE *) that holds the file pointer
returned by fopen().

Example:
FILE *ptr;

Return Value:
If the file is successfully opened, fopen() returns a valid file pointer. If the
file cannot be opened (e.g., doesn’t exist in read mode), it returns NULL.

Example Usage:
Use fopen() to open a file.

237
Reading and writing to a text file
For reading and writing to a text file, we use the functions fprintf() and
fscanf(). They are just the file versions of printf() and scanf(). The only
difference is that fprintf() and fscanf() expects a pointer to the structure
FILE.

Reading and Writing


fgetc(fp): Reads a character from file.
fputc(char, fp): Writes a character to file.
fgets(str, size, fp): Reads a string.
fprintf(fp, ...): Writes formatted output (like printf).
fscanf(fp, ...): Reads formatted input (like scanf).

Example of Creating a File


In the following example, we are creating a new file. The file mode to
create a new file will be "w" (write mode).

This C program is designed to create a text file named file1.txt in the


program's directory. It begins by including the stdio.h library, which

238
provides input and output functions such as printf() and fopen(). Inside the
main() function, a file pointer named file is declared and used to open the
file in write mode ("w") using fopen(). If the file does not exist, it will be
created; if it already exists, its contents will be overwritten. The program
then checks whether the file was successfully created by verifying if the file
pointer is NULL. If it is NULL, an error message is displayed and the program
exits with a return value of 1, indicating failure. If the file is created
successfully, it prints "File created." to notify the user. The program then
terminates by returning 0, indicating successful execution. However, it’s a
good programming practice to close the file using fclose(file); before the
program ends, to properly release the file resource.

Example: Program to write the data to the file output.txt using fprintf()

Output

239
Example: Program to read the data from the file output.txt using fscanf()

Content of output.txt file:

240
Example: Program to append the data to the file output.txt using fprintf()

Content of output.txt file:

Closing a File
The file (both text and binary) should be closed after reading/writing.

Closing a file is performed using the fclose() function.

Here, fp is a file pointer associated with the file to be closed.

241
Example: Writing and Reading a File

File I/O in C uses a special file pointer (FILE *), which acts as a connection
between the program and the file.

Working with Binary Files in C


Binary files store data in the same binary format as it exists in computer memory,
without converting it into a human-readable text format. This makes binary file
operations faster, more space-efficient, and ideal for storing complex, structured
data like records, arrays, or custom data structures.
Unlike text files that represent data using characters, binary files handle raw byte
sequences, preserving the exact representation of data as stored in memory.

Why Use Binary Files?


• Speed: Direct reading/writing of memory content reduces processing
time.
• Efficiency: No extra space used for text formatting or delimiters.
• Accuracy: Maintains exact memory layout, useful for structured data
like images, audio, databases, or custom structures (e.g., employee
records, student marksheets).
• Less error-prone: Avoids problems of data type conversions between
numbers and text.

242
Common Functions for Binary File Handling
Function Purpose
Reads binary data from a file into
fread()
memory
Writes binary data from memory to a
fwrite()
file

Syntax:
fread()

size_t fread(void *ptr, size_t size, size_t count, FILE *stream);

• ptr: Pointer to the memory block where data will be stored.


• size: Size of each data element in bytes.
• count: Number of elements to read.
• stream: Pointer to the file.

fwrite()
size_t fwrite(const void *ptr, size_t size, size_t count, FILE
*stream);

• ptr: Pointer to the data block to be written.


• size: Size of each data element in bytes.
• count: Number of elements to write.
• stream: Pointer to the file.

Reading and writing to a binary file


Functions fread() and fwrite() are used for reading from and writing to a file
on the disk, respectively, in case of binary files.

Writing to a binary file


To write into a binary file, you need to use the fwrite() function. The
functions take four arguments:

• address of data to be written in the disk


• size of data to be written in the disk

243
• number of such type of data
• pointer to the file where you want to write.

Example 3: Write to a binary file using fwrite()

244
Example: Reading from a Binary File

File Handling Best Practices


Opening Files with the Correct Mode
To begin file operations, a file must be opened using the fopen() function.
The mode provided to fopen() determines the type of access:

MODE DESCRIPTION

"r" Open for reading. File must exist.

"w" Open for writing. Creates or truncates

"a“ Open for appending. Creates if missing

245
"rb", "wb", "ab" Same as above but in binary mode.

Best Practice: Always use the appropriate mode that matches your
intended operation to avoid unintended data loss or errors.

Verifying Successful File Opening


Never assume that a file has opened successfully. Always check the return
value of fopen():

Why It Matters: Failing to check can lead to dereferencing a NULL pointer,


causing your program to crash.

3. Closing Files Properly


Always close a file using fclose() once you are done with it:
This ensures that:
• All data is properly written to the disk.
• System resources are released.

Best Practice: Even in error conditions or early returns, ensure that fclose()
is called.

4. Reading and Writing Strings Safely


When reading strings, avoid unsafe functions like gets(). Use fgets() instead:

When writing data to a file, fprintf() is recommended for formatted output:

246
Avoiding Incorrect Use of feof()
A common mistake is using feof() as a loop condition:

Correct Approach:

Checking for Errors


In addition to checking for end-of-file, check for errors with ferror():

7. Flushing Output Buffers


Use fflush() to flush the output buffer to disk explicitly:

While fclose() does this automatically, fflush() is useful when writing


intermediate data that must not be lost.

247
Summary
File handling in C allows programs to store and retrieve data from files, ensuring
data persists even after the program ends. It uses file pointers (FILE *) to manage
files, which need to be opened using fopen() and closed with fclose(). Files can be
opened in different modes like read ("r"), write ("w"), and append ("a"). C
provides functions such as fgetc(), fgets(), fputc(), fputs(), fprintf(), and fscanf() for
text file operations. For working with structured, non-text data, binary files are
used, accessed with fread() and fwrite(). Binary files are faster and more space-
efficient compared to text files as they store data in raw memory format.

Key Points:
Uses file pointers (FILE *) for file operations.
Open files using fopen() and close them with fclose().

248
Text files: fgetc(), fgets(), fputc(), fputs(), fprintf(), fscanf().
Binary files: fread(), fwrite() for faster, structured data storage.
Modes: "r" (read), "w" (write), "a" (append), and combinations like "r+", "w+".

Binary files store data in a memory format, faster and compact.

Check Your Knowledge


• What is the main difference between a file and a variable in a program?
• Name the four basic operations you can perform on a file.
• What is a file pointer, and what is its role in file handling?
• Which function is used to move the file pointer to a specific location in a
file?
• What does the tell() function do in file handling?
• How would you open a file named notes.txt in write mode?
• What is the difference between read(), readline(), and readlines() in
Python?
• Why is it important to close a file after performing operations on it?
• In which situations would you prefer to use a binary file instead of a text
file?
• How would you open a file named image.png for reading in binary mode?
• Why is using a with statement recommended when working with files in
Python?
• How can you handle errors that occur while opening or reading a file?
• Write a program in C to create and store information in a text file.
Test Data:
Input a sentence for the file: This is the content of the file test.txt.
Expected Output:
The file test.txt is created successfully...!!
• Write a program in C to read an existing file.

Test Data:

249
Input the file name to be opened: test.txt
Expected Output:
The content of the file test.txt is:
This is the content of the file test.txt.
• Write a program in C to write multiple lines to a text file.
Test Data:
Input the number of lines to be written: 4
The lines are:
test line 1
test line 2
test line 3
test line 4
Expected Output:
test line 1
test line 2
test line 3
test line 4

250
251

You might also like