Professional Documents
Culture Documents
Notes - Computational Thinking and Programming (Academic Year 2023-24) - 2023 Batch - I Yr I Semester - CSE (AI & ML) - 13-12-2023 - For Students
Notes - Computational Thinking and Programming (Academic Year 2023-24) - 2023 Batch - I Yr I Semester - CSE (AI & ML) - 13-12-2023 - For Students
NOTES
Academic Year 2023-24
I Year I Semester CSE(AI & ML)
(2023 Batch)
Prepared By:
Dr. G Uday Kiran
Ms. Srilakshmi V
I Year I Sem Computational Thinking and Programming
NOTES
Syllabus
Unit I: (10 Lectures)
Introduction to Computational Thinking: Definition, Objectives, How is Computational
Thinking Used? Logical and Algorithmic Thinking.
Problem Solving Elements: Algorithms, Definition and Characteristics; Flowchart,
Flowchart Symbols, Pseudo Code Solution to Problems, Basic Structures of C Language,
Creating and Running Programs, Variables and Data Types, Input and Output Statements,
Types of Operators, Precedence of Operators, Type Conversion.
Textbook:
1. Computational Thinking - A Beginner's Guide to Problem-Solving and Programming, Karl
Beecher, BCS Learning & Development Limited, ISBN: 9781780173641, August 2017.
2. Schaum's Outline of Programming with C, Byron Gottfried, McGraw-Hill.
3. Programming in ANSI C, E. Balaguruswamy, Tata McGraw-Hill.
References:
1. The C Programming Language, Brian W. Kernighan, Dennis M. Ritchie, Prentice Hall of India
2. Let us C, Yashavant Kanetkar, BPB Publications, New Delhi.
3. Absolute Beginners' Guide to C, Greg Perry, SAMS Publishing
Table of Contents
Syllabus ................................................................................................................... 2
Unit I ....................................................................................................................... 6
Definition ................................................................................................................... 6
Objectives ................................................................................................................... 7
Flowchart ................................................................................................................. 13
Precedence of Operators............................................................................................ 33
Unit II .................................................................................................................... 35
If Statements: ........................................................................................................... 36
Switch-Case ............................................................................................................. 43
Goto ......................................................................................................................... 52
While ........................................................................................................................ 55
For ........................................................................................................................... 59
Break ....................................................................................................................... 62
Continue .................................................................................................................. 62
Arrays ...................................................................................................................... 81
Mean ........................................................................................................................ 97
Variance ................................................................................................................... 97
Why Shall We Study Structures / Why Structures Shall be Studied? ....................... 144
Random Access Using FSeek, FTell and Rewind Functions ...................................... 166
Unit I
Topics to be Discussed:
Introduction to Computational Thinking: Definition, Objectives, How is Computational
Thinking Used? Logical and Algorithmic Thinking.
Problem Solving Elements: Algorithms, Definition and Characteristics; Flowchart,
Flowchart Symbols, Pseudo Code Solution to Problems, Basic Structures of C Language,
Creating and Running Programs, Variables and Data Types, Input and Output Statements,
Types of Operators, Precedence of Operators, Type Conversion.
Definition
Computational thinking involves breaking down complex problems, recognizing patterns,
formulating precise instructions, and devising creative solutions that can be executed by
computers or humans. In the road trip example, it's about analyzing factors, determining a
sequence of actions, and reaching a solution. The correlation lies in dissecting a non-
computer problem as one would with a coding challenge.
“Computational Thinking is a Mental Process for Designing Solutions to Problems in a Way that
Leverages the Strengths of Computers.”
-Jeanette Wing
“Computational Thinking Empowers People to be Both Critical Thinkers About the World and
Designers of their Own Digital Tools.”
-Seymour Papert
“It's a Set of Skills and Approaches that Help Individuals Solve Complex Problems in all Areas
of Life.”
-Seymour Papert
Why Study Computational Thinking?
• Problem-Solving: It enhances analytical skills, enabling systematic and efficient
problem-solving in diverse domains.
Objectives
• Critical Thinking: Develop the ability to dissect problems and evaluate multiple
solution paths.
• Pattern Recognition: Identify recurring patterns within problems and apply relevant
strategies.
• Algorithmic Thinking: Formulate step-by-step approaches to solving complex
problems.
• Abstraction: Grasp the concept of simplification by focusing on essential details while
ignoring irrelevant ones.
• Creativity: Apply computational thinking to devise innovative solutions and
approaches.
• Interdisciplinary Application: Demonstrate how computational thinking is relevant
across disciplines.
• Effective Communication: Clearly articulate problem-solving processes and
solutions.
Algorithmic Thinking:
Algorithmic thinking is a subset of logical thinking that focuses on the systematic design and
analysis of algorithms. An algorithm is a step-by-step procedure or set of instructions for
solving a specific problem or performing a task. Algorithmic thinking involves the following
aspects:
• Algorithm Design: It is the process of creating a well-defined sequence of steps to
solve a particular problem. This requires breaking down the problem into smaller
subproblems and designing a logical flow to solve each subproblem.
• Efficiency: Algorithmic thinking considers the efficiency of algorithms. Efficient
algorithms perform tasks with minimal time and resources. Analyzing time complexity
and space complexity are common practices in algorithmic thinking.
Logical thinking is a broader cognitive skill that encompasses reasoning, analysis, and
decision-making, while algorithmic thinking is a specific subset of logical thinking focused
on the systematic design and analysis of algorithms. Both are fundamental in problem-
solving, mathematics, computer science, and various fields where structured and systematic
approaches are required to arrive at solutions.
Problem Solving Elements
We use an algorithm to generate a solution to any given problem in the form of steps. When
we use a computer for solving any given problem (in well-defined multiple steps), we need to
communicate these steps to the solution properly to the computer.
When we execute any algorithm on a computer, we need to combine various operations like
subtraction and addition for performing various complex operations of mathematics. We can
express algorithms using flowcharts, natural language, and many more.
Characteristics:
• Input: An algorithm should have zero or more inputs.
• Output: An algorithm should produce one or more outputs.
• Definiteness: Each instruction must be clear and unambiguous.
• Finiteness: The algorithm should have a finite number of steps.
• Effectiveness: The operations should be basic so that they can be performed exactly
and in a finite amount of time.
Input:
An algorithm should have zero or more inputs provided externally.
Example: In the binary search algorithm, the inputs are a sorted array and a target value to
find.
Explanation: Inputs are essential for an algorithm to operate. In the case of binary search,
without an array to search through or a target value to find, the algorithm cannot perform its
intended task.
Output:
An algorithm should produce at least one output, which is the solution to the problem.
Example: In the sorting algorithm Quick Sort, the output is an array sorted in ascending or
descending order.
Explanation: The purpose of running an algorithm is to arrive at a solution, which is
delivered through its output. In Quick Sort, the output is a sorted array, fulfilling the
requirement of providing a result.
Definiteness:
Each step of the algorithm must be clear, unambiguous, and effectively computable.
Example: In a factorial calculation algorithm, the instruction "Multiply the current number
by the next integer decrementing towards 1" is a definite step.
Explanation: Definiteness ensures that each step can be performed without ambiguity, thus
making it possible for the algorithm to be implemented accurately. In the case of calculating
factorial, each step is clearly defined so that it can be executed precisely.
Finiteness
The algorithm must terminate after a finite number of steps.
Example: In the Euclidean algorithm for finding the Greatest Common Divisor (GCD) of two
numbers, the algorithm terminates once the remainder becomes zero.
Explanation: An algorithm must not run indefinitely; it must have an end point. The
Euclidean algorithm satisfies this by terminating when the remainder is zero, ensuring that
it doesn't loop infinitely.
Effectiveness
The operations of the algorithm must be basic so that they can be executed in a finite amount
of time and resources.
Example: In a linear search algorithm, the operation "Compare the target value with the
current array element" is effective and simple.
Explanation: Effectiveness ensures that each step of the algorithm can be executed with
practical constraints of time and resources. The operation in linear search is straightforward
and can be executed quickly, making it effective.
Consider the task of sorting a list of names alphabetically. You have a long list of names, and
you want to arrange them in A-to-Z order. Now, let's apply the two points mentioned:
• Scalability: Imagine you have a list of only 10 names. Sorting them manually might
not be too time-consuming. However, if you have a list of 10,000 names or more, doing
it by hand becomes impractical. Algorithms allow you to break down this large real-
world problem of sorting a massive list into smaller, manageable steps. You can divide
the list into smaller portions, sort each portion, and then merge them back together
using an algorithm like Merge Sort or Quick Sort. This scalability is crucial because
it helps you efficiently handle large-scale problems.
• Feasibility: Sorting a list of names is feasible because it can be broken down into
smaller steps. You can compare two names at a time, determine their order, and
repeat this process until the entire list is sorted. This step-by-step breakdown into
smaller tasks demonstrates the feasibility of the problem. Algorithms provide a
systematic way to tackle each of these steps, ensuring that the problem can be solved
effectively.
So, in this example, the task of sorting a large list of names illustrates the importance of
algorithms. They allow you to scale up your problem-solving capabilities and confirm the
feasibility of addressing complex tasks by breaking them down into manageable steps.
Flowchart
A flowchart is a graphical representation of a process, system, or algorithm using
standardized symbols, shapes, and arrows to depict the sequence of steps or actions.
Flowcharts are a visual tool that helps visualize, understand, and communicate the flow of
activities within a system or procedure.
Importance of Flowcharts:
• Visual Clarity: Flowcharts provide a visual representation of complex processes,
making them easier to understand and follow. They break down intricate systems into
manageable steps, helping individuals grasp the overall structure and logic.
• Process Analysis and Improvement: Flowcharts are instrumental in analyzing
existing processes. They allow individuals and teams to identify bottlenecks,
redundancies, or inefficiencies in a process. This analysis provides a basis for making
improvements and optimizing workflows.
• Documentation and Communication: Flowcharts serve as effective documentation
tools. They enable organizations to document their processes and procedures in a
clear and standardized format. Additionally, flowcharts are useful for communicating
processes and systems to stakeholders, team members, or clients, ensuring everyone
is on the same page.
• Problem Solving and Decision-Making: Flowcharts aid in problem-solving by
breaking down a problem into its constituent parts and showing the relationships
between those parts. When facing complex decisions or challenges, individuals can
use flowcharts to systematically analyze the situation and explore potential solutions.
• Quality Control and Standardization: Flowcharts are valuable for quality control
and standardization efforts. They help ensure that processes are executed
consistently and according to predefined standards. By documenting best practices
in flowcharts, organizations can maintain quality and reduce errors.
Flowchart Symbols
• Data object – The Data object, often referred to as the I/O Shape shows the Inputs to
and Outputs from a process.
• Rectangle – This is used to represent an event which is controlled within the process.
Typically this will be a step or action which is taken.
• Diamond – Used to represent a decision point in the process. Typically, the statement
in the symbol will require a `yes’ or `no’ response and branch to different parts of the
flowchart accordingly.
• Document – The Document object is a rectangle with a wave-like base. This shape is
used to represent a Document or Report in a process flow.
• Rounded box – This is used to represent an event which occurs automatically. Such
an event will trigger a subsequent action, for example, receive a telephone call, or
describe a new state of affairs.
• Stored data – This is a general data storage object used in the process flow as opposed
to data which could be also stored on a hard drive, magnetic tape, memory card, of
any other storage device.
• Manual input – This object is represented by a rectangle with the top sloping up from
left to right. The Manual Input object signifies an action where the user is prompted
for information that must be manually inputted into a system.
• Direct data – Direct data object in a process flow represents information stored which
can be accessed directly. This object represents a computer’s hard drive.
• Circle – Used to represent a point at which the flowchart connects with another
process. The name or reference for the other process should appear within the symbol.
• Internal storage – This is an object which is commonly found in programming
flowcharts to illustrate the information stored in memory, as opposed to on a file.
• Predefined process – This allows you to write one subroutine and call it as often as
you like from anywhere in the code.
Flowchart Examples:
Display sum
In this pseudocode example, common control structures like "While" to iterate through the
numbers, "If-Then-Else" to check if a number is even, and "Set" to assign values to variables
have been used. This pseudocode provides a clear and language-independent representation
of the algorithm for summing even numbers, making it easy for programmers with different
language backgrounds to understand and implement.
Global Declaration:
In this section, global variables and function prototypes are declared. These are accessible
throughout the program.
int globalVariable = 10;
void displayMessage(); // function prototype
Main() Function:
Every C program must have a main() function. This is the starting point of execution for the
program.
int main() {
int num1 = 5, num2 = 15, sum;
displayMessage();
return 0;
}
Sub Programs:
Sub programs (or functions) are blocks of code that perform a specific task. They are defined
outside the main() function (either above or below it). These functions can be called from
main() or from other functions.
void displayMessage() {
printf("This is a message from a sub program!");
}
Now, when we combine all these sections together, we get the complete structure of the C
program:
/*
Program to Calculate Sum of Two Numbers
Author: John Doe
Date: 22nd Sept 2023
Description: This is a simple program to demonstrate the structure of a C program.
*/
#include<stdio.h>
#define MAX 100
int main() {
int num1 = 5, num2 = 15, sum;
displayMessage();
return 0;
}
void displayMessage() {
printf("This is a message from a sub program!");
}
#include<stdio.h>
// Function prototypes
float add(float a, float b);
float subtract(float a, float b);
float multiply(float a, float b);
float divide(float a, float b);
int main() {
float num1, num2;
// Take input
printf("Enter two numbers separated by space: ");
scanf("%f %f", &num1, &num2);
if(num2 != 0.0) {
return 0;
}
// Function definitions
float add(float a, float b) {
return a + b;
}
CamelCase: This convention capitalizes the first letter of each word except the first one, and
there are no spaces or underscores between words. It is often used for function names and
variable names in C
int myVariable;
void calculateInterestRate();
snake_case: In this convention, words are separated by underscores, and all letters are
lowercase. It's often used for variable names and function names in some coding styles.
Example:
int my_variable;
void calculate_interest_rate();
UPPER_CASE: All letters in the identifier are capitalized, and words are separated by
underscores. This convention is often used for constants.
Example:
#define MAX_VALUE 100
const int ARRAY_SIZE = 10;
Leading Underscore: Identifiers beginning with an underscore (_) are often used to indicate
that a variable or function is private or intended for internal use within a module or library.
They should not be used for global identifiers.
Example:
static int _internal_counter;
In C programming, identifiers (which include variable names) must adhere to specific naming
convention rules for them to be valid and readable.
Rules for Naming Identifiers in C:
Character Set:
• Identifiers can consist of letters (both uppercase and lowercase), digits, and
underscore (_).
• The first character of an identifier must be a letter (uppercase or lowercase) or an
underscore (_).
Length Limitation:
• Identifiers can be of any length, but only the first 31 characters are significant. Some
compilers may have different limits, so it's a good practice to keep identifiers
reasonably short and meaningful.
Case Sensitivity:
• C is case-sensitive, which means that uppercase and lowercase letters are treated as
distinct. So, myVar and myvar are considered different identifiers.
Reserved Words:
• You cannot use C reserved words (also known as keywords) as identifiers. These words
have special meanings in the language and are used for specific purposes. Examples
of reserved words in C include int, for, if, and while.
Consistency:
• While there is no strict rule for choosing between CamelCase, snake_case, PascalCase,
or other naming conventions, it's essential to be consistent within your codebase.
Choose a convention and stick to it to make your code more readable.
Meaningful Names:
• Choose descriptive and meaningful names for your variables. Names like counter or
value convey more information than generic names like x or temp.
Digits in Identifiers:
• You can use digits in identifiers, but they cannot be the first character. For example,
myVar123 is a valid identifier.
Examples:
Valid Identifiers:
int myVar;
float interestRate;
char _internalCounter;
long long accountBalance;
int myVar123;
Invalid Identifiers:
int 123myVar; // Starts with a digit
int for; // Reserved word
int while; // Reserved word
int my-variable; // Contains a hyphen (not allowed)
double my%var; // Contains a special character (not allowed)
Data Types
int main() {
int num;
printf("Enter a number: ");
scanf("%d", &num);
printf("You entered: %d\n", num);
return 0;
}
Example 2: File Input/Output
#include <stdio.h>
int main() {
FILE *file;
char text[] = "Hello, File I/O!";
// Open a file for writing
file = fopen("output.txt", "w");
if (file == NULL) {
printf("Error opening the file!\n");
return 1;
}
// Write to the file
fputs(text, file);
// Close the file
fclose(file);
return 0;
}
Example 3: Formatted Input/Output
#include <stdio.h>
int main() {
int num = 42;
float pi = 3.14159;
char name[] = "John";
printf("Integer: %d\n", num);
printf("Float: %.2f\n", pi);
printf("Name: %s\n", name);
return 0;
}
Example 4: Character Input/Output
#include <stdio.h>
int main() {
char ch;
printf("Enter a character: ");
ch = getchar();
printf("You entered: ");
putchar(ch);
return 0;
}
Types of Operators
• Arithmetic Operators: These operators perform mathematical calculations.
• Relational Operators: Used to compare two values and return a Boolean result (true
or false).
• Logical Operators: Used to combine and manipulate Boolean values.
• Bitwise Operators: Used to perform bitwise operations on integers.
• Assignment Operators: Used to assign values to variables.
• Increment and Decrement Operators: Used to increase or decrease the value of a
variable.
• Conditional (Ternary) Operator: A shorthand way to write if-else statements.
Logical Operators
Logical AND (&&):
The logical AND operator returns true if both of its operands are true; otherwise, it returns
false.
It is represented by the && symbol.
Example:
if (x > 5 && y < 10) {
// This condition is true if both x is greater than 5 and y is less than 10.
}
Logical OR (||):
The logical OR operator returns true if at least one of its operands is true; it returns false only
if both operands are false.
It is represented by the || symbol.
Example:
if (x < 0 || y > 100) {
// This condition is true if either x is less than 0 or y is greater than 100.
}
Logical NOT (!):
The logical NOT operator is used to negate or reverse the value of its operand. If the operand
is true, ! makes it false, and vice versa.
It is represented by the ! symbol.
Example:
if (!isReady) {
// This condition is true if isReady is false (i.e., if something is not ready).
}
Summary
&& (Logical AND) Truth Table:
true && true = true
Bitwise Operators
Bitwise operators in C are used to manipulate individual bits of data in variables. These
operators work at the binary level and are often used in low-level programming, hardware
manipulation, and optimizing code. C provides six bitwise operators.
Bitwise AND (&):
The bitwise AND operator performs a bitwise AND operation between corresponding bits of
two integers. If both bits are 1, the result bit is 1; otherwise, it's 0.
Example:
int a = 5; // binary: 0101
int b = 3; // binary: 0011
int result = a & b; // binary result: 0001 (decimal: 1)
Explanation:
• a is assigned the decimal value 5, which in binary is 0101.
• b is assigned the decimal value 3, which in binary is 0011.
• Now, let's perform the bitwise AND operation between a and b:
• For each bit position (from left to right), we compare the corresponding bits in a and
b:
• The leftmost bits: 0 & 0 results in 0.
• The second leftmost bits: 1 & 0 results in 0.
• The third leftmost bits: 0 & 1 results in 0.
• The rightmost bits: 1 & 1 results in 1.
• After performing the bitwise AND operation for each bit position, we get the binary
result: 0001.
• Finally, the result is assigned to the variable result, which has a decimal value of 1.
• So, result will have the value 1, which is the decimal representation of the binary
result 0001.
• Therefore, the output of the code is that result is equal to 1.
Bitwise OR (|):
The bitwise OR operator performs a bitwise OR operation between corresponding bits of two
integers. If at least one bit is 1, the result bit is 1; otherwise, it's 0.
Example:
int a = 5; // binary: 0101
int b = 3; // binary: 0011
int result = a | b; // binary result: 0111 (decimal: 7)
Explanation:
• a is assigned the decimal value 5, which in binary is 0101.
• b is assigned the decimal value 3, which in binary is 0011.
• Now, let's perform the bitwise OR operation between a and b:
• For each bit position (from left to right), we compare the corresponding bits in a and
b:
• The leftmost bits: 0 | 0 results in 0.
• The second leftmost bits: 1 | 0 results in 1.
• The third leftmost bits: 0 | 1 results in 1.
• The rightmost bits: 1 | 1 results in 1.
• After performing the bitwise OR operation for each bit position, we get the binary
result: 0111.
• Finally, the result is assigned to the variable result, which has a decimal value of 7.
• So, result will have the value 7, which is the decimal representation of the binary
result 0111.
• Therefore, the output of the code is that result is equal to 7.
• After performing the bitwise XOR operation for each bit position, we get the binary
result: 0110.
• Finally, the result is assigned to the variable result, which has a decimal value of 6.
• So, result will have the value 6, which is the decimal representation of the binary
result 0110.
• Therefore, the output of the code is that result is equal to 6.
sum = a + b;
difference = a - b;
product = a * b;
quotient = a / b;
remainder = a % b;
return 0;
}
Example 2: Relational Operators
#include <stdio.h>
int main() {
int x = 5, y = 10;
printf("%d > %d is %d\n", x, y, x > y);
printf("%d < %d is %d\n", x, y, x < y);
printf("%d == %d is %d\n", x, y, x == y);
printf("%d != %d is %d\n", x, y, x != y);
return 0;
}
Example 3: Logical Operators
#include <stdio.h>
int main() {
int p = 1, q = 0;
printf("p && q is %d\n", p && q); // Logical AND
printf("p || q is %d\n", p || q); // Logical OR
printf("!p is %d\n", !p); // Logical NOT
return 0;
}
Example 4: Assignment Operators
#include <stdio.h>
int main() {
int x = 5, y = 10;
x += y; // Equivalent to x = x + y
printf("x += y is %d\n", x);
y *= 2; // Equivalent to y = y * 2
printf("y *= 2 is %d\n", y);
return 0;
}
Example 5: Increment and Decrement Operators
#include <stdio.h>
int main() {
int a = 5, b = 5;
printf("Original values: a = %d, b = %d\n", a, b);
a++; // Increment a by 1
--b; // Decrement b by 1
printf("After increment and decrement: a = %d, b = %d\n", a, b);
return 0;
}
Example 6: Conditional (Ternary) Operator
#include <stdio.h>
int main() {
int num = 10;
printf("The number is %s\n", (num % 2 == 0) ? "even" : "odd");
return 0;
}
Precedence of Operators
Operator Precedence in C:
• Parentheses ( ): Highest precedence. Operations inside parentheses are evaluated first.
• Postfix Operators (++, --): Increment and decrement operators are applied after the
expression.
• Unary Operators (+, -, !, ~): Unary plus, unary minus, logical NOT, and bitwise NOT.
• Multiplicative Operators (*, /, %): Multiplication, division, and modulus operators,
evaluated left to right.
• Additive Operators (+, -): Addition and subtraction operators, evaluated left to right.
• Shift Operators (<<, >>): Left shift and right shift operators, evaluated left to right.
• Relational Operators (<, <=, >, >=): Less than, less than or equal to, greater than,
greater than or equal to.
• Equality Operators (==, !=): Equal and not equal operators.
• Bitwise AND Operator (&): Bitwise AND operator.
• Bitwise XOR Operator (^): Bitwise XOR operator.
• Bitwise OR Operator (|): Bitwise OR operator.
• Logical AND Operator (&&): Logical AND operator.
• Logical OR Operator (||): Logical OR operator.
• Conditional Operator (?:): Ternary conditional operator.
• Assignment Operators (=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=): Assignment
operators.
• Comma Operator (,): Comma operator, used to separate expressions
Type Conversion
Types of Type Conversion:
• Implicit Type Conversion (Automatic): This type of conversion is performed by the
C compiler automatically when there's a need to convert one data type to another
without the programmer's intervention. It's also known as "type coercion."
• Explicit Type Conversion (Manual): This type of conversion is done explicitly by the
programmer using casting operators. It allows you to specify the desired type for
conversion.
int main() {
int num1 = 5;
double num2 = 2.5;
double result = (double)num1 + num2;
printf("Result: %lf\n", result);
return 0;
}
Unit II
Topics to be Discussed:
Computational Problems: If, If-else, Nested If, Switch-case, Ternary Operator, Goto,
Iteration with For, While, Do-while, Break, Continue, Standard Problems [GCD, Finding
Roots, Generating Factors of a Number, Checking for Leap Year], Number Series Problems
(Fibonacci Series, Natural Numbers, Even Numbers, Prime Numbers, Multiplication Table,
Palindrome Numbers).
A
Selection Statements / Control Statements
Selection statements, also known as control statements, play a crucial role in C programming
as they allow the program to make decisions and execute different code blocks based on
specific conditions. These statements are fundamental for creating programs that can adapt
to various situations and perform different actions as needed.
In C language, the control of the program flows from a given instruction to another. This type
of control flow that occurs from any given command to another is known as the sequential
control flow. Now, in any C program, a programmer might want to repeat some sets of
instructions or even skip the instructions when they are writing logic. Declarations in C, also
known as control declarations or decision-making, help them in making such decisions.
Conditional statements are used in the C programming language for making certain decisions
on the basis of the available conditions. These conditional statements get executed
sequentially in case no condition is present around the statements.
Importance of Selection Statements:
• Conditional Execution: Selection statements enable the program to execute specific
code blocks only when certain conditions are met. This conditional execution is
essential for building flexible and responsive programs. For example, you can use
selection statements to handle different cases or scenarios in your program.
• Decision-Making: They facilitate decision-making within the program. Based on the
evaluation of a condition, the program can choose to follow one path or another. This
is crucial for creating logic in the program, allowing it to choose the appropriate course
of action based on input or other factors.
• Branching: Selection statements provide branching capabilities, allowing the program
to branch out into different execution paths. This branching is essential for
implementing complex logic and handling various scenarios efficiently.
• Error Handling: They are often used for error handling in C programs. If an error
condition is encountered, a selection statement can be used to catch the error and
take appropriate corrective action, such as displaying an error message or logging the
issue.
• User Interaction: Selection statements are instrumental in creating interactive
programs. They can be used to process user input and respond accordingly. For
example, in a menu-driven program, selection statements can be used to determine
which menu option the user has chosen and execute the corresponding functionality.
• Control Flow: They control the flow of execution in a program. By using conditions
and decision-making constructs like if, else if, and else, you can design programs that
follow specific logic paths, ensuring that the code behaves as intended.
• Efficiency: Selection statements can improve program efficiency by allowing you to
execute only the necessary code based on conditions. This helps optimize resource
usage and reduce unnecessary computations, resulting in faster and more efficient
programs.
• Code Readability: Well-designed selection statements can make code more readable
and understandable. By using meaningful condition names and organizing code
logically, programmers can easily follow the program's logic and purpose.
In C programming, some common selection statements include:
• If Statement: Used for simple conditional execution.
• If-Else Statement: Used for branching between two code blocks based on a condition.
• Switch Statement: Used for multiple branching based on the value of an expression.
• Conditional (Ternary) Operator: Provides a concise way to make decisions in
expressions.
If Statements:
This type of statement would enable a programmer to choose various instruction sets on the
basis of the available condition. The instruction sets will only get executed when the
evaluation of the condition turns out to be true. In case the evaluation of the condition is
false, there will be an execution of a different instruction set. These are also known as decision
control statements.
Simple If Statement
A simple if statement is used to conditionally execute a block of code if a specified condition
is true.
Syntax:
if (condition)
{
// Code to be executed if the condition is true
}
Example 1:
#include <stdio.h>
int main()
{
int number = 5;
// Check if the number is positive
if (number > 0) {
printf("The number is positive.\n");
}
printf("This line is always executed.\n");
return 0;
}
Output:
The number is positive.
This line is always executed.
Explanation:
• In the example above, the program that checks whether a variable number is positive
using a simple if statement.
• The if statement begins with the keyword if, followed by a condition enclosed in
parentheses. In this case, the condition is number > 0, which checks if number is
greater than 0.
• If the condition in the parentheses is true, the block of code enclosed in curly braces
{} following the if statement is executed. In this case, it prints "The number is positive."
• After the if block, there is a printf statement outside of the if block. This statement is
not inside the if block's curly braces, so it is always executed, regardless of whether
the condition in the if statement is true or false.
• In the given example, since number is indeed greater than 0 (it's 5), the condition in
the if statement is true, and therefore, the code inside the if block is executed. As a
result, the program prints "The number is positive."
• After that, it prints "This line is always executed" because it's not part of the if block
and is executed unconditionally.
Example 2:
#include <stdio.h>
int main()
{
int age = 25;
// Check if the person is eligible to vote
if (age >= 18) {
printf("You are eligible to vote.\n");
}
printf("Thank you for checking your eligibility.\n");
return 0;
}
Output:
Enter your age: 20
You are eligible to vote.
Thank you for using our program.
The if statement begins with the keyword if, followed by a condition enclosed in parentheses.
In this case, the condition is age >= 18, which checks if the age is greater than or equal to
18, the legal voting age in many countries.
If the condition in the parentheses is true, the block of code enclosed in curly braces {}
following the if statement is executed. In this case, it prints "You are eligible to vote."
After the if block, there is a printf statement outside of the if block. This statement is not
inside the if block's curly braces, so it is always executed, regardless of whether the condition
in the if statement is true or false.
In the given example, the age is 25, which is indeed greater than or equal to 18. Therefore,
the condition in the if statement is true, and the code inside the if block is executed. As a
result, the program prints "You are eligible to vote."
After that, it prints "Thank you for checking your eligibility" because it's not part of the if
block and is executed unconditionally.
If-Else Statement
The if-else statement in C allows to conditionally execute one block of code if a specified
condition is true and another block of code if the condition is false.
Syntax:
if (condition) {
// Code to be executed if the condition is true
} else {
// Code to be executed if the condition is false
}
Example 1:
#include <stdio.h>
int main() {
int number = -3;
Output:
The number is non-positive (negative or zero).
This line is always executed.
Explanation:
• In this example, the C program checks whether a variable number is positive or non-
positive using an if-else statement.
• The if statement begins with the keyword if, followed by a condition enclosed in
parentheses. In this case, the condition is number > 0, which checks if number is
greater than 0.
• If the condition in the parentheses is true, the code inside the first set of curly braces
{} is executed. In this case, it prints "The number is positive."
• If the condition is false, the code inside the else block's curly braces is executed. Here,
it prints "The number is non-positive (negative or zero)."
• After either the if or else block is executed, the program continues to the next line,
which is outside both blocks and unconditionally prints "This line is always executed."
• In the given example, the value of number is -3, which is not greater than 0, so the
condition in the if statement is false. As a result, the program executes the code inside
the else block and prints "The number is non-positive (negative or zero)." After that, it
prints "This line is always executed."
Example 2:
#include <stdio.h>
int main() {
int score;
// Prompt the user for their exam score
printf("Enter your exam score: ");
scanf("%d", &score);
• In this program, the user is prompted to enter their exam score using the printf and
scanf functions.
• After reading the user's score into the score variable, we use an if-else statement to
check whether the score is passing, which in this case is defined as being greater than
or equal to 60. The condition is score >= 60.
• If the condition is true (i.e., the user's score is 60 or higher), the code inside the if
block is executed, which prints "Congratulations! You passed the exam."
• If the condition is false (i.e., the user's score is less than 60), the code inside the else
block is executed, which prints "Sorry, you did not pass the exam."
• After either the if or else block is executed, the program continues to the next line,
which is outside both blocks and unconditionally prints "Thank you for using our
program."
• In Scenario 1, where the user enters a score of 75, the condition in the if statement is
true, and the program prints "Congratulations! You passed the exam." before printing
the thank-you message.
• In Scenario 2, where the user enters a score of 45, the condition in the if statement is
false, and the program skips the code inside the if block. It then proceeds to execute
the code inside the else block, which prints "Sorry, you did not pass the exam,"
followed by the thank-you message.
Else-If Ladder
An "else-if ladder" statement in C is used to handle multiple conditions in a structured way.
It allows you to test multiple conditions in sequence and execute the code block associated
with the first true condition.
Syntax:
if (condition1) {
// Code to be executed if condition1 is true
} else if (condition2) {
// Code to be executed if condition2 is true
} else if (condition3) {
// Code to be executed if condition3 is true
}
// ...
else {
// Code to be executed if none of the conditions are true
}
Example 1:
#include <stdio.h>
int main() {
int score;
// Prompt the user for their exam score
printf("Enter your exam score: ");
scanf("%d", &score);
// Check and display the grade based on the score
if (score >= 90) {
printf("Your grade is A.\n");
} else if (score >= 80) {
printf("Your grade is B.\n");
} else if (score >= 70) {
printf("Your grade is C.\n");
} else if (score >= 60) {
printf("Your grade is D.\n");
} else {
printf("Your grade is F (Fail).\n");
}
printf("Thank you for using our program.\n");
return 0;
}
Output:
Enter your exam score: 95
Your grade is A.
Thank you for using our program.
• If none of the conditions in the ladder are true, the else block is executed, which
means the score is less than 60, and it prints "Your grade is F (Fail)."
• After printing the grade message, the program always prints "Thank you for using our
program."
Example 2:
#include <stdio.h>
int main() {
int day;
// Prompt the user for a day of the week (1-7)
printf("Enter a day of the week (1-7): ");
scanf("%d", &day);
Switch-Case
The switch-case statement in C is used to evaluate the value of an expression against a series
of possible constant values (cases). It allows the program to execute different code blocks
based on the value of the expression.
A switch statement is a multi-way type of selection statement that would resolve this issue.
The switch declaration comes into play when more than three alternatives (conditions) exist
in a program. This command then switches between all the available blocks on the basis of
the expression value. Then, each block has a corresponding value with it.
Syntax:
switch (expression) {
case constant1:
// Code to be executed if expression matches constant1
break;
case constant2:
// Code to be executed if expression matches constant2
break;
default:
// Code to be executed if expression doesn't match any case
}
Example 1:
#include <stdio.h>
int main() {
int day;
// Check and display the corresponding day name using a switch-case statement
switch (day) {
case 1:
printf("Sunday\n");
break;
case 2:
printf("Monday\n");
break;
case 3:
printf("Tuesday\n");
break;
case 4:
printf("Wednesday\n");
break;
case 5:
printf("Thursday\n");
break;
case 6:
printf("Friday\n");
break;
case 7:
printf("Saturday\n");
break;
default:
printf("Invalid input. Please enter a number between 1 and 7.\n");
}
return 0;
}
Output:
Enter a day of the week (1-7): 3
Tuesday
Thank you for using our program.
Example 2:
#include <stdio.h>
int main() {
int month;
// Prompt the user to enter a month number (1-12)
printf("Enter a month number (1-12): ");
scanf("%d", &month);
// Check and display the name of the month using a switch-case statement
switch (month) {
case 1:
printf("January\n");
break;
case 2:
printf("February\n");
break;
case 3:
printf("March\n");
break;
case 4:
printf("April\n");
break;
case 5:
printf("May\n");
break;
case 6:
printf("June\n");
break;
case 7:
printf("July\n");
break;
case 8:
printf("August\n");
break;
case 9:
printf("September\n");
break;
case 10:
printf("October\n");
break;
case 11:
printf("November\n");
break;
case 12:
printf("December\n");
break;
default:
printf("Invalid input. Please enter a number between 1 and 12.\n");
}
printf("Thank you for using our program.\n");
return 0;
}
Output:
Enter a month number (1-12): 3
March
Thank you for using our program.
Example 3:
#include <stdio.h>
int main() {
char grade;
// Check and display a message based on the entered grade using a switch-case statement
switch (grade) {
case 'A':
case 'a':
printf("Excellent! You got an A.\n");
break;
case 'B':
case 'b':
printf("Good job! You got a B.\n");
break;
case 'C':
case 'c':
printf("You got a C. It's an average grade.\n");
break;
case 'D':
case 'd':
printf("You got a D. You need to improve.\n");
break;
case 'F':
case 'f':
printf("You got an F. You did not pass.\n");
break;
default:
printf("Invalid grade. Please enter A, B, C, D, or F.\n");
}
printf("Thank you for using our program.\n");
return 0;
}
Output:
Enter your grade (A, B, C, D, or F): B
Good job! You got a B.
Thank you for using our program.
• If grade doesn't match any of the cases in the switch statement, the program executes
the code block inside the default case, which prints "Invalid grade. Please enter A, B,
C, D, or F."
• After printing the appropriate message or the error message, the program always
prints "Thank you for using our program."
• This switch-case statement allows the program to provide feedback to the user based
on the entered grade while also handling different letter case variations. It's an
effective way to process and respond to character-based input.
int main() {
int num1, num2;
return 0;
}
Output:
Enter the first number: 8
Enter the second number: 3
The largest number is: 8
Enter the first number: 15
Enter the second number: 20
The largest number is: 20
Explanation:
• It prompts the user to enter two numbers, num1 and num2.
• The conditional operator (num1 > num2) ? num1 : num2 is used to compare num1
and num2. If num1 is greater than num2, it assigns the value of num1 to the largest
variable; otherwise, it assigns the value of num2 to largest. This effectively determines
the largest of the two numbers.
• Finally, it displays the value of the largest number using printf.
Example 2:
#include <stdio.h>
int main() {
int num1, num2, num3;
: num3);
return 0;
}
Output:
Enter the first number: 8
Enter the second number: 3
Enter the third number: 12
The largest number is: 12
The program uses nested conditional (ternary) operators to efficiently compare the three input
numbers and assign the largest among them to the largest variable. This allows you to easily
determine and display the largest number among any set of three numbers provided as input.
Explanation:
• The program prompts the user to enter three numbers: num1, num2, and num3.
• We use nested conditional operators to compare the three numbers:
• The first conditional operator (num1 > num2) ? ... compares num1 and num2. If num1
is greater than num2, it proceeds to the next nested conditional (num1 > num3) ?
num1 : num3. If num1 is not greater than num2, it evaluates (num2 > num3) ? num2
: num3. This way, we determine whether num1 or num2 is the largest.
• In the nested condition (num1 > num3) ? num1 : num3, we compare num1 and num3.
If num1 is greater than num3, it assigns the value of num1 to largest. Otherwise, it
assigns the value of num3 to largest.
• Similarly, in the nested condition (num2 > num3) ? num2 : num3, we compare num2
and num3. If num2 is greater than num3, it assigns the value of num2 to largest.
Otherwise, it assigns the value of num3 to largest.
• Finally, the program displays the value of the largest number in the largest variable.
• This nested conditional operator structure allows us to determine the largest of the
three numbers efficiently. The program compares each pair of numbers sequentially,
ensuring that the largest variable ultimately holds the value of the largest number
among the three provided by the user.
Goto
The goto statement in C is used for transferring program control to a labeled statement within
the same function. It is required in very rare and specific situations when other control
structures like loops (for, while, do-while) and conditional statements (if, else, switch) are not
suitable for achieving the desired control flow. The goto statement should be used sparingly
and with caution, as it can make the code less readable and harder to maintain if used
improperly.
Syntax:
label_name:
// Statements
// ...
goto label_name;
Example 1:
#include <stdio.h>
int main() {
int count = 1;
start:
if (count <= 5) {
printf("Count: %d\n", count);
count++;
goto start; // Jump back to the "start" label
}
return 0;
}
Output:
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
Explanation:
• We have a labeled statement named start followed by a colon (start:). This creates a
label where program control can be transferred.
• Inside the main function, we initialize a variable count to 1.
• We use a goto statement to jump to the start label. This creates a loop-like behavior,
repeatedly printing the value of count as long as it is less than or equal to 5.
• Within the loop, we check if count is less than or equal to 5. If it is, we print the value
of count, increment it, and then use the goto statement to jump back to the start
label, effectively creating a loop.
• The loop continues until count becomes greater than 5, at which point the program
exits.
Example 2:
#include <stdio.h>
int main() {
int i = 1;
loop_start:
if (i <= 5) {
printf("Iteration %d\n", i);
i++;
if (i == 4) {
goto skip_iteration;
}
goto loop_start;
}
skip_iteration:
printf("Iteration 4 is skipped.\n");
return 0;
}
Output:
Iteration 1
Iteration 2
Iteration 3
Iteration 4 is skipped.
Iteration 5
Explanation:
• We have a labeled statement named loop_start followed by a colon (loop_start:). This
creates a label where program control can be transferred.
• Inside the main function, we initialize an integer variable i to 1.
• We use a goto statement to jump to the loop_start label, creating a loop-like behavior.
The loop prints the value of i and increments it as long as i is less than or equal to 5.
• Within the loop, we check if i is equal to 4. If it is, we use another goto statement to
jump to the skip_iteration label, effectively skipping the iteration when i is 4.
• After skipping the iteration, we continue with the loop and print the value of i when
it's not equal to 4.
• The loop completes when i becomes greater than 5, and the program proceeds to the
printf statement after the skip_iteration label.
This example demonstrates how the goto statement can be used to skip specific iterations
within a loop, providing fine-grained control over the flow of the program. However, it's
important to note that such use cases should be rare, and careful consideration should be
given to maintain code readability and avoid potential issues like infinite loops.
statement next to the loop is executed. So for such a construct, the statements associated
with the construct may not be executed even once.
In the post-test loop, the code is always executed once. At the completion of the loop code,
the test expression is tested. If the test expression evaluates to true, the loop repeats; if the
expression is false the loop terminates.
C Programming has three loop constructs: while, for, and do-while. The first two are pre-test
loops and do-while is a post-test loop. In addition to the test expression, two other processes
are associated with almost all loops. These are initialization and updating. The test expression
always involves a variable, which is known as a loop control variable. Initialization is the
statement that assigns the initial value to the loop control variable.
While
while statement is a pre-test loop. It uses a test expression to control the loop. Since it is a
pre-test loop, it evaluates the test expression before every iteration of the loop.
stmT will be executed repeatedly till the value of TestExpr becomes 0 (false). stmT may be a
single statement or multiple statements terminated by a semicolon.
To use the while statement, the test expression should contain a loop control variable. The
initialization of the loop control variable has to be done before the loop starts and updating
must be included in the body of the loop.
Syntax:
while (condition) {
// Code to be executed as long as the condition is true
}
Example 1:
#include <stdio.h>
int main() {
int count = 1;
// Syntax of the while loop:
// The loop continues as long as the condition (count <= 5) is true
while (count <= 5) {
printf("Count: %d\n", count);
count++; // Increment count by 1 in each iteration
}
return 0;
}
Output:
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
The while loop allows to execute the code block repeatedly as long as the condition (count <=
5) was true.
Explanation:
• An integer variable count is Declared to be used as loop control variable.
• Inside the main function, set up a while loop:
o Condition: The loop will continue as long as count is less than or equal to 5.
• Inside the loop, use printf to display the current value of count.
• After displaying the value of count, increment it by 1 using the count++ statement.
This step is crucial to ensure that the loop eventually terminates when the condition
becomes false.
• The loop continues to execute until count reaches 6. After count becomes 6, the
condition count <= 5 is no longer true, and the loop terminates.
Example 2:
#include <stdio.h>
int main()
{
int c;
c=5; // Initialization
while(c>0)
{ // Test Expression
printf(“ \n %d”,c);
c=c-1; // Updating
}
return 0;
}
Output:
This loop contains all the parts of a while loop. When executed in a program, this loop will
output.
5
4
3
2
1
Explanation:
First, the loop initialization, with ‘c’ being assigned the value of 5, is carried out. Then, the
instructions within the while construct are executed repetitively so long as the test
expression, c > 0, is true. The moment the test expression in the while construct evaluates
as false, the program is terminated.
Now, when the while statement is encountered, the test expression, similar to an if-test
expression, is evaluated. In this case, since c is 5 and c > 0, the test expression evaluates to
true. Hence the statement body of the loop is executed sequentially. A printf statement writes
the current value of c on the screen. After this, c is updated by subtracting 1. Thus, c now
has the value of 4. On reaching the end of the loop, the loop condition is checked again. If it
is true, which it is because 4 > 0, the loop is executed once again. In a similar way, the loop
is executed five times.
At the end of the fifth iteration, c has the value of 0 for which the condition will fail since 0 is
not greater than 0. Thus the term loop being applied to this repeating control structure can
be understood since all statements inside the while loop construct will be executed several
times until the condition has failed.
Do- While
The do-while loop is another type of iterative statement in C programming. It is similar to the
while loop but with one crucial difference: the do-while loop always executes its block of code
at least once, and then it checks the condition to determine whether to continue or terminate.
Syntax:
do {
// Code to be executed at least once
} while (condition);
Example 1:
#include <stdio.h>
int main() {
int count = 1;
return 0;
}
Output:
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
The do-while loop ensures that the code block inside it is executed at least once, making it
useful when you need to guarantee the execution of certain code before checking a condition
for repetition.
Explanation:
• Inside the main function, set up a do-while loop:
o The code block inside the loop is executed unconditionally, without checking
the condition initially.
• Inside the loop, use printf to display the current value of count.
• After displaying the value of count, we increment it by 1 using the count++ statement.
This step is crucial to ensure that the loop eventually terminates when the condition
in the while part becomes false.
• After the code block is executed, the loop checks the condition count <= 5. If the
condition is true, the loop continues to execute. If it's false, the loop terminates.
• The loop continues to execute until count reaches 6. After count becomes 6, the
condition count <= 5 becomes false, and the loop terminates.
Example 2:
#include <stdio.h>
int main()
{
int c=5;
do
{
printf(“Hello”);
c++;
} while(c<5);
return 0;
}
Output:
Hello
The statements within the loop are executed at least once.
For
A loop formed by using the for statement is generally called a determinate or definite loop
because the programmer knows exactly how many times it will repeat. The number of
repetitions can be determined mathematically by manually checking the logic of the loop.
Syntax:
for (initialization; condition; update) {
// Code to be executed repeatedly as long as the condition is true
}
Initialization: This part of the loop is the first to be executed. The statement(s) of this part
are executed only once. This statement involves a loop control variable.
TestExpr TestExpr represents a test expression that must be true for the loop to continue
execution.
stmT stmT is a single or block of statements.
Updating: The statements contained here are executed every time through the loop before
the loop condition is tested. This statement also involves a loop control variable.
Example 1:
int main(void)
{
int i;
for(i = 0; i < 10; i++)
printf(“%d”,i);
return 0’
}
Output:
0123456789
Explanation:
1. Set i equal to 0.
2. If i is less than 10, execute the body of the loop, that is, ‘printf’ and go to step 3;
otherwise, go to the next instruction after the for loop and continue.
3. Increment i.
4. Go to step 2.
Example 2:
#include <stdio.h>
int main()
{
int c, s=0, n;
printf(“\n Enter the No. of terms”);
scanf(“%d”, &n);
for(c=1; c<=n; c++)
s+=c;
printf(“\n Sum is %d”, s);
return 0;
}
Output:
Enter the No. of terms: 7
Sum is :28
Explanation:
• #include <stdio.h>: This line includes the standard input/output library, which is
necessary to use functions like printf and scanf.
• int main(): This is the main function where the execution of the program begins.
• int c, s=0, n;: Here, three integer variables are declared:
o c: It is used as a loop counter.
o s: This variable will store the sum of the natural numbers.
o n: It will store the user's input for the number of terms to calculate the sum
for.
• printf("\n Enter the No. of terms: ");: This line displays a message asking the user to
enter the number of terms they want to find the sum for. The \n adds a newline
character for better formatting.
• scanf("%d", &n);: This line reads an integer input from the user and stores it in the
variable n. The %d in scanf is a format specifier for integers, and &n is used to store
the entered value in the variable n.
• for(c=1; c<=n; c++): This line starts a for loop that will run 'n' times, from 1 to 'n'. The
loop counter is 'c'.
• s += c;: Inside the loop, this statement adds the current value of 'c' to the 's' variable.
It accumulates the sum of natural numbers.
• printf("\n Sum is :%d", s);: After the for loop finishes, this line prints the sum of the
first 'n' natural numbers using printf. The %d is a format specifier for integers, and it
is replaced with the value of the 's' variable.
• return 0;: This line indicates that the program has finished executing and returns a
status code of 0 to the operating system, indicating a successful execution.
Break
Break statement is used to exit a loop prematurely. It is often used within for, while, or do-
while loops to break out of the loop based on a certain condition.
Program:
#include <stdio.h>
int main() {
int i;
Continue
In C programming, the continue statement is used to skip the remaining code within the
current iteration of a loop and proceed to the next iteration. It is typically used within loops
like for or while to control the flow of execution.
Program:
#include <stdio.h>
int main() {
// Print even numbers from 1 to 10 using a for loop
printf("Even numbers from 1 to 10:\n");
for (int i = 1; i <= 10; i++) {
// Check if the number is odd; if so, skip to the next iteration
if (i % 2 != 0) {
continue;
}
printf("%d\n", i);
}
return 0;
}
Output:
Even numbers from 1 to 10:
2
4
6
8
10
• The program starts a for loop from 1 to 10.
• For each value of i, it checks if i is an odd number using the condition i % 2 != 0.
• If i is odd, the continue statement is executed, and the program skips the printf
statement.
• If i is even, the printf statement is executed, and the even number is printed.
• This process repeats for each value of i from 1 to 10, resulting in the display of even
numbers only.
Explanation:
• We include the <stdio.h> header for input and output functions.
• In the main function, we use a for loop to iterate from 1 to 10 using the loop variable
i.
• Within the loop, we check if i is an odd number using the condition if (i % 2 != 0). If i
is odd (i.e., the remainder when dividing by 2 is not 0), we execute the continue
statement.
• The continue statement causes the program to skip the remaining code within the
current iteration of the loop and move on to the next iteration.
• If i is an even number, we print it using printf("%d\n", i);. However, if i is odd, the
continue statement will skip this printf statement.
Standard Problems
Greatest Common Divisor
The GCD of two numbers, let's call them 'a' and 'b', is the largest positive integer that divides
both 'a' and 'b' without leaving a remainder. There are several methods to calculate the GCD,
but one of the most common and efficient ones is the Euclidean algorithm.
The Euclidean algorithm is based on the principle that the GCD of 'a' and 'b' is the same as
the GCD of 'b' and the remainder of 'a' divided by 'b'.
GCD(a, b) = GCD(b, a % b)
This process is repeated until 'b' becomes zero. When 'b' becomes zero, the GCD is found,
and it is equal to the value of 'a' at that point.
Program:
#include <stdio.h>
int main() {
int num1, num2;
return 0;
}
Output:
Enter two numbers: 36 48
GCD of 36 and 48 is 12
Explanation:
• We include the standard input-output library (stdio.h) to use functions like printf and
scanf.
• We define a function gcd that calculates the GCD of two integers 'a' and 'b' using the
Euclidean algorithm. If 'b' is zero, it returns 'a'; otherwise, it calls itself recursively
with 'b' and 'a % b'.
• In the main function:
o We declare two integer variables num1 and num2 to store the input numbers.
o We prompt the user to input two numbers using printf and read them using
scanf.
• We calculate the GCD by calling the gcd function with num1 and num2 as arguments
and store the result in the result variable.
• Finally, we display the GCD using printf.
Finding Roots
A quadratic equation is an equation of the form:
ax2 + bx + c = 0
Where 'a', 'b', and 'c' are constants, and 'x' is the variable we want to solve for. The solutions
for 'x', also known as roots, can be found using the quadratic formula:
−𝑏 ± √𝑏 2 − 4𝑎𝑐
𝑥=
2𝑎
Working Strategy:
• Calculate the discriminant, which is the value inside the square root: D = b^2 - 4ac.
• If the discriminant is positive (D > 0), there are two real roots.
• If the discriminant is zero (D = 0), there is one real root (a repeated root).
• If the discriminant is negative (D < 0), there are no real roots (two complex roots).
Program:
#include <stdio.h>
#include <math.h>
int main() {
float a, b, c;
return 0;
}
Output:
Enter coefficients a, b, and c: 1 -3 2
Two real roots: 2.000000 and 1.000000
Explanation:
• We include the standard input-output library (stdio.h) and the math library (math.h)
to use mathematical functions like sqrt.
• We define a function findRoots that takes the coefficients 'a', 'b', and 'c' as input and
calculates the roots based on the discriminant.
• In the main function:
o We declare three floating-point variables a, b, and c to store the coefficients of
the quadratic equation.
o We prompt the user to input these coefficients using printf and read them
using scanf.
• We call the findRoots function with the input coefficients 'a', 'b', and 'c' to calculate
and display the roots based on the discriminant.
Generating Factors of a Number
Factors of a number are the integers that evenly divide that number without leaving a
remainder. In other words, if 'a' and 'b' are integers, and 'a' divides 'b' without a remainder,
then 'a' is a factor of 'b'.
To find the factors of a number 'n', you can start by iterating from 1 up to 'n', and for each
number 'i' in that range, check if 'n' is divisible by 'i'. If it is, then 'i' is a factor of 'n'.
int main() {
int number;
// Input a number
printf("Enter a number: ");
scanf("%d", &number);
return 0;
}
Output:
Enter a number: 12
Factors of 12 are: 1 2 3 4 6 12
Explanation:
• We include the standard input-output library (stdio.h) to use functions like printf and
scanf.
• We define a function findFactors that takes an integer num as input and finds and
displays its factors using a for loop. It iterates from 1 to num and checks if each
number in that range is a factor of num.
• In the main function:
o We declare an integer variable number to store the input number.
o We prompt the user to input a number using printf and read it using scanf.
• We call the findFactors function with the input number to find and display its factors.
If (year % 4 == 0) and (year % 100 != 0) OR (year % 400 == 0), then it's a leap year.
Program:
#include <stdio.h>
int main() {
int year;
// Input a year
printf("Enter a year: ");
scanf("%d", &year);
return 0;
}
Output:
Enter a year: 2024
2024 is a leap year.
Explanation:
• We include the standard input-output library (stdio.h) to use functions like printf and
scanf.
• We define a function isLeapYear that takes an integer year as input and returns 1 if
it's a leap year and 0 if it's not. The function follows the leap year rules explained
earlier.
• In the main function:
o We declare an integer variable year to store the input year.
o We prompt the user to input a year using printf and read it using scanf.
• We call the isLeapYear function with the input year and check its return value. If it's
1, we print that the year is a leap year; otherwise, we print that it's not a leap year.
F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2) for n >= 2
F(0) and F(1) are defined as the first two Fibonacci numbers.
To calculate the nth Fibonacci number (where n >= 2), you add the (n-1)th and (n-2)th
Fibonacci numbers.
Example:
To calculate the 6th Fibonacci number (F(6)), you would use the formula:
F(6) = F(5) + F(4)
Now, F(5) can be calculated as:
F(5) = F(4) + F(3)
Continue this process until you reach the base cases (F(0) and F(1)), and you can calculate
F(6) as follows:
F(6) = F(5) + F(4)
F(6) = (F(4) + F(3)) + (F(3) + F(2))
F(6) = ((F(3) + F(2)) + (F(2) + F(1))) + ((F(2) + F(1)) + F(1))
F(6) = (((F(2) + F(1)) + (F(1) + F(0))) + ((F(1) + F(0)) + F(1))) + ((F(1) + F(0)) + F(1))
F(1) = 1
So, F(6) is 8.
Program:
#include <stdio.h>
int main() {
int n;
printf("Enter the number of terms for Fibonacci series: ");
scanf("%d", &n);
return 0;
}
Output:
Enter the number of terms for Fibonacci series: 10
Fibonacci Series up to 10 terms:
0 1 1 2 3 5 8 13 21 34
Explanation:
• We include the standard input/output library, <stdio.h>, to handle input and output
operations.
• We define a function fibonacci(int n) that calculates the nth Fibonacci number
recursively. The base case checks if n is less than or equal to 1, in which case it
Natural Numbers
Generating natural numbers within a specified range involves basic arithmetic and iteration.
Natural numbers are positive integers starting from 1 and continuing indefinitely. To generate
natural numbers within a given range, you need to specify the starting and ending points and
then iterate through them to obtain each natural number within that range.
Specify the starting point (lower bound) and ending point (upper bound) for the range of
natural numbers you want to generate.
Use a loop to iterate from the starting point to the ending point.
At each iteration, you obtain a natural number within the specified range.
Example:
Suppose you want to generate natural numbers within the range from 5 to 10.
Mathematically, the range can be defined as follows:
Natural numbers between 5 and 10: {5, 6, 7, 8, 9, 10}
You can achieve this by iterating from 5 to 10 and obtaining each natural number in the
range.
Program:
#include <stdio.h>
int main() {
int lowerBound, upperBound;
generateNaturalNumbers(lowerBound, upperBound);
return 0;
}
Output:
Enter the lower bound of the range: 5
Enter the upper bound of the range: 10
Natural numbers in the range 5 to 10:
5 6 7 8 9 10
Explanation:
• We include the standard input/output library, <stdio.h>, to handle input and output
operations.
• We define a function generateNaturalNumbers(int start, int end) that generates and
prints natural numbers in the specified range. It takes two arguments, start (the lower
bound) and end (the upper bound), and uses a for loop to iterate from start to end,
printing each number in the range.
• In the main() function:
o We declare variables lowerBound and upperBound to store the lower and
upper bounds of the range.
o We prompt the user to enter the lower and upper bounds.
• We call the generateNaturalNumbers function with the provided lower and upper
bounds to generate and print the natural numbers within the specified range.
Even Numbers
Determining even numbers within a specified range involves basic arithmetic and the concept
of divisibility by 2. An even number is an integer that is exactly divisible by 2, meaning there
is no remainder when it is divided by 2. To determine even numbers within a given range,
you need to specify the starting and ending points and then check each number in that range
to see if it's even or not.
• Specify the starting point (lower bound) and ending point (upper bound) for the range
of numbers you want to check for evenness.
• Use a loop to iterate from the starting point to the ending point.
• For each number in the range, check if it is divisible by 2 (i.e., there is no remainder
when divided by 2).
• If a number meets the condition, it is an even number.
Example:
Suppose you want to determine even numbers within the range from 4 to 10.
You can achieve this by iterating from 4 to 10 and checking if each number is divisible by 2.
Program:
#include <stdio.h>
int main() {
int lowerBound, upperBound;
determineEvenNumbers(lowerBound, upperBound);
return 0;
}
Output:
Enter the lower bound of the range: 4
Enter the upper bound of the range: 10
Even numbers in the range 4 to 10:
4 6 8 10
Explanation:
• We include the standard input/output library, <stdio.h>, to handle input and output
operations.
• We define a function determineEvenNumbers(int start, int end) that determines and
prints even numbers in the specified range. It takes two arguments, start (the lower
bound) and end (the upper bound), and uses a for loop to iterate from start to end.
Inside the loop, it checks if each number is even (i.e., divisible by 2) using the modulo
operator (%).
• In the main() function:
o We declare variables lowerBound and upperBound to store the lower and
upper bounds of the range.
o We prompt the user to enter the lower and upper bounds.
• We call the determineEvenNumbers function with the provided lower and upper
bounds to determine and print even numbers within the specified range.
Prime Numbers
Determining whether a given number is prime involves basic arithmetic and divisibility
checks. A prime number is a positive integer greater than 1 that has exactly two distinct
positive divisors: 1 and itself. To determine if a number is prime, you need to check if it is
divisible by any integer other than 1 and itself.
If the given number is less than or equal to 1, it cannot be prime because prime numbers
start from 2.
For a number n greater than 1, check if it is divisible by any integer from 2 to the square root
of n. If n is divisible by any of these integers, it is not prime. Otherwise, it is prime.
If the number is not divisible by any integer other than 1 and itself, it is considered prime.
Example:
Suppose you want to determine whether the number 17 is prime.
• Start with the number 17.
• Check if it is less than or equal to 1. Since 17 is greater than 1, continue to the next
step.
• Check if 17 is divisible by any integer from 2 to the square root of 17, which is
approximately 4.12 (rounded up to 5 for simplicity). We check divisibility by 2, 3, 4,
and 5.
o 17 is not divisible by 2 (17 % 2 = 1).
o 17 is not divisible by 3 (17 % 3 = 2).
o 17 is not divisible by 4 (17 % 4 = 1).
o 17 is not divisible by 5 (17 % 5 = 2).
• Since 17 is not divisible by any integer other than 1 and itself, it is a prime number.
Program:
#include <stdio.h>
#include <stdbool.h> // Include the standard library for Boolean data type
if (n <= 1) {
return false; // Numbers less than or equal to 1 are not prime
}
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
return false; // If n is divisible by any integer from 2 to sqrt(n), it's not prime
}
}
return true; // If no divisors are found, n is prime
}
int main() {
int num;
if (isPrime(num)) {
printf("%d is a prime number.\n", num);
} else {
printf("%d is not a prime number.\n", num);
}
return 0;
}
This program takes a positive integer input from the user, determines whether it is prime
using the isPrime function, and then prints the result. In the example, the number 17 is
determined to be prime.
Output:
Enter a positive integer: 17
17 is a prime number.
Explanation:
• We include the standard input/output library, <stdio.h>, and the stdbool.h library to
use the Boolean data type (bool).
• We define a function isPrime(int n) that takes an integer n as input and returns a
Boolean value (true if n is prime, false otherwise).
o If n is less than or equal to 1, it returns false because numbers less than or
equal to 1 are not prime.
o We use a for loop to iterate from 2 up to the square root of n (rounded up to
the nearest integer). If n is divisible by any integer in this range, it returns
false. Otherwise, it returns true.
• In the main() function:
int main() {
int lowerBound, upperBound;
determineEvenNumbers(lowerBound, upperBound);
return 0;
}
Output:
Enter the lower bound of the range: 4
Enter the upper bound of the range: 10
Even numbers in the range 4 to 10:
4 6 8 10
Explanation:
• We include the standard input/output library, <stdio.h>, to handle input and output
operations.
• We define a function determineEvenNumbers(int start, int end) that determines and
prints even numbers in the specified range. It takes two arguments, start (the lower
bound) and end (the upper bound), and uses a for loop to iterate from start to end.
Inside the loop, it checks if each number is even (i.e., divisible by 2) using the modulo
operator (%).
• In the main() function:
o We declare variables lowerBound and upperBound to store the lower and
upper bounds of the range.
o We prompt the user to enter the lower and upper bounds.
• We call the determineEvenNumbers function with the provided lower and upper
bounds to determine and print even numbers within the specified range.
Multiplication Table
Program:
#include <stdio.h>
int main() {
int num, limit;
displayMultiplicationTable(num, limit);
return 0;
}
This program takes user input for a number and a limit, and then it displays the
multiplication table for the specified number up to the specified limit. In the example
provided, it displays the multiplication table for 5 up to 10.
Output:
Enter a number: 5
Enter the limit: 10
Multiplication table for 5 up to 10:
5x1=5
5 x 2 = 10
5 x 3 = 15
5 x 4 = 20
5 x 5 = 25
5 x 6 = 30
5 x 7 = 35
5 x 8 = 40
5 x 9 = 45
5 x 10 = 50
Explanation:
• We include the standard input/output library, <stdio.h>, to handle input and output
operations.
• We define a function displayMultiplicationTable(int number, int limit) that displays
the multiplication table for a given number up to a specified limit. It takes two
arguments, number (the number for which the table is generated) and limit (the
highest value up to which the table is displayed). Inside the function, we use a for
loop to iterate from 1 to limit and print each multiplication expression along with the
result.
• In the main() function:
o We declare variables num and limit to store the user's input for the number
and the limit of the multiplication table.
o We prompt the user to enter a number and a limit.
• We call the displayMultiplicationTable function with the provided number and limit
to display the multiplication table.
Palindrome Numbers
To determine whether a given number is a palindrome, you need to understand the concept
of palindromes and perform some mathematical operations. A palindrome is a number or a
sequence of characters (such as a word) that reads the same forward and backward. For
numbers, this means that when you reverse the digits, the number remains the same.
• Extract the individual digits from the given number.
• Reverse the order of the digits.
• Compare the reversed number with the original number.
• If the reversed number is the same as the original number, it's a palindrome;
otherwise, it's not.
Example:
int main() {
int number;
if (isPalindrome(number)) {
printf("%d is a palindrome.\n", number);
} else {
printf("%d is not a palindrome.\n", number);
}
return 0;
}
This program takes a number as input from the user, checks whether it is a palindrome using
the isPalindrome function, and then prints the result. In the example provided, it correctly
identifies 121 as a palindrome.
Output:
Enter a number: 121
121 is a palindrome.
Explanation:
• We include the standard input/output library, <stdio.h>, to handle input and output
operations.
• We define a function isPalindrome(int num) that takes an integer num as input and
returns an integer:
o Inside the function, we declare two variables, reversedNum and originalNum,
to store the reversed number and the original number, respectively.
o We use a while loop to extract the individual digits from the original number,
reverse them, and store the result in reversedNum.
o We compare reversedNum with originalNum and return the result as 1 if they
are equal (indicating a palindrome) or 0 if they are not.
• In the main() function:
o We declare a variable number to store the user's input.
o We prompt the user to enter a number.
o We call the isPalindrome function with the provided number and print whether
the number is a palindrome or not based on the integer value returned by the
function
Unit III
Topics to be Discussed:
Arrays: One- and Two-Dimensional Arrays, Creating, Accessing and Manipulating Elements
of Arrays, Row/Column Major Formats, Standard Problems (Addition and Multiplication of
Two Matrixes, Mean, Variance, SD, Maximum and Minimum Elements using Arrays).
Functions: Declaring a Function, Signature of a Function, Passing Parameters to Functions,
Passing Arrays to Functions, Recursion, Standard Problems [Factorial of a Given Number,
Sum of Natural Numbers using Recursion), External, Auto, Local, Static, Register Variables.
Arrays
The variables used so far have all had a common characteristic: each variable can only be
used to store a single value at a time. For example, each of the variables ch, n, and price
declared in the statements
char ch;
int n;
float price;
are of different data types and each variable can only store one value of the declared data
type. These types of variables are called scalar variables. A scalar variable is a single variable
whose stored value is an atomic type. This means that the value cannot be further subdivided
or separated into a legitimate data type.
Memory Allocation to Identifiers
In contrast to atomic types, such as integer, floating point, and double precision data, there
are aggregate types. An aggregate type, which is referred to as both a structured type and a
data structure, is any type whose values can be decomposed and are related by some defined
structure. Additionally, operations must be available for retrieving and updating individual
values in the data structure. Such a derived data type is an array.
Why We Need Arrays?
Consider a brand-new problem: a program that can print its input in reverse order. If there
are two values, this is easy and the program is given below:
#include <stdio.h>
int main()
{
int v1, v2;
printf(“Enter two values:”);
scanf(“%i %i”, &v1, &v2);
printf(“%i\n%i\n”, v2, v1);
return 0;
}
If there are three values, this is still relatively easy and the program is given below:
#include <stdio.h>
int main()
{
int v1, v2, v3;
printf(“Enter three values: ”);
scanf(“%d %d %d”, &v1, &v2, &v3);
printf(“%d\n %d\n %d \n”, v3, v2, v1);
return 0;
}
But what if there are ten or twenty or one hundred values? Then it is not so easy.
Besides that, the solutions work only if the number of inputs exactly matches with those
expected by the user. Consider another problem: the average of n integer numbers given by
the user can easily be computed as follows.
#include <stdio.h>
int main()
{
int count,s=0, n, num;
float avg;
printf(“\n How many numbers?”);
scanf(“%d”, &n);
for(count=1;count<=n;++count)
{
printf(“\n Enter the Number:”);
scanf(“%d”, &num);
s+=num;
}
avg=(float)s/n;
printf(“Average is %f”, avg);
return 0;
}
Now if the problem is given as ‘Print the numbers that are greater than the average’, then one
solution is to read the numbers twice, i.e.,
• Read in all the numbers and calculate the average.
• Read in all the numbers again, this time checking each as it is read against a
previously calculated average.
If input is from the keyboard, then the user has to enter each number twice and accurately,
with no mistakes. This is not a viable solution. Because, for 25 numbers entered, the user
has to remember all the numbers. But what if there are 50 or 100 numbers? Then, it is not
so easy. To solve this problem, an array is required. It is a collection of numbered elements.
An array is a fundamental data structure that enables the storing and manipulation of
potentially huge quantities of data. An array stores an ordered sequence of homogeneous
values.
Homogeneous means that all the values are of the same data type. The order of the values
are also preserved, i.e., the integer array {1, 2, 3, 4} is different from {1, 4,
3, 2}.
An array can be defined as a data structure consisting of an ordered set of data values of the
homogeneous (same) type.
In C, each array has two fundamental properties: the data type and the size. Individual array
elements are identified by an integer index. In C, the index begins at zero and is always
written inside square bracket.
Syntax and Array Visualization:
data_type array_name[array_size];
• data_type is the type of data that the array will hold, such as int, float, char, etc.
• array_name is the name you give to the array.
• array_size is the number of elements the array can hold. It must be a positive integer.
Sample Program:
#include <stdio.h>
int main() {
// Declare an integer array with 5 elements
int numbers[5];
return 0;
}
Explanation:
• We include the <stdio.h> header for input and output functions.
• We declare an integer array numbers with a size of 5. This means it can hold 5 integer
values.
• We initialize each element of the array with values 10, 20, 30, 40, and 50, respectively.
• We use printf to print the elements of the array. The %d format specifier is used to
print integers.
• Finally, we return 0 from the main function to indicate successful program execution.
• When you run this program, it will display the values of the array elements on the
screen.
Sample Program:
#include <stdio.h>
int main() {
// Declare and initialize an integer array
int numbers[] = {5, 10, 15, 20, 25};
Here, we omit specifying the size of the array explicitly. The compiler automatically
determines the size based on the number of elements provided within the curly braces
{}.
• To find the length of the array, we use the formula:
int length = sizeof(numbers) / sizeof(numbers[0]);
sizeof(numbers) gives the total size (in bytes) of the array.
sizeof(numbers[0]) gives the size (in bytes) of a single element in the array.
Dividing the total size by the size of a single element gives us the length of the array.
• We then use a for loop to iterate through the elements of the array:
for (int i = 0; i < length; i++) {
printf("numbers[%d]: %d\n", i, numbers[i]);
}
• The loop starts from i = 0 and continues until i is less than the length of the array.
• Inside the loop, we use printf to print each element along with its index.
return 0;
}
Output:
Elements of the array:
numbers[0]: 10
numbers[1]: 20
numbers[2]: 30
numbers[3]: 40
numbers[4]: 50
Explanation:
• We include the <stdio.h> header for input and output functions.
• We declare and initialize a one-dimensional integer array numbers with a size of 5.
o The array is initialized with the values {10, 20, 30, 40, 50}.
• We use a for loop to iterate through the elements of the array:
o The loop variable i is used as an index to access each element.
o Inside the loop, we use printf to print each element along with its index.
The program creates a one-dimensional integer array named numbers, initializes it with the
values 10, 20, 30, 40, and 50, and then prints each element along with its index. This
demonstrates the creation of a one-dimensional array in C and how to access and print its
elements.
You can access elements of an array using square brackets [] and the index of the element
you want to access. The index is a non-negative integer that specifies the position of the
element within the array. Array indices in C start from 0.
int myArray[5] = {10, 20, 30, 40, 50};
int element = myArray[2]; // Accessing the third element (30) at index 2
In this example, myArray[2] accesses the third element (30) because C arrays are zero-based.
Sample Program:
#include <stdio.h>
int main()
{
//Array Declaration and Initialization
int arr[5] = { 5, 2, 3, 8, 51 };
You can also manipulate (change) the values of array elements by using the same indexing
approach:
int myArray[5] = {10, 20, 30, 40, 50};
myArray[1] = 25; // Changing the value of the second element to 25
After this operation, myArray will be {10, 25, 30, 40, 50}.
You can use loops like for or while to iterate through the elements of an array and apply
operations to each element. For example, you can double all elements of an array:
int myArray[5] = {10, 20, 30, 40, 50};
for (int i = 0; i < 5; i++) {
myArray[i] *= 2; // Double each element
}
After this operation, myArray will be {20, 40, 60, 80, 100}.
Keep in mind that when you manipulate array elements, you need to ensure that the index
you use falls within the valid range of the array (i.e., between 0 and the size of the array
minus one) to avoid accessing memory outside the array boundaries, which can lead to
undefined behavior.
Array of Characters:
Similar to the Way that a Numeric Array, a Character Array be Created
Sample Program:
char arr[5] = {‘a’, ‘e’, ‘i’, ‘o’, ‘u’}
Here the arr is Declared to be of Character Datatype and Size = 5.
It Can Be Observed that Character Values are Enclosed in Single Quotes.
#include <stdio.h>
int main()
{
// printing string
int i = 0;
while (arr[i])
{
printf("%c", arr[i++]);
}
return 0;
}
Output:
aeiou
Here, The While Loop Checks for the Truth Value of arr[i], i.e., If There Exists a Value for arr[i]
then it will be True.
Two-Dimensional Array
A two-dimensional array is an array of arrays, where each element is itself an array.
Syntax:
data_type array_name[rows][columns];
• data_type is the type of elements that the array will hold (e.g., int, float, char, etc.).
• array_name is the name you give to the array.
• rows is the number of rows in the array.
• columns is the number of columns in the array.
Sample Program:
#include <stdio.h>
int main() {
// Declare and initialize a 2D integer array
int matrix[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
return 0;
}
Output:
Elements of the 2D array:
matrix[0][0]: 1
matrix[0][1]: 2
matrix[0][2]: 3
matrix[1][0]: 4
matrix[1][1]: 5
matrix[1][2]: 6
matrix[2][0]: 7
matrix[2][1]: 8
matrix[2][2]: 9
Explanation:
The program declares, initializes, and prints the elements of the 2D array matrix. It
demonstrates how to work with a two-dimensional array, iterating through rows and columns
to access and print its elements.
• We include the <stdio.h> header for input and output functions.
• We declare and initialize a 2D integer array matrix with 3 rows and 3 columns.
o The array is initialized with values in a row format:
1 2 3
4 5 6
7 8 9
• We use nested for loops to iterate through the elements of the 2D array.
o The outer loop (i) iterates through the rows.
o The inner loop (j) iterates through the columns.
• Inside the nested loops, we use printf to print each element along with its row and
column indices.
1 2 3 4 5 6 7 8 9
Row-major is the default format for most programming languages, including C and C++.
When you access elements of a row-major array, you typically iterate through rows first and
then columns.
Column-Major Formats
In column-major order, elements of a multi-dimensional array are stored column by column
in memory. In a 2D array, this means that all elements of the first column are stored
sequentially, followed by all elements of the second column, and so on.
Using the same 2D array as above:
1 2 3
4 5 6
7 8 9
In column-major format, it would be stored in memory like this:
1 4 7 2 5 8 3 6 9
Standard Problems
Addition of Two Matrices
#include <stdio.h>
// Function to read a matrix
void readMatrix(int matrix[][100], int m, int n)
{
printf("Enter elements of the %d x %d matrix:\n", m, n);
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &matrix[i][j]);
}
}
}
int main() {
int m, n;
return 0;
}
Output:
Enter the number of rows: 3
Enter the number of columns: 3
Enter the elements of the first matrix:
Enter elements of the 3 x 3 matrix:
1 13 3 4 2 5 12 1 1
Enter the elements of the second matrix:
Enter elements of the 3 x 3 matrix:
123456789
Resultant 3 x 3 matrix:
2 15 6
8 7 11
19 9 10
Explanation:
// Function to read a matrix
void readMatrix(int matrix[][100], int m, int n) {
// Function body
}
This program allows the user to input the dimensions and elements of two matrices, performs
their addition if they are compatible, and then displays the resultant matrix. It's a structured
way to perform matrix addition in C with separate functions for each part of the operation.
Multiplication of Two Matries
Sample Program:
#include <stdio.h>
#define MAX_ROWS 10
#define MAX_COLS 10
// Function to read a matrix from the user
void readMatrix(int mat[MAX_ROWS][MAX_COLS], int rows, int cols) {
printf("Enter elements of the matrix (%d x %d):\n", rows, cols);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
scanf("%d", &mat[i][j]);
}
}
}
int main() {
int mat1[MAX_ROWS][MAX_COLS];
int mat2[MAX_ROWS][MAX_COLS];
int result[MAX_ROWS][MAX_COLS];
int rows1, cols1, rows2, cols2;
return 0;
}
Output:
Enter the number of rows and columns for the first matrix (m x n): 2 2
Enter elements of the matrix (2 x 2):
1234
Enter the number of rows and columns for the second matrix (p x q): 2 3
Enter elements of the matrix (2 x 3):
123456
Matrix:
9 12 15
19 26 33
Explanation:
• We include the <stdio.h> header for input and output functions.
• We define macros MAX_ROWS and MAX_COLS to specify the maximum dimensions
of matrices.
• We define three functions:
o readMatrix: Reads a matrix from the user.
o multiplyMatrices: Multiplies two matrices and stores the result in result.
o displayMatrix: Displays a matrix.
• In the main function:
o We declare arrays for the two input matrices (mat1 and mat2) and the result
matrix (result).
o We take input for the dimensions and elements of both input matrices using
the readMatrix function.
• We call the multiplyMatrices function to perform matrix multiplication. If the matrices
cannot be multiplied due to incompatible dimensions, an error message is displayed.
• Finally, we display the result matrix using the displayMatrix function.
Mean
∑ 𝐸𝑙𝑒𝑚𝑒𝑛𝑡𝑠
𝑀𝑒𝑎𝑛 =
𝑁𝑢𝑚𝑏𝑒𝑟 𝑜𝑓 𝐸𝑙𝑒𝑚𝑒𝑛𝑡𝑠
Program:
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);
int sum = 0;
return 0;
}
Output:
Mean: 3.00
Explanation:
This program calculates the mean (average) of the elements in an array.
sum is used to accumulate the total of the array elements, which is then divided by the
number of elements (n) to get the mean.
Variance
∑(𝑥𝑖2 )
𝑉𝑎𝑟𝑖𝑎𝑛𝑐𝑒 = − 𝑚𝑒𝑎𝑛2 , where xi is Each Element
𝑛
Program:
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);
return 0;
}
Output:
Variance: 2.00
Explanation:
This program calculates the variance of the array elements.
Standard Deviation
𝑆𝑡𝑎𝑛𝑑𝑎𝑟𝑑 𝐷𝑒𝑣𝑖𝑎𝑡𝑖𝑜𝑛 = √𝑉𝑎𝑟𝑖𝑎𝑛𝑐𝑒
Program:
#include <stdio.h>
#include <math.h>
int main() {
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);
int sum = 0, sumOfSquares = 0;
return 0;
}
Output:
Standard Deviation: 1.41
Explanation:
This program calculates the standard deviation based on the variance.
The sqrt function from math.h is used to compute the square root.
return 0;
}
Output:
Maximum: 5
Minimum: 1
Explanation:
This program finds the maximum and minimum elements in an array.
It iterates through the array, updating max and min as it finds larger or smaller elements,
respectively.
Program:
#include <stdio.h>
#include <math.h>
int main() {
int arr[] = {1, 2, 3, 4, 5}; // Example array
int n = sizeof(arr) / sizeof(arr[0]); // Number of elements in the array
// Calculating mean
mean = (double)sum / n;
// Calculating variance
for (int i = 0; i < n; i++) {
variance += pow(arr[i] - mean, 2);
}
variance /= n;
// Printing results
printf("Mean = %f\n", mean);
printf("Variance = %f\n", variance);
printf("Standard Deviation = %f\n", stdDeviation);
printf("Maximum Element = %d\n", max);
printf("Minimum Element = %d\n", min);
return 0;
}
Output:
Mean = 3.000000
Variance = 2.000000
Explanation:
Array and Its Size:
• The array arr contains the elements for which calculations are performed.
• n stores the number of elements in the array.
Mean Calculation:
• The mean (average) is calculated by dividing the sum of all elements by the number
of elements.
Variance Calculation:
• Another loop calculates the variance. It sums the squared differences between each
element and the mean, then divides by the number of elements.
Printing Results:
• Finally, the program prints the calculated mean, variance, standard deviation,
maximum element, and minimum element.
Functions
Functions in C are blocks of code that perform a specific task. They enhance modularity and
code reuse, allowing for a more structured and manageable approach to programming.
Definition and Purpose
A function in C is a self-contained block of code that performs a specific operation. It is a
fundamental concept in structured programming, allowing developers to break down complex
problems into smaller, more manageable tasks.
Purpose: The primary purpose of functions is to segment a large program into smaller, logical
sections. Each function is designed to perform a particular task and can be used repeatedly
throughout a program.
Characteristics of Functions
• Modularity: Functions promote modularity in programming. By dividing a program
into smaller functions, the overall structure becomes more organized and
manageable. This modularity helps in simplifying the development process and
enhancing code readability.
• Code Reuse: Functions enable code reuse, a significant advantage in programming.
Once a function is written to perform a task, it can be reused in different parts of the
program, or even in different programs, without needing to rewrite the code.
Declaring a Function
A function declaration (or prototype) in C provides the function's name, return type, and
parameters without its actual body. It serves as an interface to the function. The function
definition includes the actual body of the function. It contains the set of instructions that are
executed when the function is called.
A function declaration tells the compiler about a function's name, return type, and
parameters. It's also known as a function prototype.
Syntax for Function Declation:
returnType functionName(parameterType1 parameter1, parameterType2 parameter2, ...);
• returnType: This specifies the type of value the function will return. If the function
does not return a value, this is specified as void.
• functionName: This is the identifier for the function. It's the name used to call the
function from other parts of the program.
• parameterType1 parameter1, parameterType2 parameter2, ...: These are the
parameters that the function accepts. Each parameter is specified by a type
(parameterType) and a name (parameter). The function can accept multiple
parameters, separated by commas. If the function takes no parameters, this can be
left empty or specified with void in some cases.
Example 1:
int sum(int a, int b);
Declares a function named sum that takes two int parameters and returns an int.
No function body is provided here; it's just a declaration.
Example 2:
void displayMessage();
Declares a function displayMessage that takes no parameters and returns nothing (void).
Signature of a Function
A function signature includes the function name and its parameter list. It's used to uniquely
identify the function. It specifies how the function can be used in terms of its inputs and
output. Understanding the function signature is essential for both the correct use of existing
functions and the design of new functions.
The signature of a function comprises the function's name and its parameter list. It defines
the function's interface without considering its return type. In many programming contexts,
however, the return type is also informally considered part of the signature.
Example 1:
int add(int num1, int num2);
Signature: add(int, int)
The signature consists of the function name add and the parameter list (int, int), indicating
that this function takes two integers as input.
In this context, the return type (int) is not considered part of the signature, though informally
it's often included when discussing the function's prototype.
Example 2:
int multiply(int x, int y);
Signature: multiply(int, int)
Identifies a function multiply with two int parameters.
Example 3:
float calculateArea(float radius);
Signature: calculateArea(float)
Identifies a function calculateArea with a single float parameter.
Example 1:
void printAge(int age)
{
printf("Age is: %d\n", age);
}
age is a parameter passed to printAge.
Example 2:
int add(int num1, int num2)
{
return num1 + num2;
}
num1 and num2 are parameters passed to add.
incrementing i in each iteration. This ensures that every element of the array
is accessed.
• Calculating the Sum
o sum += arr[i];: Inside the loop, each element of the array (arr[i]) is added to
sum. This statement is equivalent to sum = sum + arr[i]; and adds the value
of the current array element to the running total stored in sum.
• Printing the Result
o printf("Sum of array elements: %d\n", sum);: After the loop completes, the total
sum of the array elements is printed to the console. %d is a format specifier
for integers, and sum is the variable holding the calculated total.
Example 2:
void printArray(int arr[], int size)
{
for(int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
arr is an array passed to printArray.
Example 3:
int findMax(int nums[], int n)
{
int max = nums[0];
for(int i = 1; i < n; i++)
{
if(nums[i] > max)
{
max = nums[i];
}
}
return max;
}
nums is an array passed to findMax.
}
}
This function doubles each element in the given array. Modifications made to the array
elements will be reflected in the original array.
Recursion
Recursion in programming refers to a technique where a function calls itself directly or
indirectly to solve a problem. It's a method of solving complex problems by breaking them
down into simpler sub-problems of the same type. Recursion is particularly useful in
situations where the solution can be naturally expressed in terms of smaller instances of the
same problem.
Characteristics of Recursion
• Base Case: Every recursive function must have a base case, which is a condition that
stops the recursion. Without a base case, recursion would continue indefinitely,
leading to a stack overflow.
• Recursive Case: This is where the function calls itself with a simpler or smaller
argument.
• Simplicity and Elegance: Recursive solutions are often more straightforward and
elegant than their iterative counterparts for certain types of problems.
• Memory Utilization: Each recursive call uses some amount of memory (stack space),
so it's important to ensure that the recursion does not go too deep.
This recursive approach calculates the Fibonacci number by summing the two preceding
Fibonacci numbers, aligning with the definition of the Fibonacci series.
Standard Problems
Factorial of a Given Number
Factorial of a Given Number Without Recursion
#include <stdio.h>
int main() {
int num;
printf("Enter a positive integer: ");
scanf("%d", &num);
if (num < 0) {
printf("Factorial of a negative number doesn't exist.\n");
} else {
printf("Factorial of %d = %ld\n", num, factorial(num));
}
return 0;
}
Output:
Enter a positive integer: 5
Factorial of 5 = 120
Explanation:
Function Signature:
• long factorial(int n): Declares a function named factorial that takes an integer n as
input and returns a long integer.
Variable Initialization:
• long fact = 1;: Initializes a long integer variable fact to store the factorial. It's initialized
to 1 because the factorial is calculated as a product.
Iterative Loop:
• for (int i = 1; i <= n; i++) { ... }: A for loop that iterates from 1 to n.
• Within the loop, fact *= i; updates fact by multiplying it with the current loop index i.
This operation calculates the factorial by multiplying all integers from 1 up to n.
Return Value:
• return fact;: After completing the loop, the function returns the calculated factorial.
Program Exit:
• return 0;: The main function returns 0, indicating successful execution.
int main() {
int num;
printf("Enter a positive integer: ");
scanf("%d", &num);
if (num < 0) {
printf("Factorial of a negative number doesn't exist.\n");
} else {
printf("Factorial of %d = %ld\n", num, factorial(num));
}
return 0;
}
Output:
Explanation:
Function Signature:
• long factorial(int n): Declares a function named factorial that takes an integer n as
input and returns a long integer. The function is designed to compute the factorial of
n.
Base Case:
• if (n == 0) return 1;: The base case of the recursion. When n is 0, the function returns
1. This is because the factorial of 0 is defined as 1. The base case is essential to stop
the recursion from continuing indefinitely.
Recursive Case:
• return n * factorial(n - 1);: The recursive case where the function calls itself. Here, the
function multiplies n with the factorial of n - 1. Each recursive call reduces n by 1,
gradually approaching the base case.
Program Exit:
• return 0;: The main function returns 0, indicating successful execution.
int main() {
int num;
printf("Enter a positive integer: ");
scanf("%d", &num);
if (num < 0) {
printf("Sum of natural numbers for a negative number doesn't make sense.\n");
} else {
printf("Sum of the first %d natural numbers is: %d\n", num,
sumOfNaturalNumbers(num));
}
return 0;
}
Output:
Enter a positive integer: 5
Sum of the first 5 natural numbers is: 15
Explanation:
Function Signature:
int sumOfNaturalNumbers(int n): Declares a function named sumOfNaturalNumbers that
takes an integer n as input and returns an integer. The function is designed to compute the
sum of the first n natural numbers.
Variable Initialization:
• int sum = 0;: Initializes an integer variable sum to store the cumulative total of natural
numbers. It starts from 0 because it will accumulate the sum in the loop.
Iterative Loop:
• for (int i = 1; i <= n; i++) { ... }: A for loop iterates from 1 to n. The loop index i represents
each natural number from 1 up to n.
• Within the loop, sum += i; adds the value of i to sum in each iteration. This operation
computes the cumulative sum of natural numbers.
Return Value:
• return sum;: After completing the loop, the function returns the total sum of the
natural numbers from 1 to n.
Program Exit:
• return 0;: The main function returns 0, indicating successful execution.
return 0;
}
Output:
Enter a positive integer: 5
Sum of the first 5 natural numbers is: 15
Explanation:
Function Signature:
• int sumOfNaturalNumbers(int n): Declares a function named sumOfNaturalNumbers
that takes an integer n as input and returns an integer. The function is designed to
compute the sum of the first n natural numbers using recursion.
Base Case:
• if (n == 0) return 0;: The base case of the recursion. When n is 0, the function returns
0. This is because the sum of natural numbers up to 0 is 0. The base case is essential
to stop the recursion from continuing indefinitely.
Recursive Case:
• return n + sumOfNaturalNumbers(n - 1);: The recursive case where the function calls
itself. Here, the function returns the sum of the current number n and the result of
sumOfNaturalNumbers(n - 1). Each recursive call reduces n by 1, gradually
approaching the base case.
Program Exit:
• return 0;: The main function returns 0, indicating successful execution.
External
• Storage Duration: External variables have static storage duration. They exist
throughout the program's execution.
• Scope: They have file scope, meaning they can be accessed across multiple functions
within the same source file.
• Declaration: External variables are declared outside of any function
Example:
// External variable declared outside any function
int globalVar = 10;
void function1()
{
// Access globalVar
printf("globalVar inside function1: %d\n", globalVar);
}
void function2()
{
// Access globalVar
printf("globalVar inside function2: %d\n", globalVar);
}
Explanation:
• An external variable globalVar is declared and initialized outside of any function. This
variable has global scope, which means it can be accessed from any function within
the same source file. Its initial value is set to 10.
• The code defines two functions: function1 and function2.
• Inside function1, the globalVar variable is accessed using its name. This is possible
because globalVar has global scope and can be seen and used from within any
function in the same source file.
• printf is used to print the value of globalVar inside function1, resulting in the output:
"globalVar inside function1: 10". The value is retrieved from the global variable.
• Similarly, inside function2, the globalVar variable is accessed and printed using
printf. The output in this case is: "globalVar inside function2: 10".
• Both function1 and function2 are independent of each other, but they can access and
modify the same globalVar variable since it has global scope.
Auto
• Storage Duration: Auto variables have automatic storage duration. They are created
when a function is called and destroyed when the function exits.
• Scope: They have block scope, meaning they are accessible only within the block or
function where they are declared.
• Declaration: Variables declared inside a function without any storage class specifier
are auto by default.
Example:
void function()
{
// Auto variable
int localVar = 5;
printf("localVar: %d\n", localVar);
}
Explanation:
• The code defines a function named function().
• Inside the function(), a variable named localVar is declared and initialized with the
value 5. This variable is an auto variable by default, as it is declared without any
storage class specifier. Auto variables have automatic storage duration, meaning they
are created when the function is called and destroyed when the function exits.
• The printf function is used to print the value of localVar using the format specifier
%d. This line of code displays the value of localVar on the console.
• The function function() is now defined and ready to be called.
• When this function is called, it will execute the code within its body. In this case, it
will print the value of localVar, which is 5, to the console.
• After printing the value, the function will exit, and the auto variable localVar will be
automatically destroyed because it has automatic storage duration. It will no longer
exist in memory after the function exits.
Local
• Storage Duration: Local variables have automatic storage duration, just like auto
variables.
• Scope: They have block scope, similar to auto variables.
• Declaration: Local variables are declared inside a block or function.
Example:
void function()
{
// Local variable
int localVar = 5;
printf("localVar: %d\n", localVar);
}
Explanation:
• The code defines a function named function(). This function doesn't take any
parameters.
• Inside the function, a variable named localVar is declared and initialized with the
value 5. This variable is a local variable because it is declared within the function's
scope. Local variables have block scope, meaning they are only accessible within the
block (in this case, the function) where they are declared.
• The printf function is used to print the value of localVar to the console. The format
specifier %d is used to format and print an integer.
• The printf statement will print the value of localVar, which is 5, to the console when
the function() is called.
• This function definition is now complete and can be called from other parts of the
program.
• When the function() is called, it will execute its code. It will print the value of localVar
(which is 5) to the console and then complete its execution.
• After the function completes its execution, the local variable localVar goes out of scope
and is automatically destroyed. It does not persist beyond the execution of the
function.
Static
• Storage Duration: Static variables have static storage duration. They are created once
when the program starts and persist until the program ends.
• Scope: They have block scope like auto and local variables but retain their values
between function calls.
• Declaration: Variables declared with the static keyword inside a function become
static variables.
Example:
void function()
{
// Static variable
static int staticVar = 0;
staticVar++;
printf("staticVar: %d\n", staticVar);
}
int main()
{
function(); // Output: staticVar: 1
function(); // Output: staticVar: 2
return 0;
}
Explanation:
• The code defines a function named function().
• Inside the function(), there is a static variable named staticVar declared and initialized
to 0. The static keyword is used to declare this variable as static. Static variables have
static storage duration, which means they are created once when the program starts
and retain their values between function calls. In this case, staticVar is initialized to
0 when the program starts.
• The code then increments the staticVar by 1 using the staticVar++ statement. This
means that each time the function() is called, staticVar will retain its value from the
previous call and increment it by 1.
• The printf function is used to print the current value of staticVar to the console using
the format specifier %d.
• The main() function is defined, which serves as the program's entry point.
• Inside main(), the function() is called for the first time using function();.
• When function() is called for the first time, it increments staticVar from 0 to 1 and
prints "staticVar: 1" to the console.
• Then, function() is called for the second time using function(); from main(). This time,
staticVar is incremented from 1 to 2, and "staticVar: 2" is printed.
• Finally, the main() function returns 0, indicating successful program execution.
Register Variables
• Storage Duration: Register variables have automatic storage duration, like auto
variables.
• Scope: They have block scope, similar to auto and local variables.
• Declaration: Variables declared with the register keyword inside a function are
register variables. The keyword suggests that the variable should be stored in a CPU
register for faster access.
Example:
void function()
{
// Register variable
register int regVar = 10;
printf("regVar: %d\n", regVar);
}
Explanation:
• In the function, a static variable staticVar is declared and initialized to 0. It has static
storage duration.
• The variable is incremented by 1, and its value is printed. Since it's static, it retains
its value between function calls.
• In main, the function is called twice.
• The first call increments staticVar to 1 and prints it.
• The second call increments staticVar to 2 and prints it. The variable's value persists
between calls.
Unit IV
Topics to be Discussed:
Pointers: Pointer, Pointer to Pointer, Pointer and Functions (Call by Reference) Arguments,
Pointers and Arrays, Address Arithmetic, Characters and Pointers, Dynamic Memory
Allocation Methods.
Strings: Declaring, Initializing, String Input and Output Functions, String Handling
Functions.
Pointers
Why Shall We Study Pointers / Why Pointers are Necessary to Study After Functions?
• Memory Management: Pointers provide direct access to memory and help in efficient
memory management.
• Performance Optimization: They allow manipulation of data directly in memory,
which can optimize program performance.
• Dynamic Memory Allocation: Pointers are essential for dynamic memory allocation,
which is crucial for creating flexible data structures like linked lists, trees, and graphs.
• Function Arguments: Understanding pointers is critical for passing data to functions
more efficiently, especially when dealing with large structures or arrays.
Definition:
A pointer in C is a variable that stores the memory address of another variable. This allows
direct access and manipulation of the value stored at that memory location.
Mathematical Foundations:
Pointers are based on the concept of indirect referencing. Mathematically, if x is a variable
and &x is its address, a pointer p can store &x.
Then, *p (dereferencing) gives access to the value of x.
Syntax:
Declaration: datatype *pointer_name;
Initialization: pointer_name = &variable;
Dereferencing: *pointer_name; to access the value at the pointed location.
Example 1: Simple Example Demonstrating the Use of Pointers
#include <stdio.h>
int main() {
int var = 10; // A variable
int *ptr; // A pointer variable declaration
ptr = &var; // Store address of var in pointer variable
return 0;
}
Output:
Value of var = 10
Address of var = 0x7fffb077b624
Value of ptr = 0x7fffb077b624
Value at *ptr = 10
Explanation:
• Include Directive:
#include <stdio.h>: This line includes the standard input-output library in the
program, which is necessary for using the printf function.
• Function Declaration:
int main() {: This is the start of the main function, which is the entry point of every C
program. The program execution starts here.
• Variable Declaration and Initialization:
int var = 10;: A variable var of type int (integer) is declared and initialized with the
value 10.
• Pointer Declaration:
int *ptr;: This line declares a pointer variable ptr that is intended to point to an integer.
At this point, ptr doesn't have a defined value.
• Assigning Address to Pointer:
ptr = &var;: The address of var is assigned to ptr. The operator & is used to get the
address of var. Now, ptr contains the memory address of var.
• Printing Value of Variable:
printf("Value of var = %d\n", var);: This prints the value of var, which is 10.
• Printing Address of Variable:
printf("Address of var = %p\n", &var);: This prints the memory address of var. %p is
used as the format specifier for an address.
• Printing Value of Pointer:
printf("Value of ptr = %p\n", ptr);: This prints the value stored in ptr, which is the
address of var. Notice this should match the address printed in the previous step.
• Printing Value at the Address Pointed by Pointer:
• printf("Value at *ptr = %d\n", *ptr);: Dereferencing the pointer ptr with *ptr gives the
value at the memory address stored in ptr, which is the value of var. This line prints
10, the value of var.
return 0;
}
Output:
Value at arr[0] = 10
Value at arr[1] = 20
Value at arr[2] = 30
Explanation
• Declaration and Initialization: An array arr of integers is declared and initialized
with three values. A pointer ptr is declared and initialized to point to the first element
of the array (arr[0]).
• Looping through Array: A for loop is used to iterate through the array elements.
• Accessing Elements: Within the loop, *ptr dereferences the current value pointed to
by ptr (initially arr[0]), which is then printed.
• Pointer Increment: After each iteration, ptr++ increments the pointer so that it points
to the next array element.
int main()
{
int a = 100, b = 200;
printf("Before swap, a = %d and b = %d\n", a, b);
swap(&a, &b);
printf("After swap, a = %d and b = %d\n", a, b);
return 0;
}
Output:
Before swap, a = 100 and b = 200
After swap, a = 200 and b = 100
Explanation:
• Function swap: A function swap is defined to swap the values of two integers. It takes
two pointers as arguments.
• Pointer Dereferencing in Function: Inside the swap function, *x and *y are used to
access and swap the values of the variables pointed by x and y.
• Main Function: Two integers a and b are declared and initialized. Before and after
calling swap, their values are printed to show the effect of the swap.
• Calling swap: swap is called with the addresses of a and b (&a and &b). This is known
as call by reference, where the function can modify the actual values of the arguments.
• Result: The values of a and b are swapped as a result of the swap function call,
demonstrating how pointers can be used to alter function arguments directly.
return 0;
}
Output:
Value of num: 50
Value at pointer ptr: 50
Explanation:
• Variable Declaration: int num = 50; initializes an integer variable num with the value
50.
• Pointer Initialization: int *ptr = # declares a pointer ptr and initializes it with
the address of num.
• Dereferencing Pointer: printf("Value at pointer ptr: %d\n", *ptr); prints the value at
the address stored in ptr. Dereferencing ptr with *ptr yields the value of num, which
is 50.
Pointer Assignment
Pointer assignment involves assigning the address of a variable to a pointer.
Syntax: pointer_variable = &variable;
After assignment, the pointer points to the address of the assigned variable.
Example
#include <stdio.h>
int main() {
int a = 10, b = 20;
int *ptr;
ptr = &a; // Pointer points to a
printf("Value pointed to by ptr: %d\n", *ptr);
ptr = &b; // Now pointer points to b
printf("Value pointed to by ptr: %d\n", *ptr);
return 0;
}
Output:
Value pointed to by ptr: 10
Value pointed to by ptr: 20
Explanation
• Variable Declaration: Two integers a and b are declared and initialized.
• Pointer Declaration: A pointer ptr is declared.
• Assigning Pointer to a: ptr = &a; assigns the address of a to ptr. *ptr now equals 10.
• Printing Value Pointed by ptr: The value at the address stored in ptr is printed,
showing 10.
• Reassigning Pointer to b: ptr = &b; changes the address stored in ptr to that of b.
*ptr now equals 20.
• Printing New Value Pointed by ptr: The new value at the address stored in ptr is
printed, showing 20.
int main()
{
int arr[] = {5, 2, 8, 1, 3};
int min, max;
return 0;
}
Output:
Minimum element = 1
Maximum element = 8
Explanation:
• Function Declaration: The findMinMax function takes an array, its length, and
pointers to store minimum and maximum values.
• Initializing Min and Max: *min = *max = arr[0]; initializes both min and max to the
first element of the array.
• Looping Through Array: The loop iterates over the array elements starting from the
second element.
• Updating Min and Max: Inside the loop, *min and *max are updated if a smaller or
larger element, respectively, is found.
• Main Function: The main function defines an array, calls findMinMax, and prints the
minimum and maximum elements.
• Output: The program prints the smallest and largest elements in the array.
Returning Pointers
Purpose of Returning Pointers
• Access to Data Structures: Functions can return pointers to complex data structures
(e.g., structs, arrays) that would be inefficient to return by value.
• Dynamic Memory Allocation: Often used with functions that allocate memory
dynamically (using malloc, calloc, etc.) so that the allocated memory can be accessed
outside the function.
Syntax
The function declaration specifies that it returns a pointer, typically datatype*
function_name().
Example: int* getArray() { ... }
Important Considerations
• Lifetime of Data: Ensure the data being pointed to remains valid after the function
returns. Do not return pointers to local (automatic) variables declared within the
function.
• Memory Management: If the pointer refers to dynamically allocated memory, the
calling function is usually responsible for freeing that memory when it's no longer
needed to avoid memory leaks.
• Null Pointer Checks: The calling code should check if the returned pointer is NULL,
especially if the function uses dynamic memory allocation.
Example
#include <stdio.h>
#include <stdlib.h>
int* createArray(int size)
{
int *arr = malloc(size * sizeof(int));
if (arr != NULL) {
// Initialize array
for (int i = 0; i < size; i++) {
arr[i] = i;
}
}
return arr;
}
int main()
{
int *myArray = createArray(5);
if (myArray != NULL) {
// Use the array
for (int i = 0; i < 5; i++) {
printf("%d ", myArray[i]);
}
free(myArray); // Free the allocated memory
} else {
printf("Memory allocation failed.");
}
return 0;
}
Output:
01234
Explanation
• Function createArray: This function dynamically allocates memory for an array and
returns a pointer to the array.
• Memory Allocation: malloc is used to allocate memory. It's crucial to check if malloc
successfully allocated memory by verifying arr is not NULL.
• Initializing Array: The array elements are initialized within the function.
• Returning Pointer: The function returns a pointer to the allocated array.
• In main Function: The returned pointer is received in myArray. A check ensures it's
not NULL before using it.
• Freeing Memory: It's crucial to free the allocated memory using free(myArray) to
avoid memory leaks.
Pointer to Pointer
A pointer to a pointer is a form of multiple indirection or a chain of pointers. It is essentially
a pointer that holds the address of another pointer.
Definition
A pointer to a pointer is a variable that stores the address of another pointer variable.
Syntax
datatype **pointer_to_pointer;
Usage
Used in dynamic memory allocation.
Helpful in complex data structures like trees, graphs, and linked lists.
Common in handling arrays of strings.
Example
#include <stdio.h>
int main()
{
int var = 300;
int *ptr;
int **pptr;
return 0;
}
Output:
Value of var = 300
Value available at *ptr = 300
Value available at **pptr = 300
Explanation
• Variable Declaration: int var = 300; declares an integer variable var and initializes it
with the value 300.
• Pointer Declaration: int *ptr; declares a pointer ptr to an integer.
int num = 5;
modifyValue(&num); // Pass num by reference
printf("Modified value: %d\n", num); // Outputs 6
return 0;
}
Output:
Modified value: 6
Explanation
• A variable num is declared and initialized with the value 5.
• The modifyValue function takes a pointer as a parameter, which is used to pass num
by reference.
• Inside modifyValue, the value pointed to by ptr (i.e., num) is incremented.
• In the main function, modifyValue is called with &num to pass a pointer to num.
• After the function call, the modified value of num is printed, which is 6.
Explanation
• Two integer variables a and b are declared and initialized with values 10 and 20,
respectively.
• The swap function takes two pointers as parameters, allowing it to swap the values of
the variables they point to.
• Inside swap, the values pointed to by x and y are swapped using a temporary variable.
• In the main function, swap is called with &a and &b to pass both a and b by reference.
• After the function call, the values of a and b are printed, demonstrating that they have
been swapped.
Advantages
Efficient array manipulation using pointers.
Allows for dynamic memory allocation using malloc and arrays of unknown size using pointer
arithmetic.
Example 1: Traverse and Print Array
Program
#include <stdio.h>
int main()
{
int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr; // arr is a pointer to the first element
for (int i = 0; i < 5; i++)
{
printf("%d ", *ptr); // Print the value at the pointer
ptr++; // Move the pointer to the next element
}
return 0;
}
Output:
12345
Explanation
• An integer array arr is declared and initialized with values 1 to 5.
• A pointer ptr is declared and initialized with arr. This makes ptr point to the first
element of the array.
• A for loop is used to iterate through the elements of the array.
• Inside the loop, *ptr is used to access and print the value pointed to by ptr.
• ptr++ is used to increment the pointer, effectively moving it to the next element of the
array.
Explanation
• An integer array arr is declared and initialized with values 1 to 5.
• A pointer ptr is declared and initialized with arr, making it point to the first element.
• An integer variable sum is initialized to 0 to store the sum of array elements.
• A for loop is used to iterate through the elements of the array.
• Inside the loop, *ptr is used to access and add the value pointed to by ptr to the sum.
• ptr++ is used to increment the pointer, moving it to the next element.
• After the loop, the sum of array elements is printed.
Address Arithmetic
Pointer address arithmetic involves performing arithmetic operations on pointers, such as
addition and subtraction, to navigate and manipulate memory addresses. It's a powerful
feature in C that allows for efficient traversal of arrays, data structures, and memory
allocation.
Pointer Arithmetic Operations
• Addition: Adding an integer to a pointer increments the pointer's address by the
product of the integer and the size of the pointed-to data type.
• Subtraction: Subtracting an integer from a pointer decrements the pointer's address
by the product of the integer and the size of the pointed-to data type.
Syntax
• ptr + n: Moves n elements forward.
• ptr - n: Moves n elements backward.
• ptr1 - ptr2: Computes the difference in addresses between two pointers.
Advantages
Efficient traversal of arrays and data structures.
Useful for dynamic memory allocation, pointer arithmetic, and pointer-based data
manipulation.
Example 1: Pointer Arithmetic – Addition
Pointer arithmetic addition involves adding an integer value to a pointer, which increments
the pointer's address by the product of the integer and the size of the pointed-to data type.
Program
#include <stdio.h>
int main()
{
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr; // Pointer points to the first element
return 0;
}
Output:
Element at index 0: 10
Element at index 2: 30
Explanation
• An integer array arr is declared and initialized with values 10 to 50.
• A pointer ptr is declared and initialized with arr, making it point to the first element
of the array.
• The program prints the value at the first index (index 0) using *ptr, which is 10.
• Pointer arithmetic is used to move the pointer two elements forward. ptr = ptr + 2;
increments the pointer's address by 2 * sizeof(int) bytes, effectively pointing to the
element at index 2.
• The program prints the value at index 2 using *ptr, which is 30.
Program
#include <stdio.h>
int main()
{
int arr[] = {10, 20, 30, 40, 50};
int *ptr = &arr[4]; // Pointer points to the last element
return 0;
}
Output:
Element at index 4: 50
Element at index 2: 30
Explanation
• An integer array arr is declared and initialized with values 10 to 50.
• A pointer ptr is declared and initialized with the address of the last element of the
array (&arr[4]), making it point to the last element.
• The program prints the value at the last index (index 4) using *ptr, which is 50.
• Pointer arithmetic is used to move the pointer two elements backward. ptr = ptr - 2;
decrements the pointer's address by 2 * sizeof(int) bytes, effectively pointing to the
element at index 2.
• The program prints the value at index 2 using *ptr, which is 30.
Character Arrays
• Strings in C are typically represented as character arrays (e.g., char str[] = "Hello";).
Pointer to Characters
• Pointers to characters (char *) are commonly used to access and modify individual
characters in a string.
Explanation
• A character array str is declared and initialized with the string "Hello, World!".
• A pointer ptr is declared and initialized with str, making it point to the first character
of the string.
• A variable length is initialized to 0 to store the length of the string.
• A while loop is used to iterate through the characters of the string.
• Inside the loop, *ptr is used to access the current character. If it's not '\0' (null
terminator), length is incremented.
• ptr++ is used to move the pointer to the next character in the string.
• After the loop, the length of the string is printed.
Explanation
• A character array source is declared and initialized with the string "Hello".
• An empty character array destination of size 10 is initialized.
• The stringCopy function is defined to copy one string to another.
• Inside the function, a while loop is used to iterate through the characters of the source
string.
• *dest = *src; copies the character from the source to the destination.
• dest++ and src++ are used to move to the next characters in both source and
destination.
• After copying all characters, *dest = '\0'; adds a null terminator to the destination,
ensuring it's a valid C string.
• In the main function, the stringCopy function is called to copy the source string to the
destination.
• The copied string is printed.
size_t is an unsigned integer type representing the size of memory to allocate in bytes.
malloc returns a void pointer (void *) to the first byte of the allocated memory block.
It allocates a block of memory of the specified size and returns a pointer to the beginning of
that block.
free (Memory Deallocation)
Syntax:
void free(void *ptr);
Syntax Explanation:
ptr is a pointer to the memory block that was previously allocated using malloc.
free deallocates the memory block pointed to by ptr.
After calling free, the pointer ptr becomes invalid, and the memory can be reused for other
purposes.
if (arr == NULL)
{
printf("Memory allocation failed.\n");
return 1; // Exit with an error code
}
// Initialize the array
for (int i = 0; i < size; i++)
{
arr[i] = i * 2;
}
// Use the array
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
// Free the allocated memory
free(arr);
return 0;
}
Output:
02468
Explanation
• An integer pointer arr is declared to store the address of dynamically allocated
memory.
• An integer size is set to 5, indicating the size of the dynamically allocated integer array.
• malloc is used to allocate memory for an integer array of size size. The cast (int *) is
used to convert the result of malloc to the appropriate pointer type.
• A check is performed to ensure that memory allocation was successful. If arr is NULL,
it means that memory allocation failed, and an error message is printed before exiting
the program with an error code.
• A for loop is used to initialize the elements of the array with even numbers.
• Another for loop is used to print the values of the array.
• After using the array, free is called to release the dynamically allocated memory to
avoid memory leaks.
• malloc is used to allocate memory for a character array (string) of size 20. The cast
(char *) is used to convert the result of malloc to the appropriate pointer type.
• A check is performed to ensure that memory allocation was successful. If name is
NULL, it means that memory allocation failed, and an error message is printed before
exiting the program with an error code.
• The strcpy function is used to initialize the name string with the value "John Doe".
• The program prints the contents of the name string.
• After using the string, free is called to release the dynamically allocated memory to
avoid memory leaks.
Strings
Strings in C are arrays of characters terminated by a null character '\0'. They are used to
store text.
Declaring
Syntax:
char str[50];
This declares str as a string capable of holding up to 49 characters plus the null character.
Initializing
Initialization can be done at the time of declaration
char str[] = "Hello, World!";
or
by assigning values to the array:
char str[50];
str[0] = 'H';
str[1] = 'i';
str[2] = '\0'; // null character to terminate the string
Example:
char str[50];
• gets(str); // Reads a string from the user.
• puts(str); // Outputs the string.
Example:
char str[50];
Example:
#include <stdio.h>
#include <string.h>
int main()
{
char source[] = "Hello, World!";
char destination[50];
strcpy(destination, source);
Explanation:
• source string is initialized with "Hello, World!".
• destination string is declared with enough space.
• strcpy function copies source to destination.
• The copied string is printed.
Example:
#include <stdio.h>
#include <string.h>
int main()
{
char source[] = "Hello, World!";
char destination[50];
strncpy(destination, source, 5);
destination[5] = '\0'; // Null-terminate the string
Explanation
• source string contains "Hello, World!".
• destination string is declared.
• strncpy function copies first 5 characters from source to destination.
• destination is null-terminated.
• The result "Hello" is printed.
2. strlen
• Returns the length of the string (excluding the null character).
Example:
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, World!";
int length = strlen(str);
Explanation:
• str is initialized with "Hello, World!".
• strlen calculates the length of str, excluding the null character.
• Length (13) is printed.
Example
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "C Programming";
int i;
P
r
o
g
r
a
m
m
i
n
g
Explanation
• str is initialized with "C Programming".
• A loop runs from 0 to the length of str.
• Each character of str is printed on a new line.
Example:
#include <stdio.h>
#include <string.h>
int main()
{
char str1[20] = "Hello, ";
char str2[] = "World!";
strcat(str1, str2);
Explanation:
• str1 and str2 are initialized.
• strcat concatenates str2 to str1.
• The concatenated string "Hello, World!" is printed.
Example:
#include <stdio.h>
#include <string.h>
int main()
{
char str1[20] = "Hello, ";
char str2[] = "World!";
Explanation:
• str1 and str2 are initialized.
• strncat concatenates the first 3 characters of str2 to str1.
• The result "Hello, Wor" is printed.
Example:
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "Hello";
char str2[] = "World";
if (result == 0) {
printf("Strings are equal\n");
} else {
printf("Strings are not equal\n");
}
return 0;
}
Output:
Explanation
• str1 and str2 are initialized.
• strcmp compares str1 and str2.
• The result indicates they are not
Unit V
Topics to be Discussed:
Structures: Defining Structures, Initializing Structures, Structures and Functions, Array of
Structures.
File Management: Creating, Reading, Writing Text and Binary Files, Random Access Using
FSeek, FTell and Rewind Functions.
Structures
Structures in C are a way to group different types of variables under a single name. These
variables can be of different types and are known as members of the structure. Structures
are useful for representing complex data items that have multiple attributes.
In the C programming language, structures provide a way to group together variables of
different data types under a single name. A structure is a user-defined data type that allows
you to create complex and custom data structures to represent real-world entities or complex
data records.
Key Points:
• Grouping Data: Structures allow you to group together variables of various data types,
including integers, floating-point numbers, characters, and even other structures,
into a single unit.
• User-Defined: Unlike basic data types (int, float, char, etc.), structures are user-
defined data types. This means you can define your own structures to suit the specific
needs of your program.
• Members or Fields: Variables inside a structure are referred to as members or fields.
Each member can have a unique data type and a meaningful name.
• Organization: Structures are useful for organizing related data elements. For example,
you can use a structure to represent a student with fields like student ID, name, and
GPA.
• Modularity: Structures promote modularity in code. You can define a structure once
and then reuse it throughout your program, making your code more organized and
maintainable.
• Accessing Members: To access members of a structure, you use the dot (.) operator
followed by the member's name. For example, if you have a structure representing a
point with members x and y, you can access them as point.x and point.y.
Example:
// Define a structure for representing a point in 2D space
struct Point
{
int x; // x-coordinate
int y; // y-coordinate
};
int main()
{
// Declare a structure variable
struct Point p1;
// Initialize structure members
p1.x = 3;
p1.y = 5;
// Access and use structure members
printf("Coordinates: (%d, %d)\n", p1.x, p1.y);
return 0;
}
In this example, we define a structure Point to represent 2D points with x and y coordinates.
We then declare a structure variable p1, initialize its members, and access them to print the
coordinates.
Output:
Coordinates: (3, 5)
Explanation:
Structure Definition:
// Define a structure for representing a point in 2D space
struct Point
{
int x; // x-coordinate
int y; // y-coordinate
};
In this step, a structure named Point is defined. This structure is used to represent a point
in 2D space and has two members: x (representing the x-coordinate) and y (representing the
y-coordinate).
Main Function:
int main() {
Inside the main() function, a structure variable p1 of type struct Point is declared. This
variable will be used to store the coordinates of a point.
p1.y = 5;
The x and y members of the p1 structure variable are initialized with values 3 and 5,
respectively. This sets the coordinates of the point represented by p1 to (3, 5).
The printf function is used to display the coordinates of the point stored in the p1 structure
variable. It prints "Coordinates: (3, 5)" to the console. This line demonstrates how to access
structure members using the dot (.) operator.
The main() function ends with a return 0; statement, indicating successful program
execution. The program then terminates, and the operating system typically receives a return
code of 0 to signify that the program ran without errors.
Defining Structures
A structure in C programming is a user-defined data type that allows grouping together
different data types under a single unit. This unit, or structure, can contain variables of
various data types, such as int, float, char, etc. These variables are referred to as "members"
or "fields" of the structure.
Syntax:
struct StructureName
{
dataType member1;
dataType member2;
...
};
Key Points:
• Keyword struct: This keyword is used to define a structure.
• StructureName: This is a label for the structure type and follows the same naming
conventions as variables in C.
• Members: Inside the structure, members are declared, each with its own data type.
• Semicolon: A semicolon (;) is required at the end of the structure definition.
Explanation:
• Custom Data Type: Structures create a new data type that can be used to declare
variables. Once a structure is defined, it can be used throughout the program to create
instances of that structure type.
• Grouping Data: Structures are particularly useful when there is a need to group
related data elements, which may be of different types, into a single logical unit. For
example, if a program needs to handle information about books, a structure can be
created with members like title, author, price, etc.
• Modularity and Readability: Using structures increases the modularity of the
program, making it easier to understand, maintain, and modify.
• Use Cases: Structures are widely used in various programming scenarios such as
data modeling, representing complex entities (like students, employees, etc.), and in
systems programming.
Example 1:
#include <stdio.h>
struct Student
{
char name[50];
int age;
float marks;
};
int main()
{
struct Student student1;
// Use student1...
return 0;
}
Explanation:
• struct Student is defined with members: name, age, and marks.
• An instance student1 of struct Student is declared.
Example 2:
#include <stdio.h>
struct Date
{
int day, month, year;
};
struct Student
{
char name[50];
struct Date dob;
float marks;
};
int main()
{
struct Student student1;
// Use student1...
return 0;
}
Explanation:
• Two structures are defined: struct Date and struct Student.
• struct Student contains a nested structure struct Date.
Example 3:
struct Book
{
char title[50];
char author[50];
float price;
int pages;
};
int main()
{
struct Book book1;
// book1 can now hold information about a book
return 0;
}
In this example, a struct Book is defined with four members: title, author, price, and pages.
book1 is then declared as an instance of struct Book, ready to store information about a
specific book.
Explanation:
Defining the Structure
struct Book
{
char title[50];
char author[50];
float price;
int pages;
};
• struct Book { ... };:
o This line begins the definition of a structure named Book.
• Inside the curly braces { ... }, the members (or fields) of the structure are declared:
o char title[50];: A character array named title, which can hold a string up to 49
characters long (plus the null terminator \0 that signifies the end of the string)
is declared. This is intended to store the title of the book.
o char author[50];: Similarly, this is a character array to store the author's
name, following the same logic as title.
o float price;: A float variable to store the price of the book.
o int pages;: An integer variable to store the number of pages in the book.
• The semicolon ; at the end of the structure definition is crucial as it marks the end of
the structure definition in C.
Additional Point:
For Example:
strcpy(book1.title, "C Programming Language");
strcpy(book1.author, "Brian W. Kernighan and Dennis M. Ritchie");
book1.price = 45.99;
book1.pages = 279;
After declaring book1, you can assign values to its members, as Stated in the Above Example.
Each member of book1 can be accessed using the dot operator ., as shown in the example
above.
Initializing Structures
Initialization of structures in C involves setting initial values to the members of the structure
at the time of its declaration. This can be done in several ways:
• List Initialization: Assigning values to each member in the order they are declared
in the structure.
• Designated Initialization: (Available in C99 and later) Assigning values to specific
members using their names.
• Zero Initialization: Initializing all members to zero or null by default.
Example:
Let's consider a structure Book and demonstrate different ways of initializing it.
#include <stdio.h>
struct Book
{
char title[50];
char author[50];
float price;
int pages;
};
int main() {
// List Initialization
struct Book book1 = {"The C Programming Language", "Kernighan and Ritchie", 45.50,
279};
// Designated Initialization
struct Book book2 = {.title = "1984", .author = "George Orwell", .price = 9.99, .pages = 328};
return 0;
}
Output:
Book 1:
Title: The C Programming Language
Author: Kernighan and Ritchie
Price: 45.50
Pages: 279
Book 2:
Title: 1984
Author: George Orwell
Price: 9.99
Pages: 328
Explanation:
Structure Definition:
A structure Book with members title, author, price, and pages is defined.
List Initialization (book1):
• book1 is initialized using list initialization. The values are assigned in the order the
members are defined in the structure.
• "The C Programming Language", "Kernighan and Ritchie", 45.50, and 279 are
assigned to title, author, price, and pages of book1, respectively.
This example illustrates how to initialize structures in C and how to access and use their
members. The initialization ensures that the structure variables book1 and book2 hold
specific data right from their declaration, making them ready for use in the program.
Example:
Consider a Book structure and a function that modifies and prints its contents.
#include <stdio.h>
struct Book {
char title[50];
char author[50];
float price;
int pages;
};
int main() {
struct Book book1 = {"1984", "George Orwell", 15.99, 328};
return 0;
}
Output:
Original Book:
Title: 1984
Author: George Orwell
Price: 15.99
Pages: 328
Updated Book:
Title: 1984
Author: George Orwell
Price: 12.99
Pages: 328
Explanation:
Structure Definition and Initialization:
• The Book structure is defined with members title, author, price, and pages.
• book1 is initialized with an initializer list. The values "1984", "George Orwell", 15.99,
and 328 are assigned to the respective members.
Function Call:
• In main, the function updateBook is called, passing the address of book1 and the new
price 12.99.
• The function modifies book1's price and prints the updated details.
This example demonstrates the interaction between structures and functions in C. The
structure is used to group related data, and the function manipulates this data, showcasing
a common pattern in structured programming. The use of a pointer to pass the structure to
the function allows for efficient memory usage and direct modification of the original
structure.
Array of Structures
An array of structures in C is a powerful way to store and manipulate a collection of
structured data. Initializing an array of structures involves setting initial values for each
structure in the array.
Methods of Initialization
• Using an Initializer List: Similar to initializing individual structures, but repeated
for each element in the array.
• Designated Initializers: (Available in C99 and later) Allows initializing specific
members in each structure of the array.
• Manual Initialization: Individually setting values for each member of each structure
in the array, often done inside a loop or a function.
Example:
Consider an example where an array of a Book structure is initialized and used.
#include <stdio.h>
struct Book
{
char title[50];
char author[50];
float price;
int pages;
};
int main()
{
// Array of structures initialization
struct Book library[2] =
{
{"1984", "George Orwell", 9.99, 328},
{"The C Programming Language", "Kernighan and Ritchie", 45.50, 279}
};
Book 2:
Title: The C Programming Language
Author: Kernighan and Ritchie
Price: 45.50
Pages: 279
Explanation:
Structure Definition:
• The Book structure is defined with members title, author, price, and pages.
• The members of each Book structure in the array are accessed using the dot operator
. (e.g., library[i].title).
Case Study:
Create A Structure (to Store Marks of 4 Courses English, Mathematics, Chemistry and CTP,
Student ID). The Structure Shall Store Marks of N Students for Each Course. Marks can be
floating point values, Student ID Could be Both Numbers and Characters (for Example S1)
Using Different Functions to Read Marks, Find Minimum, Maximum and Average Marks for
Each Course, Display Minimum, Maximum and Average Marks for each course. While
Displaying Minimum and Maximum Marks Also Display the Student ID Obtained them.
Program:
#include <stdio.h>
#include <string.h>
min[j] = students[0].marks[j];
strcpy(minId[j], students[0].id);
for (int i = 1; i < n; i++)
{
if (students[i].marks[j] < min[j])
{
min[j] = students[i].marks[j];
strcpy(minId[j], students[i].id);
}
}
}
}
void displayResults(float min[], float max[], float avg[], char minId[][10], char maxId[][10])
{
const char *courses[] = {"English", "Mathematics", "Chemistry", "CTP"};
for (int i = 0; i < NUM_COURSES; i++)
{
printf("%s:\n", courses[i]);
printf("Minimum: %.2f (Student ID: %s)\n", min[i], minId[i]);
printf("Maximum: %.2f (Student ID: %s)\n", max[i], maxId[i]);
printf("Average: %.2f\n\n", avg[i]);
}
}
int main()
{
struct Student students[MAX_STUDENTS];
int n;
readMarks(students, n);
return 0;
}
Output:
Enter the number of students: 2
Enter ID for student 1: S1
Enter marks for English, Mathematics, Chemistry, CTP: 15 16 7 9
Enter ID for student 2: S2
Enter marks for English, Mathematics, Chemistry, CTP: 14 18 6 7
English:
Minimum: 14.00 (Student ID: S2)
Maximum: 15.00 (Student ID: S1)
Average: 14.50
Mathematics:
Minimum: 16.00 (Student ID: S1)
Maximum: 18.00 (Student ID: S2)
Average: 17.00
Chemistry:
Minimum: 6.00 (Student ID: S2)
Maximum: 7.00 (Student ID: S1)
Average: 6.50
CTP:
Minimum: 7.00 (Student ID: S2)
Maximum: 9.00 (Student ID: S1)
Average: 8.00
Explanation:
Structure Definition and Constants
#define MAX_STUDENTS 100
#define NUM_COURSES 4
struct Student {
char id[10];
float marks[NUM_COURSES]; // 0: English, 1: Mathematics, 2: Chemistry, 3: CTP
};
• #define MAX_STUDENTS 100: This line defines a preprocessor macro
MAX_STUDENTS with a value of 100, which sets the maximum number of students
that can be handled by the program.
• #define NUM_COURSES 4: Similar to MAX_STUDENTS, this line defines
NUM_COURSES as 4, indicating the number of courses (English, Mathematics,
Chemistry, and CTP).
• struct Student { ... };: This defines a structure Student with two members: id (an array
of 10 chars for storing the student ID) and marks (an array of 4 floats to store the
marks for each of the four courses).
Function readMarks()
void readMarks(struct Student students[], int n)
{
for (int i = 0; i < n; i++)
{
printf("Enter ID for student %d: ", i + 1);
scanf("%s", students[i].id);
printf("Enter marks for English, Mathematics, Chemistry, CTP: ");
for (int j = 0; j < NUM_COURSES; j++)
{
scanf("%f", &students[i].marks[j]);
}
}
}
• This function reads the marks and IDs for n students.
• for (int i = 0; i < n; i++): Loops through each student.
• scanf("%s", students[i].id);: Reads the student ID.
• for (int j = 0; j < NUM_COURSES; j++): Nested loop to read marks for each course.
Function findMinimum()
void findMinimum(struct Student students[], int n, float min[], char minId[][10])
{
// ... (similar logic as findMaximum)
}
• Finds the minimum marks for each course.
• min[] and minId[] are used to store the minimum marks and the corresponding
student IDs.
Function findMaximum()
void findMaximum(struct Student students[], int n, float max[], char maxId[][10])
{
// ... (similar logic as findMinimum)
}
• Finds the maximum marks for each course.
• max[] and maxId[] are used to store the maximum marks and the corresponding
student IDs.
Function calculateAverage()
void calculateAverage(struct Student students[], int n, float avg[])
{
// ...
}
• Calculates the average marks for each course.
• avg[] is used to store the calculated averages.
Function displayResults()
void displayResults(float min[], float max[], float avg[], char minId[][10], char maxId[][10])
{
// ...
}
• Displays the minimum, maximum, and average marks for each course, along with the
student IDs of those who scored the minimum and maximum marks.
Main Function()
int main() {
struct Student students[MAX_STUDENTS];
int n;
readMarks(students, n);
return 0;
}
• struct Student students[MAX_STUDENTS];: Declares an array students of Student
structures to store data for up to MAX_STUDENTS.
• int n;: Declares an integer n to store the actual number of students.
• scanf("%d", &n);: Reads the number of students.
• readMarks(students, n);: Calls readMarks to input student IDs and marks.
• The arrays min, max, avg, minId, and maxId are declared for storing the results.
• findMinimum, findMaximum, and calculateAverage functions are called to process the
data.
• displayResults is called to display the outcomes.
• return 0;: Indicates successful program termination.
Each function in the program is dedicated to handling a specific part of the process, such as
reading data, finding minimum or maximum marks, calculating averages, or displaying
results. This modular approach enhances the readability and maintainability of the code.
File – Definition
A file in computing is a collection of data or information that is identified by a name and
stored on a storage device, like a hard disk. In programming, files are critical for storing data
permanently, enabling information to persist beyond the runtime of the program.
A file is a container in a computer system for storing data. Files can store a wide range of
data, from written text to binary information like images or executable programs. In
programming, files are essential for data persistence, enabling data to be stored permanently,
as opposed to volatile memory storage, which is lost when a program terminates or the
computer is turned off.
Introduction to Files
• Persistence: Files provide a way to store data persistently. Files allow programs
written in C to store data permanently, as opposed to variables and arrays which are
temporary and are lost when the program ends.
• Data Access: They enable both sequential and random access to data.
• Types of Files: Typically, files are categorized as text files (human-readable) and
binary files (computer-readable). Mainly, there are two types of files – text files
(readable by humans and computers) and binary files (primarily readable by
computers).
File Management
Creating
Use of fopen: The fopen function is used to create and open files. If the file does not exist, it
can create a new file, depending on the mode specified.
Function Used: fopen()
Modes: "w" for writing (creates a new file), "wb" for writing in binary mode.
Explanation:
Opening a File for Writing
FILE *file = fopen("example.txt", "w");
This line attempts to open (or create if it doesn't exist) a file named example.txt in write mode
("w").
fopen is used for this task. If successful, it returns a pointer to a FILE object, which is stored
in the variable file.
Output:
Explanation:
Opening a File for Writing in Binary Mode
FILE *file = fopen("example.bin", "wb");
The program begins by trying to open (or create if it doesn't exist) a file named example.bin
in binary write mode ("wb").
fopen is used for this purpose, and if successful, it returns a pointer to a FILE object, which
is assigned to the variable file.
Reading
Reading Methods: Methods include fscanf, fgets, and direct character reading using fgetc.
Function Used: fscanf() for formatted reading, fgets() for string reading, fread() for binary
reading.
Example 1: Reading a Text File
#include <stdio.h>
int main()
{
FILE *file = fopen("example.txt", "r");
char buffer[100];
if (file == NULL)
{
printf("Error opening file.\n");
return 1;
}
while (fgets(buffer, 100, file) != NULL)
{
printf("%s", buffer);
}
fclose(file);
return 0;
}
Output:
Explanation:
Opening the File
FILE *file = fopen("example.txt", "r");
This line attempts to open a file named example.txt in read mode ("r"). The fopen function is
used for this purpose.
If successful, fopen returns a pointer to a FILE object, which is stored in the variable file.
Example 1:
#include <stdio.h>
int main()
{
FILE *file = fopen("textfile.txt", "w");
if (file == NULL) {
printf("Error opening file.\n");
return 1;
}
fclose(file);
Explanation:
• Open the File for Writing:
o FILE *file = fopen("textfile.txt", "w");: Opens (or creates) textfile.txt in write
mode. If the file already exists, it's truncated to zero length.
• Error Handling:
o if (file == NULL) { ... }: Checks if the file was opened successfully. If not (file ==
NULL), it prints an error message and exits with a return code of 1.
• Writing to the File:
o fprintf(file, "Hello, World!\n"); and the next fprintf: Writes two lines of text into
the file.
• Closing the File:
o fclose(file);: Closes the file, which is important to ensure that the data is
properly saved.
• Success Message:
o printf("Text file written successfully.\n");: Prints a message to the console
indicating successful file writing.
• Program Exit:
o return 0;: Indicates that the program has executed successfully.
Example 2:
#include <stdio.h>
int main()
{
int numbers[] = {1, 2, 3, 4, 5};
FILE *file = fopen("binaryfile.bin", "wb");
if (file == NULL) {
printf("Error opening file.\n");
return 1;
}
fclose(file);
Explanation:
Step 1: Open the File
FILE *file = fopen("example.txt", "r+");
• fopen: This function opens a file. "example.txt" is the name of the file, and "r+" is the
mode. Here, "r+" means the file is opened for reading and writing.
• file: This is a pointer to FILE, a structure that stores information about the file.