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

Coding Techniques Notes

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

Coding Techniques Notes

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 222

UNIT –I : PROBLEM SOLVING FUNDAMENTALS

1.1 Programs and Algorithms


Computer Science and Software Development requires basic knowledge in
Programs and Algorithms in C.Programs in C are the language of instructions
written in the C programming language which tell a computer what to do on
certain tasks. It is known for its efficiency and closeness to hardware since it is
a powerful, widely used language. It’s used for many things including
operating systems as well as embedded systems.On the other hand, algorithms
are step by step procedures or formulas used to solve problems or perform
tasks. They usually form the logical structure of any program that explains how
data should be processed for desired outcomes.

The importance of combining C programming with algorithms includes:

Efficiency- Precise control over computer resources which results into efficient
implementation complex algorithms is possible under C.
Problem-solving – In C, structured approaches to solving computational
problems can be effectively implemented through algorithms.
Foundation for advanced concepts – Learning more advanced programming
languages and concepts can be based on understanding C and algorithms.
Versatility- Different platforms and systems can apply algorithms developed in
C due to wide range applicability of C.
Performance optimization-C’s low level capabilities allow fine tuning of
algorithm.

1.2 Problem Definition


In C programming, problem definition is the process of identifying the input
and output of a problem, and assigning variable names to each item. is the first
crucial step in the problem-solving process. It involves clearly understanding
and stating the problem you need to solve using C code.A problem definition
should include:
● Constraints: Are there any limitations or specific requirements you must
adhere to?
● Precise definition: A clear statement of the problem
● Understanding: A thorough understanding of the problem

Example:
Problem statement: Write a C program to calculate the factorial of a given
number.

Input format: An integer n representing the number for which factorial is to


be calculated.
Output format: An integer representing the factorial of n.
Constraints: 0 <= n <= 12
1.3.Flow Chart

1.3.1 What is a Flowchart?


Flowchart is a graphical representation of an algorithm. Programmers often use
it as a program-planning tool to solve a problem. It makes use of symbols
which are connected among them to indicate the flow of information and
processing.
The process of drawing a flowchart for an algorithm is known as
“flowcharting”.
1.3.2 Basic Symbols used in Flowchart Designs
Terminal: The oval symbol indicates Start, Stop and Halt in a program’s logic
flow. A pause/halt is generally used in a program logic under some error
conditions. Terminal is the first and last symbols in the flowchart.

Input/Output: A parallelogram denotes any function of input/output type.


Program instructions that take input from input devices and display output on
output devices are indicated with parallelogram in a flowchart.

Processing: A box represents arithmetic instructions. All arithmetic processes


such as adding, subtracting, multiplication and division are indicated by action
or process symbol.

Decision Diamond symbol represents a decision point. Decision based


operations such as yes/no question or true/false are indicated by diamond in
flowchart.
Connectors: Whenever flowchart becomes complex or it spreads over more
than one page, it is useful to use connectors to avoid any confusions. It is
represented by a circle.

Flow lines: Flow lines indicate the exact sequence in which instructions are
executed. Arrows represent the direction of flow of control and relationship
among different symbols of flowchart.

1.3.3 Rules For Creating Flowchart :


A flowchart is a graphical representation of an algorithm.it should follow some
rules while creating a flowchart
Rule 1: Flowchart opening statement must be ‘start’ keyword.
Rule 2: Flowchart ending statement must be ‘end’ keyword.
Rule 3: All symbols in the flowchart must be connected with an arrow line.
Rule 4: The decision symbol in the flowchart is associated with the arrow line.

1.3.4 Advantages of Flowchart:


● Flowcharts are a better way of communicating the logic of the system.
● Flowcharts act as a guide for blueprint during program designed.
● Flowcharts help in debugging process.
● With the help of flowcharts programs can be easily analyzed.
● It provides better documentation.
● Flowcharts serve as a good proper documentation.
● Easy to trace errors in the software.
● Easy to understand.
● The flowchart can be reused for inconvenience in the future.
● It helps to provide correct logic.
1.3.5 Disadvantages of Flowchart:
● It is difficult to draw flowcharts for large and complex programs.
● There is no standard to determine the amount of detail.
● Difficult to reproduce the flowcharts.
● It is very difficult to modify the Flowchart.
● Making a flowchart is costly.
● Some developers think that it is a waste of time.
● It makes software processes low.
● If changes are done in software, then the flowchart must be redrawn

1.Draw a flowchart to input two numbers from the user and display the
largest of two numbers
1.4.Fundamental Algorithms

1.4.1 Exchange of values of two variables

Problem

Given two variables, a and b, exchange the values assigned to them.

Algorithm development: The problem of interchanging the values associated


with two variables involves a very fundamental mechanism that occurs in many
sorting and data manipulation algorithms. To define the problem more clearly
we will examine a specific example.
Consider that the variables a and b are assigned values as outlined below. That
is,

This means that memory cell or variable a contains the value 721, and memory
cell or variable b contains the value 463. Our task is to replace the contents of a
with 463, and the contents of b with 721. In other words we want to end up
with the configuration below:

To change the value of a variable we can use the assignment operator. Because
we want a to assume the value currently belonging to b, and b the value
belonging to a we could perhaps make the exchange with the following
assignments:

a := b (1)

b := b (2)

where ":=" is the assignment operator. In (1) ":=" causes the value stored in
memory cell b to be copied into memory cell a.
Let us work through these two steps to make sure they have the desired effect.

We started out with the configuration

Then after the execution of the assignment a:=b we have

The assignment (1) has changed the value of a but has left the value of b
untouched. Checking with our target configuration we see that a has assumed
the value 463 as required. So far so good! We must also check on b. When the
assignment step (2) i.e. b:= a is made after executing step (1) we end up with:

In executing step (2), a is not changed while b takes on the value that currently
belongs to a. The configuration that we have ended up with does not represent
the solution we are seeking. The problem arises because in making the
assignment:

a := b

we have lost the value that originally belonged to a (i.e. 721 has been lost). It is
this value that we want b to finally assume. Our problem must therefore be
stated more carefully as:

new value of a := old value of b;

new value of b := old value of a

What we have done with our present proposal is to make the assignment

new value of b := new value of a

In other words when we execute step (2) we are not using the value a that will
make things work correctly because a has already changed. To solve this
exchange problem we need to find a way of not destroying "the old value of a"
when we make the assignment
a := b

A way to do this is to introduce a temporary variable t and copy the original


value of a into this variable before executing step (1). The steps to do this are:

t := a;
a := b

After these two steps we have

We are better off than last time because now we still have the old value of a
stored in t. It is this value that we need for assignment to b. We can therefore
make the assignment
b := t

After execution of this step we have:

Rechecking with our target configuration we see that a and b have now been
interchanged as required.

The exchange procedure can now be outlined.

Algorithm Description

1. Save the original value of a in t.

2. Assign to a, the original value of b.

3. Assign to b, the original value of a that is stored in t.

The exchange mechanism as a programming tool is most usefully implemented


as a procedure that accepts two variables and returns their exchanged values.

Applications

Sorting algorithms
1.4.2. Counting

Problem

Given a set of n students' examination marks (in the range 0 to 100) make a
count of the number of students that passed the examination. A pass is awarded
for all marks of 50 and above.

Algorithm development

Counting mechanisms are very frequently used in computer algorithms.


Generally a count must be made of the number of items in a set which possess
some particular property or which satisfy some particular condition or
conditions. This class of problems is typified by the "examination marks"
problem.

As a starting point for developing a computer algorithm for this problem we


can consider how we might solve a particular example by hand.
Suppose that we are given the set of marks 55, 42, 77, 63, 29, 57, 89
To make a count of the passes for this set we can start at the left, examine the
first mark (i.e. 55), see if it is ≥50, and remember that one student has passed so
far. The second mark is then examined and no adjustment is made to the count.
When we arrive at the third mark we see it is ≥50 and so we add one to our
previous count. The process continues in a similar manner until all marks have
been tested.

In more detail we have:

After each mark has been processed the current count reflects the number of
students that have passed in the marks list so far encountered. We must now
ask, how can the counting be achieved? From our example above we see that
every time we need to increase the count we build on the previous value. That
is

current_count = previous_count+1
When, for example, we arrive at mark 57, we have

previous_count = 3

Current count therefore becomes 4. Similarly when we get to the next mark
(i.e. 89) the current count of 4 must assume the role of previous_count. This
means that whenever a new current count is generated it must then assume the
role of previous_count before the next mark is considered. The two steps in this
process can be represented by

current_count := previous_count+1 (1)

previous_count := current_count (2)

These two steps can be repeatedly applied to obtain the count required. In
conjunction with the conditional test and input of the next mark we execute
step (1), followed by step (2), followed by step (1), followed by step (2) and so
on.
Because of the way in which previous count is employed in step (1) we can
substitute the expression for previous_count in step (2) into step (1) to obtain
the simpler expression

The current count on the RHS (right-hand side) of the expression assumes the
role of previous count. As this statement involves an assignment rather than an
equality (which would be impossible) it is a valid computer statement. What it
describes is the fact that the new value of current count is obtained by adding 1
to the old value of current_count.

Viewing the mechanism in this way makes it clear that the existence of the
variable previous count in its own right is unnecessary. As a result we have a
simpler counting mechanism.The essential steps in our pass-counting algorithm
can therefore be summarized as:

while less then n marks have been examined, do


(a). read next mark,
(b). if current mark satisfies pass requirement then add one to count.

Before any marks have been examined the count must have the value zero. To
complete the algorithm the input of the marks and the output of the number of
passes must be included. The detailed algorithm is then as described below.
Algorithm description

1. Prompt then read the number of marks to be processed.

2. Initialize count to zero.

3 While there are still marks to be processed repeatedly do

(a). read next mark,

(b). if it is a pass (i.e. ≥50) then add one to count.

4. Write out total number of passes.

Applications:
All forms of counting.

1.4.3 Summation Of A Set Of Numbers

Problem

Given a set of numbers, design an algorithm that adds these numbers and
returns the resultant sum. Assume n is greater than or equal to zero.

Algorithm development

One of the most fundamental things that we are likely to do with a computer is
to add a set of n numbers. When confronted with this problem in the absence of
a computer we simply write the numbers down one under the other and start
adding up the right-hand column. For example, consider the addition of 421,
583 and 714..

In designing a computer algorithm to perform this task we must take a


somewhat different approach. The computer has a built-in device which accepts
two numbers to be added, performs the addition, and returns the sum of the two
numbers. In designing an algorithm to add a set of numbers a primary concern
is the mechanism for the addition process. We will concentrate first on this
aspect of the problem before looking at the overall design.
The simplest way that we can instruct the computer's arithmetic unit to add a
set of numbers is to write down an expression that specifies the addition we
wish to be performed. For our three numbers mentioned previously we could
write

s := 421 + 583 + 714 (1)

The assignment operator causes the value resulting from the evaluation of the
right-hand side of statement (1) to be placed in the memory cell allocated to the
variable s.

Expression (1) will add three specific numbers as required. Unfortunately it is


capable of doing little else. Suppose we wanted to sum three other numbers.
For this task we would need a new program statement.

It would therefore seem reasonable that all constants in expression (1) could be
replaced by variables. We would then have

s := a + b + c (2)

Expression (2) adds any three numbers provided they have been previously
assigned as values or contents of a, b, and e respectively. Expression (2) as the
basis of a program for adding numbers is more general and more useful than
expression (1). It still has a serious deficiency - it can only add sets of three
numbers.

A fundamental goal in designing algorithms and implementing programs is to


make the programs general enough so that they will successfully handle a wide
variety of input conditions. That is, we want a program that will add any
numbers where n can take on a wide range of values. The approach we need to
take to formulate an algorithm to add n numbers in a computer is different from
what we would do conventionally to solve the problem. Conventionally we
could write the general equation

s=(a1 + a2 + a3 + ….. + an). (3)

n
or equivalently s = Σ ai (4)
i=1

(Reminder: ∑ is the mathematical summation


operator)

We could also write a computer program statement somewhat like equation (3)
to add our n numbers but this is not very practical because we want to be able
to change n (we may want to use the program to sum a different sized set of
numbers). We must therefore look for a better mechanism more in keeping with
the way a computer is naturally designed to do things. Several facts about
computers are relevant for our current problem. Firstly, computers are well
suited to do repetitive things. Secondly, the computer's adding device is
designed so that it can only add two numbers at a time. We might therefore ask
how we can formulate an algorithm for the addition of n numbers that makes
best use of these facts.

One way to do this that takes note of the fact that the computer adds two
numbers at a time is to start by adding the first two numbers a1 and a2. That is,

s := a1 + a2 (1)

We could then proceed by adding a3 to the s computed in step (1).

s := s + a3 (2)

In a similar manner:

From step (2) onwards we are actually repeating the same process over and
over. The only difference is that values of a and s change with each step. For
general ith step we have

s := s+ai+1 (i)

This general step can be placed in a loop to iteratively generate the sum of n
numbers.

The algorithm we want to develop for summing n numbers should perform


correctly for all values of n greater than or equal to 0 (i.e n>=0). It must
therefore work correctly for the sum of zero (n = 0) and the sum of 1 (n = 1)
numbers. This means the step (1) we have used is not appropriate. However, if
we replace i + 1 in the general step (i), by i and substitute i = 1 we get:

s:= s + a1 (1')

The step (1') will be correct provided s:= 0 before this step is executed. It
follows that all sums for n>=1 can be generated iteratively. The instance where
n = 0 is a special case which cannot be generated iteratively. The sum of zero
numbers is zero and so we can generate the first sum directly by the assignment

s:= 0

The core of the algorithm for summing n numbers therefore involves a special
step followed by a set of n iterative steps. That is,

1. Compute first sum (s=0) as special case.

2. Build each of the n remaining sums from its predecessor by an iterative


process.

3. Write out the sum of n numbers.

Algorithm description

1. Prompt and read in the number of numbers to be summed.

2. Initialize sum for zero numbers.

3. While less than n numbers have been summed repeatedly do

(a) read in next number,

(b) compute current sum by adding the number read to the most
recent sum.

4. Write out sum of n numbers.

Applications

Average calculations, variance and least squares calculations.

1.5 Fundamental Algorithms

1.5.1 Factorial Computation

Problem

Given a number n, compute n factorial (written as n!) where n >= 0 .

Algorithm development

We can start the development of this algorithm by examining the definition


of n! We are given that

n!=1 x 2 x 3 x ……x (n - 1) x n for n >= 1

and by definition

0! = 1

In formulating our design for this problem we need to keep in mind that the
computer's arithmetic unit can only multiply two numbers at a time.

Applying the factorial definition we get

0! = 1
1! = 1 x 1
2! = 1 x 2
3! = 1 x 2 x 3
4! = 1 x 2 x 3 x 4
.
.
.

We see that 4! contains all the factors of 3!. The only difference is the inclusion
of the number 4. We can generalize this by observing that n! can always be
obtained from (n - 1)! by simply multiplying it by n (for n >= 1) That is,

n! = n x (n - 1)! for n >= 1

Using this definition we can write the first few factorials as:

1! = 1 x 0!
2! = 2 x 1!
3! = 3 x 2!
4! = 4 x 3! and so on

If we start with p = 0! = 1 we can rewrite the first few steps in computing n!

as:
From step (2) onwards we are actually repeating the same process over and
over. For the general (i+1)th step we have

p := p x i (i+1)

This general step can be placed in a loop to iteratively generate n!. This allows
us to take advantage of the fact that the computer's arithmetic unit can only
multiply two numbers at a time.

In many ways this problem is very much like the problem of summing a set of
n numbers. In the summation problem we performed a set of additions, whereas
in this problem we need to generate a set of products. It follows from the
general (i+1)th step that all factorials for n≥1 can be generated iteratively. The
instance where n = 0 is a special case which must be accounted for directly by
the assignment

p := 1 (by definition of 0!)

The central part of the algorithm for computing n! therefore involves a special
initial step followed by n iterative steps.

1. Treat 0! as a special case (p := 1).

2. Build each of the n remaining products p from its predecessor by an iterative


process.

3. Write out the value of n factorial.

Algorithm description

1. Establish n, the factorial required where n>=0.

2. Set product p for 0! (special case). Also set product count to zero.

3. While less than n products have been calculated repeatedly do

(a) increment product count,

(b) compute the ith product p by multiplying i by the most recent product.

4. Return the result n!.

This algorithm is most usefully implemented as a function that accepts as input


a number n and returns as output the value of n!.
Applications

Probability, statistical and mathematical computations.

1.5.2 Sine Function Computation

Problem

Design an algorithm to evaluate the function sin(x) as defined by the infinite


series expansion

Algorithm development

This problem embodies some of the techniques we have seen in earlier


algorithms. Studying the expression for sin (x) we see that powers and
factorials following the sequence

1, 3, 5, 7, …

are required. We can easily generate this odd sequence by starting with 1 and
successively adding 2. Our other problem is to compute the general term
, which can be expressed as

The function we need to compute this will involve the following steps:

The algorithm can be completed by implementing the additions and


subtractions and making the appropriate termination. With this approach each
term (i.e. ) is computed by starting at the smallest j value and working
upwards. In calculating n! we used the efficient approach of calculating each
term from its predecessor. The question this raises is can we do the same with
the present problem? To explore this possibility we can examine the overlap for
some specific terms of the series. For example,

Each of the terms can be described by the


general term:

Therefore to generate consecutive terms of the sine series we can use

To get the terms to alternate in sign we can repeatedly execute,

sign := – sign

This will generate alternating positive and negative terms. This can be
incorporated directly into our term expression. The initial conditions are
therefore

The ith term and summation which can be generated iteratively from their
predecessors are:

We now have an effective iterative mechanism for generating successive terms


of the sine function. The only other consideration is how to terminate the
algorithm.

Clearly we can only evaluate sin (x) to a finite number of terms. An important
consideration here is the desired accuracy we require for sin (x). Because x is
in the range -1<=x<=1 we can see that the contribution from higher terms
quickly becomes very small. For example the 4th term (i.e. ) makes a
contribution of less than 0.0002. In circumstances like this a useful way to
bring about termination is to fix an acceptable error level (e.g. ) and
generate successive terms until the contribution of the current term is less than
the acceptable error. A detailed error analysis of the problem confirms that this
is an acceptable termination condition. Because the terms alternate in sign we
will have to use the absolute error term value for the termination test.

The overall strategy for our sine function algorithm can be summarized as
follows.

Algorithm description

1. Set up initial conditions for the first term that cannot be computed iteratively.

2. While the absolute value of current term is greater than the acceptable error

do
(a) identify the current ith term,

(b) generate current term from its predecessor.

(c) add current term with the appropriate sign to the accumulated sum
for the sine function.

Since the sine expression involves the calculation of a single value it is best
implemented as a function.

Applications
Mathematical and statistical computations.

1.6 Fundamental Algorithms

1.6.1 Generation Of Fibonacci Sequence

Problem

Generate and print the first n terms of the Fibonacci sequence where n≥1. The
first few terms are:

0, 1, 1, 2, 3, 5, 8, 13, ...
Each term beyond the first two is derived from the sum of its two nearest
predecessors.
Algorithm development

From the definition we are given that:

new term = preceding term + term before preceding term

The last sentence of the problem statement suggests we may be able to use the
definition to generate consecutive terms (apart from the first two) iteratively.

Let us define:

a as the term before the preceding term

b as the preceding term

c new term

Then to start with we have:

a := 0 first Fibonacci number

b := 1 second Fibonacci number

c:= a+b third Fibonacci number (from definition)

When the new term c has been generated we have the third Fibonacci number.
To generate the fourth, or next Fibonacci number, we need to apply the same
definition again. Before we can make this next computation we need to make
some adjustments. The fourth Fibonacci number is derived from the sum of the
second and third Fibonacci numbers. With regard to the definition, the second
Fibonacci number has the role of the term before the preceding term and the
third Fibonacci number has the role of "the preceding term". Therefore, before
making the next (i.e. the fourth) computation we must ensure that:

(a) new term (i.e. the third) assumes the role of the preceding term.

(b) and what is currently the preceding term must assume the role of the term
before the preceding term.

That is,

a := 0 [1] term before preceding term

b := 1 [2] preceding term


c := a + b [3] new term

a := b [4] term before preceding term becomes preceding term

b := c [5] preceding term becomes new term

After making step [5] we are in a position where we can use the definition to
generate the next Fibonacci number. A way to do this is to loop back to step
[3]. Further investigation of steps [3] → [5] indicates they can be placed in a
loop to iteratively generate Fibonacci numbers (for n > 2 ).

Algorithm description

1. Prompt and read n, the number of Fibonacci numbers to be generated.

2. Assign first two Fibonacci numbers a and b.

3. Initialize count of number generated.

4. While less than Fibonacci numbers have been generated do

(a) write out next two Fibonacci numbers;

(b) generate next Fibonacci number keeping ‘a’ relevant.

(c) generate next Fibonacci number from most recent pair keeping ‘b’
relevant for next computation;

(d) update count of number of Fibonacci numbers generated, i.

5. If n even then write out last two Fibonacci numbers else write out second last
Fibonacci number.

Applications

Th Fibonacci sequence has practical applications in botany, electrical network


theory, sorting, and searching.
1.6.2 Reversing The Digits Of An Integer

Problem

Design an algorithm that accepts a positive integer and reverses the order of its
digits.

Algorithm development

Digit reversal is a technique that is sometimes used in computing to remove


bias from a set of numbers. It is important in some fast information-retrieval
algorithms. A specific example clearly defines the relationship of the input to
the desired output. For example,

Input : 27953

Output : 35972

Although we might not know at this stage exactly how we are going to make
this reversal one thing is clear – we are going to need to access individual digits
of the input number. As a starting point we will concentrate on this aspect of
the procedure. The number 27953 is actually

To access the individual digits it is probably going to be easiest to start at one


end of the number and work through to the other end. The question is at which
end should we start? Because other than visually it is not easy to tell how many
digits there are in the input number it will be best to try to establish the identity
of the least significant digit (i e. the rightmost digit). To do this we need to
effectively chop off the least significant digit in the number. In other words we
want to end up with 2795 with the 3 removed and identified.

We can get the number 2795 by integer division of the original number by 10

i.e. 27953 div 10 → 2795

This chops off the 3 but does not allow us to save it. However, 3 is the
remainder that results from dividing 27953 by 10. To get this remainder we can
use the mod function. That is,

27953 mod 10 → 3

Therefore if we apply the following two steps


we get the digit 3, and the new number 2795. Applying the same two steps to
the new value of n we can obtain the 5 digit. We now have a mechanism for
iteratively accessing the individual digits of the input number.

Our next major concern is to carry out the digit reversal. When we apply our
digit extraction procedure to the first two digits we acquire first the 3 and then
5. In the final output they appear as:

3 followed by 5 (or 35)

If the original number was 53 then we could obtain its reverse by first
extracting the 3, multiplying it by 10, and then adding 5 to give 35. That is,

3×10+5 → 35

The last three digits of the input number are 953. They appear in the "reversed"
number as 359. Therefore at the stage when we have the 35 and then extract the
9 we can obtain the sequence 359 by multiplying 35 by 10 and adding 9. That
is,

The last number obtained from the multiplication and addition process is the
"digit-reversed" integer we have been seeking. On closely examining the digit
extraction, and the reversal process, it is evident that they both involve a set of
steps that can be performed iteratively.

We must now find a mechanism for building up the "reversed" integer digit by
digit. Let us assume that the variable dreverse is to be used to build the
reversed integer. At each stage in building the reversed integer its previous
value is used in conjunction with the most recently extracted digit. Rewriting
the multiplication and addition process we have just described in terms of the
variable dreverse we get
The variable dreverse can be used on both sides of this expression. For the
value of dreverse to be correct (ie. dreverse = 3) after the first iteration it must
initially be zero. This initialization step for dreverse is also needed to ensure
that the algorithm functions correctly when the input number to be reversed is
0.

Algorithm description

1. Establish n. the positive integer to be reversed.

2. Set the initial condition for the reversed integer dreverse.

3. While the integer being reversed is greater than zero do

(a) use the remainder function to extract the rightmost digit of the number
being reversed:

(b) increase the previous reversed integer representation dreverse by a


factor of 10 and add to it the most recently extracted digit to give the
current dreverse value:

(c) use integer division by 10 to remove the rightmost digit from the number
being reversed.

This algorithm is most suitably implemented as a function which accepts as


input the integer to be reversed and returns as output the integer with its digits
reversed.

Applications

Hashing and information retrieval,database applications.


1.7 Fundamental Algorithms

1.7.1 Base Conversion

Problem

Convert a decimal integer to its corresponding octal representation.

Algorithm development

Frequently in computing it is necessary to convert a decimal number to the


binary, octal or hexadecimal number systems. To design an algorithm for such
conversions we need to understand clearly what the base change entails.

Because initially we probably have no firm ideas on the mechanism for base
conversion we will begin with some groundwork. We can start by trying to
come to terms with exactly what is a decimal number and an octal number. For
this exploration we can look at some specific examples.

The decimal (i.e. base 10) number 275 by its representation, is seen to consist
of:

The decimal system uses the ten digits 0.1.2.3..... 9 to represent numbers. The
actual position of each digit in a number determines its value. Similar
conventions apply for the octal (or base 8) number system. The octal system
uses only the eight digits 0.1.2.3..... 7 to represent numbers. In the octal system
the position of each digit determines its value in a similar (but different) way to
the decimal system. Taking a few steps ahead for the purposes of illustration it
can be shown that the octal representation of the decimal number 275 is 423.
The octal number consists of:

We can now more explicitly identify the base conversion mechanism


In changing a decimal number to its octal representation we start by dividing
the decimal number by 8. The remainder of this operation is the least
significant digit (i.e. 5) of the octal representation. The quotient (i.e. 11) is then
taken and divided by 8. The remainder of this operation is the second least
significant digit of the octal representation. The process of dividing the quotient
and using the remainder as the next least significant digit of the octal
representation continues until a zero quotient is encountered. This situation
marks the fact that there are no higher order digits in the octal representation
(in the example above a zero quotient after 3 divisions by 8 indicates that there
are no five-hundred-and-twelves in our original number 93-this is clearly true).

We now have the essentials for implementing our base conversion algorithm. It
involves an iterative process where successive octal digits are derived as
remainders from a sequence of quotients, each of which is in turn derived from
its predecessor by division by 8. More specifically starting with q := 93 we
have

To get both the quotient q and the remainder r at each step we will need to
employ both the integer division and remainder functions. For the general ith
step we will need

As we have already established, the iterative process needs to be terminated as


soon as a zero quotient is encountered. The initial value of the quotient q
should be the original decimal value of the number to be converted to octal.
The essential steps in the algorithm are:

1. Initialize the quotient q to the decimal number to be converted.


2. Derive the octal digits iteratively using a succession of remainder and
quotient computations on consecutive quotient values. Terminate the process
when a zero quotient is encountered.
The algorithm should be implemented so that it will also handle conversions
other than decimal to octal (e.g. decimal to binary, decimal to ternary). To
allow this the inputs to the algorithm should be the new base required and the
decimal number to be converted. For convenience of output the digits of the
new representation should be stored in an array and written out only after the
loop has terminated. Incorporating these refinements we get the following
detailed algorithm.

Algorithm description

1 Establish the newbase and initialize the quotient q to the decimal number to
be converted.

2. Set the new digit count ndigit to zero.

3. Repeatedly

(a) compute the next most significant digit (i.e. octal) from the current
quotient q as the remainder r after division by newbase.

(b) convert r to appropriate ascii value.

(c) increment new digit count ndigit and storer in output array newrep,

(d) compute the next quotient q from its predecessor using integer division
by newbase until the quotient is zero.

Applications
Interpretation of stored computer data and instructions.

1.8 Algorithm Development

1.8.1 Algorithm Description

An algorithm is a set of instructions that tells a computer exactly what to do to


solve a problem or perform a task. Imagine you’re teaching someone how to tie
their shoes. You would give them a series of steps to follow, and that’s
essentially what an algorithm does for a computer.

Characteristics of a Good Algorithm

● Correctness: The algorithm must solve the problem correctly every


time. For example, if you’re writing an algorithm to sort numbers in
order, it should always put them in the right sequence.
● Efficiency: The algorithm should do its job quickly and not waste
resources like memory or processing power. A good algorithm is like a
shortcut that gets you to the same destination faster and with less effort.
● Clarity: The steps in the algorithm should be simple and easy to
understand. If you can explain your algorithm to someone who isn’t a
programmer, that’s a good sign that it’s clear.

● Finiteness: The algorithm should always finish after a certain number of


steps. It shouldn’t go on forever without reaching a conclusion.

Steps in Algorithm Development

1. Problem Understanding:
○ Before you can write an algorithm, you need to fully understand
the problem you’re trying to solve. Ask yourself, "What exactly
needs to be done?" For example, if the task is to find the largest
number in a list, you need to understand what the input will look
like (a list of numbers) and what the output should be (the largest
number in that list).
2. Algorithm Design:
○ Once you understand the problem, you can start thinking about
how to solve it. This is where you outline the steps needed to
reach the solution. For example, if you’re finding the largest
number, your steps might include:
1. Start with the first number in the list.
2. Compare it with the next number.
3. If the next number is larger, remember it as the largest so
far.
4. Continue until you’ve checked all the numbers.
5. The largest number you’ve remembered is your answer.
3. Pseudocode and Flowcharting:
○ Before writing actual code, it’s helpful to write pseudocode,
which is like writing down the algorithm in plain language. It’s
not real code, but it helps you plan out what the code will do.
○ You can also draw a flowchart to visualize the steps. Flowcharts
use different shapes to represent different actions, like decision
points or processes. It’s like a map that shows how your
algorithm will work.
4. Implementation:
○ Now, you translate your algorithm into actual code using a
programming language like C. This is where you take your
pseudocode and turn it into commands that the computer can
execute. For example, if your algorithm is finding the largest
number, you’ll write code that performs the comparisons and
keeps track of the largest number.
5. Testing and Debugging:
○ After writing the code, you need to test it to make sure it works as
expected. Try running it with different inputs to see if it always
gives the correct output. If something goes wrong, this is where
debugging comes in—you’ll need to find and fix the errors in
your code.
6. Optimization:

○ Once your algorithm is working, you can look for ways to make
it better. Maybe you can write it in a way that makes it run faster
or use less memory. This step is about refining your algorithm to
make it as efficient as possible.

Example of an Algorithm

Problem: Let’s say you want to find the largest number out of three given
numbers.

Algorithm:

1. Start.

2. Take three numbers: a, b, and c.

3. Compare a with b and c.

○ If a is larger than both, a is the largest.


○ If not, move to the next step.

4. Compare b with c.

○ If b is larger than c, b is the largest.


○ Otherwise, c is the largest.
5. Output the largest number.

6. End.
This example shows how an algorithm breaks down the task of finding the
largest number into simple, logical steps that a computer can follow.

By following these steps in algorithm development, you can create a clear and
effective solution to any problem you want to solve with a computer program.

1.9 Design consideration


1.9.1 Applications

When you're developing software, especially in C, it's important to think about


how your program is designed. Good design ensures that your software not
only works correctly but is also easy to maintain, efficient, and scalable. Here
are some key design considerations to keep in mind, along with their
applications.

1. Modularity

Modularity means breaking down a program into smaller, manageable parts


called modules or functions. Each module performs a specific task. This makes
your code easier to understand, debug, and reuse.

Example: Imagine you’re writing a program to manage a library. You could


create different modules like:

● A module to add new books.


● A module to search for books.

● A module to issue books to members.

By separating these tasks into different modules, you can work on them
independently. If there’s an issue with searching for books, you only need to
check the search module, not the entire program.

Applications:

● Easier Debugging: If something goes wrong, you can focus on a


specific module rather than sifting through the entire codebase.
● Code Reusability: Modules can be reused in other programs. For
example, a module to search for items can be reused in another
application like a grocery inventory system.

● Team Collaboration: In large projects, different team members can


work on different modules simultaneously without interfering with each
other’s work.
2.Scalability

Scalability refers to how well your software can handle growth. As more data
or users are added, a scalable program continues to perform well without
requiring major changes.

Example: Suppose you’ve written a program to manage a small shop’s


inventory. Initially, it handles 100 items, but what if the shop expands and starts
stocking 10,000 items? A scalable design ensures your program can handle this
increase smoothly.

Applications:

● Efficient Data Handling: A scalable program uses data structures that


can grow with the data. For example, using dynamic arrays that can
resize themselves as more data is added.
● Handling More Users: In web applications, scalability ensures that as
more users log in, the application continues to perform well without
slowing down.

● Future-Proofing: Designing for scalability means your program can


adapt to future needs without requiring a complete rewrite.

3.Memory Management

Memory Management is crucial in C because you have direct control over


how memory is allocated and freed. Proper memory management prevents
issues like memory leaks, where memory is used up and not released,
eventually causing the program to run out of memory and crash.

Example: When you create a program that needs to store data temporarily, you
might allocate memory dynamically (e.g., using malloc() in C). After the data
is no longer needed, you must release that memory using free() to avoid
memory leaks.

Applications:

● Efficient Use of Resources: Proper memory management ensures your


program runs efficiently, even on systems with limited memory.
● Preventing Crashes: By freeing unused memory, you reduce the risk of
your program crashing due to running out of memory.

● Better Performance: Programs that manage memory well are faster


because they make better use of available resources.
4.Error Handling

Error Handling involves writing code that anticipates and deals with potential
errors that could occur during the execution of a program. Good error handling
makes your program more reliable and user-friendly.

Example: Imagine you’re writing a program that reads a file. What if the file
doesn’t exist? Instead of crashing, the program should detect this error and
inform the user, maybe by displaying a message like "File not found."

Applications:

● Graceful Recovery: When something goes wrong, your program


should handle the situation without crashing. For example, if there’s an
error while connecting to a database, your program might try
reconnecting or provide an alternative option.
● User Feedback: Error messages guide users on what went wrong and
how they can fix it, making your software more user-friendly.

● Robust Software: By anticipating errors and handling them properly,


your program becomes more reliable and less likely to fail unexpectedly.

Applications of C Programming

C is a powerful language that’s widely used in various fields due to its


efficiency and control over hardware. Here’s how C is applied in different
areas:

● System Software: C is used to develop operating systems, compilers,


and other system-level software. Its ability to interact directly with
hardware makes it ideal for these tasks. Example: The UNIX operating
system, which is foundational to many modern operating systems, was
originally written in C.
● Embedded Systems: C is often used to program microcontrollers and
other embedded devices because it allows precise control over the
hardware. Example: C is used in the development of firmware for
devices like washing machines, microwave ovens, and even medical
devices.
● Game Development: C’s performance makes it suitable for developing
game engines where speed is critical. Example: Many early game
engines were written in C, and even today, parts of game engines are
developed in C for optimized performance.
● High-Performance Computing: Applications that require intensive
computations, such as scientific simulations, often use C for its speed.
Example: C is used in simulations for weather forecasting, physics
research, and other computationally heavy tasks.

● Network Programming: C is used to develop network protocols and


applications, where direct access to system resources is necessary.
Example: Many network tools and utilities, like those used to manage
internet traffic, are written in C.

By considering these design principles, you can develop robust, efficient, and
scalable software in C that not only meets current needs but can also adapt to
future challenges.
Unit – II: C PROGRAMMING FUNDAMENTALS

2.1 Data types


• Data types are the keywords, which are used for assigning a type to a variable.
• Allows the programmers to select the appropriate data type as per the need of the
application.
• Data types are used to specify the types of data that are going to process within the
program.
• C supports different types of data types. They are,

1. Primary Data Type


2. User Defined Data Type
3. Derived Data Type
4. Empty Data Type
2.1.1 Primary Data Type
The primary data types are divided into the following,
1. Integer Data Type
• Integer data type allows a variable to store numeric values.
• The keyword is used to define integer data type is “int”.
• The storage size of integer data type is 2 or 4 or 8 byte.
• Syntax
Data_type variable name;
• Eg., int a;
• Architecture-Specific Details: The internal representation of integers (e.g., how bits are used
for signed vs. unsigned integers) can depend on the machine's architecture. For example, a
32-bit machine will have different ranges and capacities for these integers compared to a
64-bit machine.

Signed Integer Unsigned Integer


 It occupies 2 bytes in memory.  It also occupies 2 bytes in
 It ranges from -32768 to 32767. memory.
 Control string used is %d or %L.  It ranges from 0 to 65535.
 Eg: int a=2;  Control string used is %u.
long int b=2;  Eg: unsigned long b;
unsigned short int c;

2. Character Data Type


• Character data type allows a variable to store only one character.
• Storage size of character data type is 1 byte. We can store only one character using
character data type.
The keyword is used to define character data type is “char”.
• Eg: char a;

Signed Char Unsigned Char


 It occupies 1 byte in  It occupies 1 byte in memory.
memory.  It ranges from 0 to 255.
 It ranges from -128 to 127.  Control String used is %c.
 Control String used is %c.

3. Floating Point Data Type


Floating point data type consists of 2 types. They are,
 Float
 double
float
• Float data type allows a variable to store decimal values.
• Storage size of float data type is 4 byte.
• These are numbers which contain fractional parts, both positive and negative.
• The keyword used to define float data type is, float.
• It ranges from (3.42-38) to (3.42+38).
• Control String used is %f.
• Eg: float a;
double
• Double data type is also same as float data type which allows up-to 10 digits after
decimal.
• The keyword used to define double variables is double.
• The range for double data type is from 1E–37 to 1E+37.
• It also occupies 2 bytes in memory.
• Eg: double a;

2.1.2 User Defined Data Type


• The keyword used to define user defined data type is “typedef”.
• It allows users to define the identifier which would represent an existing data type.
• The main advantage is it increases the program’s readability.
2.1.3 Derived Data Type
• Derived data types are created by using predefined data types (int, char, float,
double) only.
• Array, pointer, structure and union are called as derived data types in C language.
2.1.4 Empty Data Type
• Void is an empty data type that has no value.
• This can be used in functions and pointers.
Example Program
#include<stdio.h>
main() {
int sum;
float
money;char
letter;
double pi;
sum = 10; /* assign integer value */
money = 2.21; /* assign float value */
letter = 'A'; /* assign character value */
pi = 2.01E6; /* assign a double value */
printf("value of sum = %d\n", sum );
printf("value of money = %f\n", money );
printf("value of letter = %c\n", letter );
printf("value of pi = %e\n", pi );
}
Output
value of sum = 10
value of money = 2.210000
value of letter = A
value of pi = 2.010000e+06

2.2 Preprocessor Section


• It is used to link system library files for defining the macros and for defining the
conditional inclusion
• C program depends upon some header file for function definition that is used in
program.
• Header file is extended with ‘.h’.
• This file should be included using #.
• Eg., #include<stdio.h>, #define A 10, #if def, #endif…
2.2.1 Global Declaration Section
• This section declares some variables that are used in more than one functionthroughout
the program.
• These variables must be declared outside of the main function. So these variables are
known as global variables.
2.2.2 Main Function
• Every C program must contain main function.
• Without main function that is not a C program.
• After main function empty parenthesis are necessary.
• Main () is the starting point of every ‘C’ program.
• The execution always begin with the main function
• The execution starts with opening brace ‘{’ & closing brace ‘}’
• In between these braces the programmer should write executable and declaration part.
o Executable part - It contains a set of statements or a single statement. These
statements are enclosed between the braces.
o Declaration part - It declares the entire variables that are used in executablepart.
Variable initialization is done in declaration section.
Sub Program Section (Or) User Defined Function
• These section defined by user are called user defined functions.
• These functions are defined after the main function (Or) before the main function.
2.2.3 Programming Rules
While writing a program, a programmer should follow the following rules.
• All statements should be written in lowercase letters.
• Uppercase letters are only used for symbolic constants.
• Blank space may be inserted between the words. But blank space is not used while
declaring a variable, keyword, constant and function.
• The programmers can write the statement anywhere between the two braces.
• We can write one or more statements in a same line by separating each statement in asame
line with semicolon (:).
• The opening and closing braces should be balanced.
2.2.4 Preprocessor Directives

The following table lists down all the important preprocessor directives

Directive Description

# define Substitutes a preprocessor macro.

#include Inserts a particular header from another file.

#undef Un defines a preprocessor macro.

#ifdef Returns true if this macro is defined.

#ifndef Returns true if this macro is not defined.

#if Tests if a compile time condition is true.

#else The alternative for #if.

#elif #else and #if in one statement.

#endif Ends preprocessor conditional.


#error Prints error message on stderr.

Issues special commands to the compiler, using a standardized


#pragma
method.

2.2.5 Preprocessor Examples

1. #define MAX_ARRAY_LENGTH 20
2. #include <stdio.h>
3. #include "myheader.h"
4. #undef FILE_SIZE
5. #define FILE_SIZE 42
6. #ifndef MESSAGE
7. #define MESSAGE "You wish!"
8. #endif
9. #ifdef DEBUG
/* Your debugging statements here */
10. #endif

2.3 Constants and Variables


2.3.1 Constants
• Constants are the entity whose values can't be changed during the execution of a
program.
• Eg: x=3, Here 3 is a constant.
• Constants are classified into two types. They are,
 Numerical Constant
 Character Constant
2.3.1.1 Numerical Constant

It is divided into two types,


1. Integer Constant
2. Real Constant
Integer Constant
• Integer constants are the numeric constants formed with the sequence of digits withoutany
fractional part or exponential part.
• There are three types of integer constants in C language: decimal constant (base 10),octal
constant (base 8) and hexadecimal constant (base 16).
• Decimal Digits: 0 1 2 3 4 5 6 7 8 9
• Octal Digits: 0 1 2 3 4 5 6 7
• Hexadecimal Digits: 0 1 2 3 4 5 6 7 8 9 A B C D E F.
Example
• Decimal Constants: 0, ‐9, 22, etc.
• Octal Constants: 021, 077, 033, etc.
• Hexadecimal Constants: 0x7f, 0x2a, 0x521, etc.
Floating Point Constant
• Floating point constants are the numeric constant that has either fractional part or
exponent part.

Example
‐2.0
0.0000234
‐0.22E‐5
2.3.1.2 Character Constant
• Character constants are the constant which use single quotation around characters.
2. Single Character Constant
• It contains a single character enclosed within a pair of single inverted commas both
pointing to the left.
• Eg: ‘s’, ‘M’, ‘3’, etc.
3. String Constant
• A string constant is a sequence of characters enclosed in double quotes, thecharacters
may be letters, numbers, special characters and blank spaces, etc.
• Eg: “Hello”, ”23”, “a”, etc.
Rules for Defining Constants
• It must have at least one digit.
• It can be either positive or negative.
• No commas or blank spaces are allowed.
• Decimal points are not allowed in integer constants, but allowed in real constants.

2.3.2 Variable
• Variables are memory location in computer's memory to store data.
• To indicate the memory location, each variable should be given a unique name called
identifier.
• A variable is an identifier that is used to represent some specified type of information
within a designated portion of the program.
Rules for naming the variables
• Variable name can be composed of letters (both uppercase and lowercase letters),
digits and underscore '_' only.
• The first letter of a variable should be either a letter or an underscore.
• No commas or blank spaces are allowed within a variable name.
• There is no rule for the length of length of a variable. However, the first 31 charactersof a
variable are discriminated by the compiler.

Variable Declaration
• Declaration of variable can be done in the declaration part of the program.
• The variables must be declared before they are used in the program.
Syntax
Data_type variable name;
Example
int a; char
m;float s;
Initializing Variables
• Value can be initialized in the valuable name using an assignment operator = .
Syntax
Data_type variable name = value; (or) variable name=value;
Example
Eg: int x=2; x=2;
Scope of the Variable
• Scope of the variable implies the availability of variables within the program.
• Variables have 2 types of scope.
o Local variables
o Global variables
Local Variables
• Local variables are defined inside a main function block (Or) inside a compound
statement of a function subprogram are called local variables.
Example
function()
{
int i, j;
}
2.3.2.1 Global / External Variables
• The variables that are declared before the function main() are called the global /
external variables.
Eg:
int a, b; // here a,ball is a global variables.
main()
{
……
function()
}
function()
{
…….}

2.3.2.2 Enumerated constants


 Enumerated data types are a special form of integers, with the following constraints:
 Only certain pre-determined values are allowed.
 Each valid value is assigned a name, which is then normally used instead of
integer values when working with this data type.
 Enumerated types, variables, and typedefs, operate similarly to structs:
enum suits { CLUBS, HEARTS, SPADES, DIAMONDS, NOTRUMP } trump;
enum suits ew_bid, ns_bid;
typedef enum Direction{ NORTH, SOUTH, EAST, WEST } Direction;Direction
nextMove = NORTH;
 Values may be assigned to specific enum value names.
o Any names without assigned values will get one higher than the previous
entry.
o If the first name does not have an assigned value, it gets the value of zero.
o It is even legal to assign the same value to more than one name.
o Example:
o enum Errors{ NONE=0, // Redundant. The first one would be zero anyway
 MINOR1=100, MINOR2, MINOR3, // 100, 101, and 102
MAJOR1=1000, MAJOR2, DIVIDE_BY_ZERO=1000 }; // 1000, 1001, and
1000 again.
 Because enumerated data types are integers, they can be used anywhere integers are
allowed. One of the best places in in switch statements:

switch( nextMove )

case NORTH:
y++;
break;
// etc.
 The compiler will allow the use of ordinary integers with enumerated variables, e.g.
trump = 2; , but it is bad practice.
2.3.2.3 Keywords
• Keywords are the reserved words used by the compiler that have standard and fixed(or)
predefined meaning in ‘C’ Language.
• Those words cannot be changed by the user and they are the basic building blocks for
program statements.
• There are 32 keywords in C language. Some of the keywords are,
Keywords in C Language
auto double int struct do
break else Long switch default
case enum register typedef const
char extern return union if
continue for Signed, void goto
unsigned
float static sizeof short while

• All the keywords must be written in lower case.

2.4 Pre-defined Libraries


1. stdio.h

 Purpose: Provides input/output functions for reading from and writing to streams such as
the console and files.

#include <stdio.h>

int main() {

char name[50];

printf("Enter your name: ");


scanf("%s", name);
printf("Hello, %s!\n", name);

return 0;
}

 printf: Outputs formatted data to the console.


 scanf: Reads formatted data from the console.
2. stdlib.h

 Purpose: Offers general utility functions including memory allocation, conversion


functions, and functions for controlling program execution.

#include <stdlib.h>
int main() {
int *arr;
int size = 5;

arr = (int *)malloc(size * sizeof(int));


if (arr == NULL) {
printf("Memory allocation failed.\n");
return 1;
}

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


arr[i] = i * 2;
}
for (int i = 0; i < size; ++i) {
printf("%d ", arr[i]);
}
printf("\n");

free(arr);

return 0;
}
 malloc: Allocates memory dynamically.
 free: Releases dynamically allocated memory.
 srand and rand: Seed and generate pseudo-random numbers.
3. math.h

 Purpose: Contains mathematical functions and constants.

1) #include <stdio.h>
#include <math.h>
int main() {

double x = 2.0;
double result;

result = sqrt(x); // Square root function

printf("Square root of %lf is %lf\n", x, result);

return 0;
}

2) #include <stdio.h>
#include <math.h>
int main() {
double num = 16.0;
double sqrt_result = sqrt(num); // Square root
double pow_result = pow(2, 3); // Power function (2 raised to the power of 3)
double ceil_result = ceil(4.3); // Ceiling function (smallest integer not less than 4.3)
printf("Square root of %.1f = %.2f\n", num, sqrt_result);
printf("2^3 = %.1f\n", pow_result);
printf("Ceiling of 4.3 = %.1f\n", ceil_result);
return 0;
}

 sqrt: Calculates the square root.


 pow: Computes the power of a number.
 ceil: Rounds up to the nearest integer.
4. string.h

Purpose: Provides functions for manipulating arrays of characters (strings) and memory
manipulation functions.

#include <stdio.h>
#include <string.h>
int main() {
char str1[20] = "Hello";
char str2[20] = "World";
char str3[20];
// Copying str1 to str3
strcpy(str3, str1);
printf("str3 after strcpy: %s\n", str3);

// Concatenating str2 to str3


strcat(str3, str2);
printf("str3 after strcat: %s\n", str3);
// Length of str3
printf("Length of str3: %lu\n", strlen(str3));
return 0;
}

 strcpy: Copies a string.


 strcat: Concatenates strings.
 strlen: Calculates the length of a string.

5. ctype.h (Character Handling)

Purpose: Defines functions for character classification and transformation.

#include <stdio.h>
#include <ctype.h>

int main() {
char ch = 'A';

if (isalpha(ch)) {
printf("%c is an alphabet character.\n", ch);
}

if (isdigit(ch)) {
printf("%c is a digit.\n", ch);
}

if (isupper(ch)) {
printf("%c is an uppercase letter.\n", ch);
}
if (islower(ch)) {
printf("%c is a lowercase letter.\n", ch);
}
return 0;
}

 isalpha: Checks if a character is an alphabet.


 isdigit: Checks if a character is a digit.
 isupper and islower: Checks if a character is uppercase or lowercase, respectively.

6.time.h (Date and Time Functions)

Purpose: Provides functions for manipulating date and time.

#include <stdio.h>
#include <time.h>

int main() {
time_t current_time;
struct tm *local_time;
char time_str[100];

// Get current time


time(&current_time);

// Convert to local time format


local_time = localtime(&current_time);

// Format time as a string


strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", local_time);

printf("Current time: %s\n", time_str);


return 0;
}
 time: Retrieves the current calendar time.
 localtime: Converts a time_t object into a structure representing local time.
 strftime: Formats time as a string according to a specified format.

2.5 Storage Classes


 A storage class defines the scope (visibility) and life time of variables and/or functions
within a C program.
 There are following storage classes which can be used in a C program.
 auto
 register
 static
 extern

2.5.1 auto - Storage Class


• auto is the default storage class for all local variables.
{
int Count;
auto int Month;
}

• The example above defines two variables with the same storage class. auto can only be
used within functions, i.e. local variables.
2.5.2 register - Storage Class
 register is used to define local variables that should be stored in a register instead of RAM.
 This means that the variable has a maximum size equal to the register size (usually one
word) and can’t have the unary '&' operator applied to it (as it does not have a memory
location).
{
register int Miles;
}
 Register should only be used for variables that require quick access - such as counters. It
should also be noted that defining 'register' goes not mean that the variable will be stored in
a register. It means that it MIGHT be stored in a register - depending on hardware and
implementation restrictions.
2.5.3 static - Storage Class
 static is the default storage class for global variables. The two variables below (count and
road) both have a static storage class.
static int Count; int Road;
{
printf("%d\n", Road);
}
 static variables can be 'seen' within all functions in this source file. At link time, the static
variables defined here will not be seen by the object modules that are brought in.
 static can also be defined within a function. If this is done the variable is initalized at run
time but is not reinitalized when the function is called. This inside a function static variable
retains its value during vairous calls.
void func(void);
static count=10; /* Global variable - static is the default */
main(){
while (count--){
func();} }
void func( void ){
static i = 5;
i++;
printf("i is %d and count is %d\n", i, count);
}
This will produce following result
i is 6 and count is 9
i is 7 and count is 8
i is 8 and count is 7
i is 9 and count is 6
i is 10 and count is 5
i is 11 and count is 4
i is 12 and count is 3
i is 13 and count is 2
i is 14 and count is 1
i is 15 and count is 0
2.5.4 Extern - Storage Class
 extern is used to give a reference of a global variable that is visible to ALL the program
files.
 When you use 'extern' the variable cannot be initialized as all it does is point the variable
name at a storage location that has been previously defined.
 When you have multiple files and you define a global variable or function which will be
used in other files also, then extern will be used in another file to give reference of defined
variable or function.
 File 1: main.c

int count=5;
main()
{
write_extern();
}
File 2: write.c
void write_extern(void);
extern int count;
void write_extern(void)
{
printf("count is %i\n", count); }
• Here extern keyword is being used to declare count in another file.

2.6 Expressions
 An expression represents data item such as variables, constants and are interconnected with
operators as per the syntax of the language.
 Syntax: variable=expression;
 Eg: y=(a/b)+c; z=(a*b)-d;
Type Conversion
• It is a process of converting the type of an expression from one type to another type.
• Eg: x = (int)10.45
Example Program
#include<stdio.h>
#include<conio.h>
void main( )
{
int c;
clrscr( );
c=(int)10.45;
printf("\n Output is:%d",c);
getch( );
}
Output
Output is: 10

2.6.1 Types of Expressions

1. Primary Expressions:

 Identifiers: Variable names like x, count, etc.


 Constants: Literal values like 10, 3.14, 'A', "Hello".
 String Literals: Enclosed in double quotes ("Hello").
 Function Calls: Invocations of functions like printf("Hello");.

2. Arithmetic Expressions:

 Operators: Arithmetic operators such as +, -, *, /, %.


 Examples:

int sum = a + b;
double area = radius * radius * 3.14159;
int quotient = x / y;
3. Relational Expressions:

 Operators: Comparison operators such as ==, !=, <, >, <=, >=.
 Examples:

if (x == y) {
printf("x is equal to y\n");
}
if (a < b) {
printf("a is less than b\n");
}

4. Logical Expressions:

 Operators: Logical operators such as && (AND), || (OR), ! (NOT).


 Examples:

if (x > 0 && y < 10) {


printf("x is positive and y is less than 10\n");
}
if (!(a == b)) {
printf("a is not equal to b\n");
}

5. Conditional Expressions:

 Ternary Operator: condition ? expr1 : expr2.


 Example:

int max = (a > b) ? a : b;

6. Bitwise Expressions:

 Operators: Bitwise operators such as & (AND), | (OR), ^ (XOR), ~ (NOT), << (left
shift), >> (right shift).
 Examples:

int result = x & y;


int flipped = ~x;

7. Assignment Expressions:

 Operators: Assignment operator = and compound assignment operators like +=, -=,
*=, /=, etc.
 Examples:

x = 10;
y += 5;
2.6.2 Evaluation of Expressions

 Order of Evaluation: C follows rules for evaluating expressions based on operator


precedence and associativity.
 Side Effects: Expressions can have side effects, such as modifying variables or calling
functions.

Examples of Complex Expressions,

int a = 10, b = 5, c = 3;
int result = (a + b) * c - (a / b);

In the above example:

 (a + b) calculates the sum of a and b.


 * c multiplies the result by c.
 a / b calculates the quotient of a divided by b.
 The overall expression (a + b) * c - (a / b) computes a final result based on arithmetic
operations.

2.7 Precedence of operators

 If more than one operators are involved in an expression, C language has a


predefined rule of priority for the operators. This rule of priority of operators is
called operator precedence.
 In C, precedence
 arithmetic operators( *, %, /, +, -)
 relational operators(==, !=, >, <, >=, <=)
 logical operators(&&, || and !).
2.7.1 Example of precedence
(1 > 2 + 3 && 4)
This expression is equivalent to:
((1 > (2 + 3)) && 4)
i. e, (2 + 3) executes first resulting into 5
then, first part of the expression (1 > 5) executes resulting into 0 (false)then,
(0 && 4) executes resulting into 0 (false)

Output
0

Associativity of operators

 If two operators of same precedence (priority) is present in an expression,


Associativity of operators indicate the order in which they execute.
Example of associativity
1 == 2 != 3
 Here, operators == and != have same precedence.
 The associativity of both == and != is left to right, i.e, the expression on the left is
executed first and moves towards the right.
 Thus, the expression above is equivalent to :
((1 == 2) != 3)
i.e, (1 == 2) executes first resulting into 0 (false)then,
(0 != 3) executes resulting into 1 (true)
The table below shows all the operators in C with precedence and associativity.

Operator Meaning of operator Associativity


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

2.7.2 Operators
• An operator is a symbol that specifies an operation to be performed on the operands.
Operand
• It is a data item on which operators perform operation.
• Eg: a+b
Here, a, bOperands + Operator

Various Types of Operator


1. Arithmetic Operators
2. Relational Operators
3. Logical Operators
4. Assignment Operators
5. Increment and Decrement Operators
6. Conditional Operators
7. Bitwise Operators
8. Special Operators
Arithmetic Operators
• C allows basic arithmetic operations like addition, subtraction, multiplication and
division.
• Arithmetic Operators are,
o + , - , * , / , %.
Arithmetic operators are classified as
• Unary Arithmetic: It requires only one operand.
o Eg: +x, -y
• Binary Arithmetic: It requires two operands.
• Eg: a+b, a%b, etc.
• Integer Arithmetic: It requires both operands are integer values for arithmetic
operation.
Eg: a+b a=5, b=2
a+b = 5+2=7

• Floating Point Arithmetic: It requires both operands are float type for arithmetic
operation.
Eg: a+b, a=6.5 b=3.5
a+b, 6.5+3.5 = 10

Sample Program 1:
#include<stdio.h> // Header File
#include<conio.h>
int a=5, b=10; //Global Declaration
void main( ) /* main is the starting of every c program */
{
int c; //Local Declaration
clrscr( );
printf(“ \n The sum of the two values:”);c
= a+b;
printf(“%d”,c);
getch( );
}
Output: The sum of the two values: 15

Sample Program 2:
#include<stdio.h>
#include<conio.h>
void main( )
{
int a=10, b=4, c;
float d=3, e;
clrscr( );
c = a/b;
printf(" \n Value of a/b is:%d",c);
e = a/d;
printf("\n Value of a/d is:%f",e);
getch( );
}
Output
Value of a/b is: 2
Value of a/d is: 3.333333
Relational Operator
• Relational operators are used to compare two or more operands. Operands may be
variables, constants or expression.
• If the relation is true, it returns value 1 and if the relation is false, it returns value 0.
o Relational operators are, <, >, <=, >=, ==, !=
Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int a,b;
clrscr()
;
printf(“\n Enter the Values of a and b:”);
scanf(“%d%d”,&a,&b);
printf(“\n The Result is”);
printf(“%d”, a<b);
printf(“%d”, a>b);
printf(“%d”, a<=b);
printf(“%d”, a>=b);
printf(“%d”, a==b);
printf(“%d”, a!=b);
getch();
}
Output
Enter the Values of a and b: 4 2
The Result is
0
1
0
1
0
1
Logical Operators
 Logical operators are used to combine the results of two or more conditions.

Operator Meaning Example


If c=5 and d=2 then,((c==5) &&
&& Logical AND
(d>5)) Returns false.
|| Logical OR If c=5 and d=2
Then, ((c==5) || (d>5)) returns true.
! Logical NOT If c=5 then, !(c==5) returns false.

Logical AND – This operator is used where a set of statements are to be executed, if two ormore
expressions are true.
Logical OR – This is used, if either of them is true from two or more condition, then set of
statements are executed.
Logical NOT – This operator reverses the value of the expression it operates on.

Sample Program
#include<stdio.h>

#include<conio.h>
void main()
{
int
c1.c2,c3;
clrscr();
printf(“Enter the values c1, c2, c3:”);
scanf(“%d%d%d”, &c1,&c2&c3);
if((c1<c2)&&(c1<c3))
printf(“c1 is less than c2 and c3”);if(!(c1<c2))
printf(“\n c1 is greater than c2”);
if((c1<c2)||((c1<c3))
printf(“c1 is less than c2 or c3 both”);getch();
}

Output
Enter the values c1, c2, c3: 9 6 3
C1 is greater than c2
Assignment Operator
• Assignment operators are used to assign a value or an expression or a value of a
variable to another variable.
• Syntax: variable=expression (or) value ;
• Example : x=10; x=a+b; x=y;
• Two types of assignment operator are,
 Compound Assignment
 Nested Assignment (or) Multiple Assignment

Compound Assignment

 Assign a value to a variable in order to assign a new value to a variable after


performing a specified operation.

Operator Example Same As


= a=b a=b
+= a+=b a=a+b
-= a-=b a=a-b
*= a*=b a=a*b
/= a/=b a=a/b
%= a%=b a=a%b

Multiple Assignments
• It is used to assign a single value or an expression to multiple variables.
• Syntax: var1=var2=…………..varn=single variable or expression;

Sample Program

#include<stdio.h>
#include<conio.h>
int b=10;
void main( )
{
int a=3, b=5;
clrscr( );
a+=b; // a= a+b
printf(" \n The sum of the two values:%d",a);
getch( );
}

Output:
The sum of the two values: 8
Increment and Decrement Operators
• These are the increment (++) and decrement (--) operators. Both of these are unary
operators.
• The ++ adds 1 to the operand and – subtracts 1 from the operand.
o ++x - Pre Increment (First increment and then return the value)
o --x - Pre Decrement (First decrement and then return the value)
o x++ - Post Increment (First return the value and then increment)
o x-- - Post Decrement (First return the value and then decrement)
Example
Let a=5 and b=10
a++; //a becomes 6
a‐‐; //a becomes 5
++a; //a becomes 6
‐‐a; //a becomes 5
Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int a=5;
clrscr();
printf(“Post Increment Value a++=%d\n”,a++);
printf(“Pre Increment Value ++a=%d\n”,++a);
printf(“Pre Decrement Value -- a=%d\n”,--a);
printf(“Post Decrement Value a--=%d\n”,a--);
getch();
}
Output:
Post Increment Value a++=5
Pre Increment Value ++a=7
Pre Decrement Value --a=6
Post Decrement Value a--=6

Conditional Operator (Or) Ternary Operator


• Conditional operator itself checks the condition and executes the statement dependingon
the condition.
• Syntax: condition?exp1:exp2
Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int a=5, b=2, big;
clrscr();
big=(a>b)?a:b;
printf(“Largest number is %d”,big);
getch();
}
Output: Largest number is 5
Bitwise Operators
• It is used to manipulate the data at bit level. It operates on integers only.

Operator Meaning
& Bitwise AND
| Bitwise OR
^ Bitwise XOR
<< Shift Left
>> Shift Right
~ One’s Complement

Operations of above operators are,


a b a|b a&b a^b ~a
0 0 0 0 0 1
0 1 1 0 1 1
1 0 1 0 1 0
1 1 1 1 0 0

Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int a, b, c;
clrscr();
a=12;
b=25;
c=a&b;
printf(“Bitwise AND=%d”,c);
c=a/b;
printf(“Bitwise OR=%d”,c);
c=a^b;
printf(“Bitwise XOR=%d”,c);
c=~a;
printf(“One’s Complement=%d”,c);
getch();
}
Output:
Bitwise AND=8
Bitwise OR=29
Bitwise XOR=21
One’s Complement= 220
Special Operators
It consists of the following,

Operators Meaning
, Comma Operator
sizeof() Size of Operator
& and * Address Operator / Indirection Operator
. and  Member Selection Operator
Comma Operator
• It is used to separate the statement elements such as variables, constants or expression,etc.
sizeof() Operator
• It is a unary operator which is used in finding the size of data type, constant, arrays,
structure etc.
Address Operator / Indirection Operator
• Address Operator (&) - This symbol is used to specify the address of the variable.
• Indirection Operator (*) - It is used to specify the value of the variable.

Member Selection Operator


• These symbols are used to access the elements from a structure.
Sample Program
#include<stdio.h>
#include<conio.h>
void main( )
{
int c;
clrscr( );
printf(" \n Size of Int is:%d",sizeof(c));
getch( );
}
Output
Size of Int is: 2

2.7.3 Associability
"associability" generally refers to the ability to associate or connect with others, often used
in interpersonal or social contexts rather than technical or mathematical ones.

2.8 Managing Input / Output Functions in C


• In C Language two types of Input/output statements are available and all input and output
operations are carried out through function calls.
o Unformatted Input / Output Statements
o Formatted Input / Output Statements

Unformatted Input / Output Statements


• These statements are used to input/output a single/group of characters from/to the
input/output devices.
Unformatted Input Statements
getchar() function
• A single character can be given to the computer using ”C” input library function
getchar().
• It reads a single character from a standard input device.
• Syntax: char variable=getchar();
getc() function
• It is used to accept a single character from the standard input to character variable.
• Syntax: character variable=getc();
gets() function
• It is used to read the string from the standard input device.
• Syntax: gets(char type of array variable);
Unformatted Output Statements
putchar() function
• It is used to display one character at a time on the standard output device.
• Syntax: putchar(character variable);
putc() function
• It is used to display a single character in a character variable to standard output device.
• Syntax: putc(character variable);
puts() function
• It is used to display / write the string to the standard output device.
• Syntax: puts(char type of array variable);
Formatted Input / Output Statements
• These statements are used read the data from the keyboard and write the data to the
monitor.
Formatted Input Statements
• Reads the formatted data from the keyboard.
scanf() function
• It is used to read information from the standard input device.
• scanf() function starts with a string argument and may contain additional arguments.
• scanf() requires conversion symbol(control string) to identify the data to be read
during execution of the program.
• Syntax: scanf(“control string”,&var1,&var2…..&varn);
• Eg: scanf(“%d %f %c”,&a,&b,&c);
Rules for writing scanf() function
• The control string must begin with (%) sign and must be within quotations.
• If there is a number of input data items, items must be repeated by commas and must
begin with (&) sign except for string input.
• The control string and the variables going to input should match with each other.
Formatted Output Statements
• Writes the formatted data to the monitor.
printf() function
• printf() is formatted output function.
• It is used to print the result message on the output screen.
• It prints all types of data values.
• It must have termination with semicolon.
Syntax:
printf(“control string”,var1,var2,……var n);
Rules for writing printf() function
• Place appropriate headings in the output.
• The Variable must be separated by comma and need not be begin with &sign.
• The control string and variables must match in their order.
• The control string must be in quotation.
• The printf statement is terminated by semicolon (;).
Example Program 1
#include<stdio.h>
#include<conio.h>
void main()
{
clrscr();
char a[10];
puts(“Enter a String:”);
gets(a);
puts(“Answer=”);
puts(a);
getch();
}
Output
Enter a String: MECH
Answer = MECH

Example Program 2
#include<stdio.h>
#include<conio.h>
void main()
{
clrscr();
char a;
printf(“Enter a Character:”);
a = getchar();
printf(“Answer=”);
putchar(c);
getch();
}
Output
Enter a Character: B Answer = B
Assignment Statements
Simple Assignments
 The C-based languages use == as the equality relational operator to avoid confusionwith
their assignment operator.
 The operator symbol for assignment:
1. = FORTRAN, BASI C, PL/I, C, C++, Java
2. := ALGOL, Pascal, Ada
Conditional Targets
If

flag ? count 1 : count2 = 0; ⇔


(flag)

Count1 =0;
Example:
Else
Compound Assignment Operators

 A compound assignment operator is a shorthand method of specifying a commonly


needed form of assignment.
 The form of assignment that can be abbreviated with this technique has the destinationvar
also appearing as the first operand in the expression on the right side, as in
a=a + b

 The syntax of assignment operators that is the catenation of the desired binary
operator to the = operator.
sum += value; ⇔ sum = sum + value;

Unary Assignment Operators

 C-based languages include two special unary operators that are actually abbreviated
assignments.
 They combine increment and decrement operations with assignments.
 The operators ++ and -- can be used either in expression or to form stand- alone
single-operator assignment statements. They can appear as prefix operators:
sum = ++ count; ⇔count = count + 1; sum = count;
 If the same operator is used as a postfix operator:
sum = count ++; ⇔sum = count; count = count + 1;

Assignment as an Expression:
 This design treats the assignment operator much like any other binary operator,
except that it has the side effect of changing its left operand.
Ex:
while ((ch = getchar())!=EOF)
{...} // why ( ) around assignment?
 The assignment statement must be parenthesized because the precedence of the
assignment operator is lower than that of the relational operators.
Disadvantage:
 Another kind of expression side effect which leads to expressions that is difficult toread
and understand.
For example,
a = b + (c = d / b++) – 1
Denotes the instructions
Assign b to temp
Assign b + 1 to b
Assign d / temp to c
Assign b + c to temp
Assign temp – 1 to a
 There is a loss of error detection in the C design of the assignment operationthat
frequently leads to program errors.

if (x = y) ...
instead of
if (x == y)
..

2.9 Decision Making and Looping Constructs


Control Statements
• All the instructions are executed sequentially by default, when no repetition of some
calculations is necessary.
• In some situation we may have to change the execution order of statements based onsome
condition or to repeat set of statements until certain conditions are met.
• In such situation conditional or control structure statements are used.
• C language provides four general categories of control structures.
a) Sequential Structure
• In which instructions are executed in sequence.
Eg:
i=i+1
;
j=j+1
;
b) Selection Structure
• Sequence of the instructions is determined by using the result of the condition.
• If the result is true, then the statement i=i+1 will be executed otherwise it executes
j=j+1.
Eg:
if(x>y)
i=i+1;
else
j=j+1;
c) Iteration Structure
• In which statements are repeatedly executed. These form program loops.
Eg:
for(i=1;i<=5;i++)
{
i=i+1;
}
d) Encapsulation Structure
• In which the other compound structure are included.
• It includes an if statement in a for loop or a for loop in an if statement.

2.9.1 Decision Making (Or) Conditional Statements


 Conditions are placed in the program using decision making statements.
 Decision making statements check the condition and then executes its sub blocks.
 ‘C’ language provides the following conditional statements or selection structures
(decision making).
 if statement
 if…else statement
 nested if…else statement
 if…else ladder
The if statement
 The if statement is a decision making statement.
 It is used to control the flow of execution by executing statements and also test
logically whether the condition is true (or) false. 
Syntax
if (condition is true)
{
statement 1;
statement 2;
}

Example
#include<stdio.h>
#include<conio.h>
void main( )
{
int a;
clrscr();
printf("\n Enter the Number:");
scanf("%d",&a);
if(a>10)
{
printf("\n a is greater than 10");
}
getch( ); }
Output:
Enter the Number: 12
a is greater than 10
The if…else statement
• It is basically two way decision making statement used to control the flow of executionand
to carry out the logical test.
• It has two blocks if &else. If block is executed when the condition is true, else blockis
executed when the condition is false.
Syntax
if(condition)
{
true statements;
}
else
{
false statements;
}
Example
#include<stdio.h>
#include<conio.h>
void main( )
{
int a;
clrscr();
printf("\n Enter the Number:");
scanf("%d",&a);
if(a>10)
{
printf("\n a is greater than 10");
}
else
{
printf("\n a is less than 10");
}
getch( );
}
Output:
Enter the number: 2
A is less than 10

nested if…else statement


• Writing an entire if…else statement in another if…else statement is called nesting,and
the statement is called nested
• if…else.
Syntax
if(condition 1) {
if(condition 2) {
true statement 2;
}
else {
false statement 2;
}
}
else {
false statement 1;
}
The if…else Ladder
• Number of logical conditions is checked for executing various statements.
• If three are more than three alternatives and indentation is not consistent, it may be
different for you to determine the logical structure of the if statement.
Syntax
if(condition 1) {
statement 1;
}
else if(condition 2) {
statement 2;
}
else if(condition 3) {
statement 3;
}
else {
default statements;
}
Example
#include<stdio.h>
#include<conio.h>
void main() {
int m1,m2,m3;
float avg;
printf("\n Enter the Marks:");
scanf("%d%d%d",&m1,&m2,&m3);
avg=(m1+m2+m3)/3;
printf("\n The average is:%f",avg);
printf("\n The Grade is:");
if(avg>=60) {
printf("First class");
}
else if(avg>=50) {
printf("Second class");
}
else if(avg>=35) {
printf("Thrid class");
}
else
{
printf("Fail");
} getch();
}
Output:
Enter the Marks: 65
75
70
The average is: 70.000000
The Grade is: First class

Switch or Branching Statements


The switch statement
• The switch statement is used to execute a particular group of statements from several
available groups of statements.
• It is a multi-way decision statement, it tests the value of given variable or expression
against a list of case values and when a match is found, a block of statements associated
with that case is executed.
• Switch statement required only one argument of any data type which is checked with
number of case options.
• If the value matches with case constant, that particular case statement is executed if not
default is executed.
• Every case statements terminate with break statement is used to exit from the current case
structure.
Syntax
switch(expression)
{
case constant 1 :
block
1;
break;
case constant 2 :
block 2;
break;
……………………
default :
default
block;break;
}
Example Program
#include<stdio.h>
#include<conio.h>
void main() {
int a, b, c, option;
printf(“\n 1.Addition”);
printf(“\n 2.subtraction”);
printf(“\n 3.multiplication”);
printf(“\n 4.Division”);
printf(“\n 5.Exit”);
printf(“\n Enter Two Numbers:”);
scanf(“%d %d”, &a, &b);
printf(“\n Enter Your Option:”)
scanf(“%d”, &option);
switch(option) {
case 1:
c=a+b;
printf(“\n Addition=%d” ,c);
break;
case 2:
c=a-b;
printf(“\n subtraction=%d”,c);
break;
case 3:
c=a*b;
printf(“\n multiplication=%d”,c);
break;
case 4:
c=a/b;
printf(“\n division=%d”,c);
break;
case 5:
exit(0)
;break;
default
:
printf(“Invalid Choice”);
}
getch();
}
Output
Enter Two Numbers: 2

4
Enter Your Option: 1
6
The break statement
• It is used to terminate the loop.
• When a break statement is used inside any C loop, then the loop is terminated.
Syntax: break;

The continue statement


• When a continue statement is encountered inside any C loop, the control is
automatically transferred to the beginning of the loop.
Syntax

continue;

The goto statement


• It is used to transfer the control unconditionally from one place to another place in the
program.
• When a goto statement is encountered inside a loop, the control is transferred to the
beginning.
• It requires a label to identify the place to move the execution.
• A label is a valid variable name and must be ended with colon (:).
Syntax
goto label;
………….
………….
label:
(Or)
label:
………..
goto
label;
Difference between Break and Continue statement

Break Continue
Break statement takes the control to the Continue statement takes the control to the
outside of the loop. beginning of the loop.

This can be used only in looping


It is also used in switch statement. statements.

Always associated with if condition in


loops. This is also associated with if condition.
Branching and Looping
Various Looping Concepts

• The loop is defined as the block of statements which are repeatedly executed for certain
number of times.
• The loop in a program consists of two parts,
 Body of the loop
 Control Statement – Used to test the condition
 They are three types of loop control statements
 while loop
 do-while loop
 for loop
The while Loop

• The while loop is an entry controlled loop or top tested loop statement, means the
condition is evaluated first if it is true, and then the body of the loop is executed.
• It is a repetitive control structure, used to execute the statements within the body untilthe
condition becomes false.
Syntax
while(condition)
{
……………..
body of the loop;
……………..
}
Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int x=0;
while(x<10)
{
printf(“%d\n”,x);
x++;
}
getch();
}
Output

0 6
1 7
2 8
3 9
4
5

The do…while Loop

• The do…while loop is an exit controlled loop or bottom tested loop statement, means the
condition is evaluated last if it is true, and then the body of the loop is executed.
• Loop will be executed at least once even though the condition is false.
• It is also a repetitive control structure, used to execute the statements within the bodyuntil
the condition becomes false.
Syntax
do
{…………..
body of the loop;
…………..
}while(condition);

Example Program

#include<stdio.h>
#include<conio.h>
void main()
{
int
x=0;
do
{
printf(“%d\n”,x);
x++;
}
while(x<4);
getch();
}
Output
0
1
2
3

The for Loop


• The for loop is another repetitive control structure, and is used to execute set of
instructions repeatedly until the condition becomes false.
• for loop has 3 parts,
1. Initialize Counter – used to initialize counter variable.
2. Test Condition – used to test the condition
3. Increment / Decrement Counter – used to increment / decrement the counter
variable
Syntax
for(initialize counter;test condition;increment / decrement counter)
{
……………
body of the loop;
……………..
}
Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int x;
for(x=0;x<10;x++)
{
printf(“%d\n”,x);
}
getch();
}
Output
0 6
1 7
2 8
3 9
4
5
Difference between while and do….while loop

while do….while
 It is an entry controlled loop or top  It is an exit controlled loop or bottom
tested loop. tested loop.
 First the condition is tested, if it is  It executes the body once, after it
true then the block is executed until checks the condition, if it is true the
the condition becomes false. body is executed until the condition
becomes false.
 Loop will not be executed if the  Loop will be executed at least once
condition is false. even though the condition is false.

2.10 Type casting

Type casting in C involves explicitly converting a variable from one data type to another. This
conversion is necessary when assigning or using variables of different types in expressions,
functions, or assignments where automatic type conversion (coercion) by the compiler may not
suffice or is not desired. Here's a detailed explanation of type casting in C:

Syntax
(type_name) expression
Where:

 type_name is the target data type to which you want to convert the expression.
 expression is the variable, constant, or expression that you want to convert.Examples

1. Basic Examples

Converting from int to float:

int num_int = 10;


float num_float;
num_float = (float) num_int;

 (int) num_float casts the float variable num_float to an integer. This results in num_int being
assigned the value 10, truncating the decimal part.

2. Type Casting in Expressions

Ensuring Correct Division Result:

int a = 10, b = 3;
float result;

result = (float) a / b;
 (float) a casts a to a float before division. This ensures that the division result stored in result
(3.3333...) is a float value, not truncated due to integer division.

Rules and Considerations

 Loss of Precision: When casting from a larger type to a smaller type (e.g., double to float,
float to int), there may be loss of data or precision. For example, converting 10.5 to an int
results in 10, discarding the fractional part.
 Range and Sign: When casting between signed and unsigned types, or when values exceed
the range of the target type, the behaviour can be implementation-defined or lead to
unexpected results. It's important to understand the ranges and behaviours of data types in C.
 Pointer Type Casting: Type casting also applies to pointers in C, where you can cast one
pointer type to another, but this requires caution to ensure compatibility and proper
alignment in memory.

2.11 Function

• It is a set of instructions that are used to perform specified tasks which repeatedly
occurs in the main program.
• Functions are a sub-program that contains one or more statements and it performs some
task when called.
• Functions are classified into two types,
o Pre-defined Functions
o User-defined Functions

Pre-defined Functions
• The pre-defined functions or library functions are built-in functions.
• The user can use the functions, but cannot modify the function.
• Example: sqrt()
User-defined Functions
• The functions defined by the user for their requirement are called user-defined
functions.
• Whenever it is needed, the user can modify the function.
• Example: sum(a,b)
Advantages
• The length of the source program can be reduced by dividing into it into smaller
functions.
• It is easy to locate and debug an error.
• It avoids coding of repeated instructions.
How Function Works
• Once a function is called the control passes to the called function.
• The working of calling function is temporarily stopped.
• When the execution of called function is completed then the control returns back to the
calling function and execute the next statement.

Parameters
• It provides the data communication between the calling function and called
function.
• There are two types of parameters. They are,
o Actual Parameters
o Formal Parameters
Actual Parameters
• These are the parameters transferred from the calling function (main program) to the
called function.

Formal Parameters
• These are the parameters which are used in the called function.
Types of Variable
Local and Global Variables
There are two kinds of variables.
1. Local variable
2. Global variable
Local Variable
• The local variable is defined within the body of the function.
• These variables are defined local to that function only or block only, other
function cannot access these variables.
Example
value(int a, int b)
{
int c, d;
}
c and d are local variables.
Global Variable
• Global variables are defined outside the main() function.
• Multiple functions can use these variables.
Example
int m=5,n=10;
main() {
int a,b;
}
m and n are global variables.
Program to demonstrate local and global variables
#include<stdio.h>
#include<conio.h>
int A, B; //Global Variables
int Add()
{
return A + B;
}
int main()
{
int answer; // Local Variable
A=5;
B=7;
clrscr();
answer=Add();
printf(“%d\n”, answer);
getch();
return 0;
Output:
12
The return statement
• The return statement may or may not send back some values to the calling
function.
• Syntax:
return;(Or) return(expression);

Function Prototypes
Explain different function prototypes. (Or) Explain function with and without arguments
with examples for each. (Nov/Dec 2014)
• The functions are classified into the following types depending on whether the
arguments are present or not and whether the value is returned or not.
• A function prototype declaration consists of the function’s return type, name and
argument list.
• It is always terminated with semicolon.
• If the programmer makes mistake, the compiler generates an error message.
• The 4 types of function prototypes are,
 Function with no arguments and no return values.
 Function with arguments and no return values.
 Function with arguments and with return values.
 Function with no arguments and with return values.
Function with no arguments and no return values
• In this prototype, no data transfer take place between the calling function and the called
function.
• The function is only executed and nothing is obtained.
• ie., the called program does not receive any data from the calling program and does
not send back any value to the calling program.

• These functions act independently, i.e. they get input and display output in the same
block.
Syntax
• The dotted lines indicate that, there is only transfer of control but no data transfer.
Example Program
#include<stdio.h>
#include<conio.h>
void add(); //Function with No Argument
void main()
{
clrscr();
add(); // Calling Function
getch();
}
void add() //Called Function
{
int a = 35, b = 10; printf("Sum
is: %d",a+b);
}
Output
Sum is: 45
Function with arguments and no return values
• In this prototype, data transfer take place between the calling function and the
called function.
• It is a one way data communication, i.e. the called program receives data from calling
program but it does not return any value to the calling program.

Syntax

• The continuous line indicates data transfer and the dotted line indicates transfer of
control.
Example Program
#include <stdio.h>
#include<conio.h>
void add(int, int); // Function with Argument
void main()
{
int a = 55, b = 10;
clrscr();
add(a,b); // Calling Function
getch();
}
void add(int a, int b) // Called Function
{
printf("Sum is: %d",a+b);
}
Output:
Sum is: 65
Function with arguments and with return values
• In this prototype, data transfer take place between the calling function and the
called function as well as between called function and calling function.
• It is a two way data communication, i.e. the called program receives data from calling
program and it return some value to the calling program.

Syntax

Example Program
#include<stdio.h>
#include<conio.h>
int add(int, int); //Function with Argument
void main()
{
int a = 5, b = 10;
clrscr();
printf("Sum is: %d", add(a,b)); //Calling Function
getch();
}
int add(int a, int b) // Called Function
{
return a+b;
}
Output:
Sum is: 15
Function with no arguments and with return value
• In this prototype, data transfer take place between the called function and the
calling function.
• It is a one way data communication, i.e. the called program does not receives data
from calling program but it return some value to the calling program.
Syntax

Example Program
#include<stdio.h>
#include<conio.h>
int add(); //Function with No Argument
void main()
{
clrscr();
printf("Sum is: %d",add()); //Calling Function
getch();
}
int add() //Called Function
{
int a=8,b=2;
return a+b;
}
Output:
Sum is: 10
Elements of User-defined Function
• To write an efficient user-defined function, the programmer must familiar with
the following three elements.
 Function Definition
 Function Declaration
 Function Call
Function Definition
• A function definition specifies the name of the function, the types and number of
parameters it expects to receive, and its return type.
• Syntax:
return-type function-name(parameters)
{
Body of the Function;
}

Function Declaration
• A function declaration tells the compiler about a function's name, return type, and
parameters.
• Syntax: return_type function name(parameters list);
Rules for declaring a function
• The list of parameter must be separated by comma.
• If the function does not return any value, then the return type void is must.
• If there are no parameters, simply place void in braces.
• The data type of actual and formal parameters must match.
Example
int max(int num1, int num2);
• Parameter names are not important in function declaration only their type is
required.
int max(int, int);
Function Call
• A function can be called by simply specifying the name of the function, return value
and parameters if presence.
Syntax
function name();
function name(parameter);
return value=function name(parameter);
Eg:

fun(); - Function without argument and return value


fun(a,b); - Function with argument
c=fun(a,b); - Function with argument and return value

Built-in functions (string functions, math functions)

 All C inbuilt functions which are declared in string.h header file are given below.
 The source code for string.h header file is also given below for your reference.

List of inbuilt C functions in string.h file:

String
Description
functions
strcat ( ) Concatenates str2 at the end of str1
strncat ( ) Appends a portion of string to another
strcpy ( ) Copies str2 into str1
strncpy ( ) Copies given number of characters of one string to another
strlen ( ) Gives the length of str1
Returns 0 if str1 is same as str2. Returns <0 if strl < str2. Returns >0 if str1 >
strcmp ( )
str2
Same as strcmp() function. But, this function negotiates case. “A” and “a” are
strcmpi ( )
treated as same.
strchr ( ) Returns pointer to first occurrence of char in str1
strrchr ( ) last occurrence of given character in a string is found
strstr ( ) Returns pointer to first occurrence of str2 in str1
strrstr ( ) Returns pointer to last occurrence of str2 in str1
strdup ( ) Duplicates the string
strlwr ( ) Converts string to lowercase
strupr ( ) Converts string to uppercase
strrev ( ) Reverses the given string
strset ( ) Sets all character in a string to given character
strnset ( ) It sets the portion of characters in a string to given character
strtok ( ) Tokenizing given string using delimiter

List of inbuilt C functions in math.h file:


 “math.h” header file supports all the mathematical related functions in C
language.
 All the arithmetic functions used in C language are given below.
 Click on each function name below for detail description and example programs.

Function Description
This function returns the nearest integer which is less than or equal to the
floor ( )
argument passed to this function.
This function returns the nearest integer value of the float/double/long double
argument passed to this function. If decimal value is from “.1 to .5”, it returns
round ( ) integer value less than the argument. If decimal value is from “.6 to
.9”, it returns the integer value greater than the argument.
This function returns nearest integer value which is greater than or equal to the
ceil ( )
argument passed to this function.
sin ( ) This function is used to calculate sine value.
cos ( ) This function is used to calculate cosine.
cosh ( ) This function is used to calculate hyperbolic cosine.
exp ( ) This function is used to calculate the exponential “e” to the xth power.
tan ( ) This function is used to calculate tangent.
tanh ( ) This function is used to calculate hyperbolic tangent.
sinh ( ) This function is used to calculate hyperbolic sine.

log ( ) This function is used to calculates natural logarithm.


log10 ( ) This function is used to calculates base 10 logarithm.
This function is used to find square root of the argument passed to this
sqrt ( )
function.
pow ( ) This is used to find the power of the given number.
This function truncates the decimal value from floating point value and
trunc.(.)
returns integer value.

Math functions with example


Math built in function are used to calculate some mathematics calculation. these are predefined by
the system or provided in the programming languages.

Some of the math functions are:

1. sqrt(argument): Return the square root of given argument.

for ex: sqrt(4) will return 2, sqrt(16) will return 4 and it will be same for all the numeric data.
## program: To display square root of natural number less than 10.
#include<stdio.h>
#include<conio.h>
#include<math.h> // for math function int
main()
{
float i,r;
for(i=1;i<=10;i++)
{
r=sqrt(i);
printf("%f n",r);
}
getch();
return 0;
}

Output

1.00
1.41
1.73
2.00
2.24
2.45
2.65
2.83
3.00
3.16

Parameter Passing Mechanism:

 Function is good programming style in which we can write reusable code that can be
called whenever require.
 Whenever we call a function then sequence of executable statements gets executed. We
can pass some of the information to the function for processing called argument /
parameter.
 There are two ways that the parameters can be passed to a function. They are,
 Call by Value (Pass by Value)
 Call by Reference (Pass by Reference / Address / Pointers)
Call by Value
 This method copies the values of actual parameters into the formal parameters of the
function.
 ie., xerox copy of original parameter is created and passed to the called function.
 Here, the changes to the formal parameter do not affect the actual parameter.

Example Program
#include<stdio.h>
#include<conoi.h>
void swap(int num1, int num2); //Function Definition
int main()
{
int n1=50, n2=70;
clrscr();
swap(n1, n2); // Calling Function
printf("\n Number 1: %d",n1);
printf("\n Number 2: %d",n2);
getch();
return(0);
}
void swap(int num1, int num2) // Called Function
{
int temp;
temp = num1;
num1 = num2;
num2 = temp;
}

Output
Number 1: 50
Number 2: 70

 In the above example, n1 and n2 are the original values and xerox copy of these values
is passed to the function and is copied into formal parameter num1 and num2 variable
of same function respectively.

Call by Reference
 It is another way of passing parameters to the function.
 While passing parameter using call by address method, we are passing the actual
address of the variable to the called function
 .Any changes to the formal parameter will affect the actual parameter.

Example Program
#include<stdio.h>
#include<conio.h>
void swap(int *num1, int *num2); //Function Definition
int main()
{
int n1=50, n2=70;
clrscr();
swap(&n1, &n2); //Calling Function
printf("\n Number 1: %d",n1);
printf("\n Number 2: %d",n2);
getch();
return(0);
}
void swap(int *num1, int *num2) //Called Function
{
int temp;
temp = *num1;
*num1 = *num2;
*num2 = temp;
}
Output:
Number 1: 70
Number 2: 50

 In the above example, n1 and n2 are the original values and address of these values is
passed to the function and is copied into formal parameter num1 and num2 variable of
same function respectively
Difference between Call by Value and Call by Reference

Call by Value Call by Reference


• Values are passed in function call. • Address or pointers are passed in
• This method copies the values of actual function call.
parameters into the formal parameters of • This method copies the addresses of
the function. actual parameters into the formal
• Here, the changes to the formal parameter parameters of the function.
do not affect the actual parameter. • Any changes to the formal parameter
will affect the actual parameter
Appendix
C Programming Examples

Write a C program to swap two numbers without using third variable.


#include<stdio.h>
#include<conio.h>
void main( )
{
int a, b;
clrscr( );
printf("\n Enter the value of a:");
scanf("%d",&a);
printf("\n Enter the value of b:");
scanf("%d",&b);
a=a+b;
b=a-b;
a=a-b;
printf(“\n After Swapping”);
printf("\n The value of a is:%d",a);
printf("\n The value of b is:%d",b);
getch( );
}
Output:
Enter the value of a: 5
Enter the value of b: 6
After Swapping The value of a is: 6
The value of b is: 5

Write a C program for swapping two numbers using call by value.


#include<stdio.h>
void swap(int number1, int number2)
{
int temp;
temp = number1;
number1 = number2;
number2 = temp;
}
int main()
{ int num1=50,num2=70;
swap(num1, num2);
printf("\n Number 1: %d",num1);
printf("\n Number 2: %d",num2);
return(0);
}
Output:
Number 1: 50
Number 2: 70
Call by Reference / Address / Pointers
Write a C program to exchange the values of two variables using pass by reference.
(April/May 2015)
#include <stdio.h>
void swap(int *num1, int *num2)
{ int temp;
temp = *num1;
*num1 = *num2;
*num2 = temp;
}
int main()
{
int num1=50,num2=70;
swap(&num1, &num2);
printf("\n Number 1: %d",num1);
printf("\n Number 2: %d",num2);
return(0);
}
Output:
Number 1: 70
Number 2: 50

Write a simple C program to understand input and output statements using pre-defined
functions.
#include <stdio.h>

int main() {
// Declare variables
int number;
float decimal;
char character;
char string[100];

// Read an integer value from the user


printf("Enter an integer: ");
scanf("%d", &number);

// Read a float value from the user


printf("Enter a floating-point number: ");
scanf("%f", &decimal);

// Read a character from the user


printf("Enter a single character: ");
scanf(" %c", &character); // Note the space before %c to skip any leftover whitespace

// Read a string from the user


printf("Enter a string: ");
scanf("%s", string);
// Print the values entered by the user
printf("\nYou entered:\n");
printf("Integer: %d\n", number);
printf("Floating-point number: %.2f\n", decimal);
printf("Character: %c\n", character);
printf("String: %s\n", string);

return 0;
}

Output
Enter an integer: 10
Enter a floating-point number: 3.14
Enter a single character: A
Enter a string: HelloWorld

You entered:
Integer: 10
Floating-point number: 3.14
Character: A
String: HelloWorld

To read two numbers x and n , and compute the sum of geometric progression
1+x+x2+x3+⋯+xn

#include <stdio.h>
#include <math.h> // For the pow() function

// Function to compute the sum of the geometric progression


double geometric_sum(double x, int n) {
if (x == 1) {
return n + 1; // Special case where the ratio is 1
} else {
return (pow(x, n + 1) - 1) / (x - 1);
}
}

int main() {
double x;
int n;

// Read input values for x and n


printf("Enter the value of x: ");
scanf("%lf", &x);
printf("Enter the value of n: ");
scanf("%d", &n);

// Calculate the sum of the geometric progression


double result = geometric_sum(x, n);

// Print the result


printf("The sum of the geometric progression is: %.2f\n", result);

return 0;
}
Output:

Enter the value of x: 2


Enter the value of n: 3
The sum of the geometric progression is: 15.0

To check whether a given number is palindrome or not

#include <stdio.h>

// Function to check if a number is a palindrome


int is_palindrome(int num) {
int reversed = 0, original = num, remainder;

// Reverse the number


while (num != 0) {
remainder = num % 10;
reversed = reversed * 10 + remainder;
num /= 10;
}

// Check if the original number is equal to the reversed number


return original == reversed;
}

int main() {
int num;

// Read input value for num


printf("Enter a number: ");
scanf("%d", &num);

// Check if the number is a palindrome


if (is_palindrome(num)) {
printf("%d is a palindrome.\n", num);
} else {
printf("%d is not a palindrome.\n", num);
}

return 0;
}
Output
Enter a number: 121
121 is a palindrome.

Enter a number: 123


123 is not a palindrome.

Write a simple C program to find the factors of a given number

#include <stdio.h>

// Function to find and print the factors of a given number


void find_factors(int num) {
printf("The factors of %d are: ", num);

// Loop through numbers from 1 to num


for (int i = 1; i <= num; i++) {
// Check if i is a factor of num
if (num % i == 0) {
printf("%d ", i);
}
}

printf("\n"); // Print newline at the end


}

int main() {
int num;

// Read input value for num


printf("Enter a number: ");
scanf("%d", &num);

// Find and print the factors of the given number


find_factors(num);

return 0;
}

Output

Enter a number: 28
The factors of 28 are: 1 2 4 7 14 28
Write a C program to find the frequency of each digit in a given number

#include <stdio.h>

#define DIGITS 10

int main() {
int num;
int frequency[DIGITS] = {0}; // Initialize an array to store frequency of digits

// Read the input number


printf("Enter a number: ");
scanf("%d", &num);

// Handle negative numbers by using the absolute value


if (num < 0) {
num = -num;
}

// Calculate frequency of each digit


while (num > 0) {
int digit = num % 10; // Extract the last digit
frequency[digit]++; // Increment the frequency count for that digit
num /= 10; // Remove the last digit from the number
}

// Print the frequency of each digit


printf("Frequency of each digit:\n");
for (int i = 0; i < DIGITS; i++) {
if (frequency[i] > 0) {
printf("Digit %d: %d times\n", i, frequency[i]);
}
}

return 0;
}

Output:

Enter a number: 122333


Frequency of each digit:
Digit 1: 1 times
Digit 2: 2 times
Digit 3: 3 time
UNIT-3 ARRAYS AND POINTERS
3.1ARRAYS-INTRODUCTION

To process large amount of data, we need a data structure known as Array. An array is a
collection of similar data elements. These data elements have the same data type. The elements of the
array are stored in consecutive memory locations and are referenced by an index also known as the
subscript. Subscript is an ordinary number which is used to identify an element of the array. Some
examples where the concept of an array can be used include:

● List of temperatures recorded on every day of the month


● List of employees in a company
● List of students in a class
● List of products sold
● List of customers

3.1.1 Declaration of Arrays

An array must be declared before being used. Declaring an array means specifying three things

● Data Type : What kind of values it can store, for example int, char, float, double
● Name : To identify the array
● Size : The maximum number of values that the array can hold

Arrays are declared using the following syntax:

type name[size];

The size of the array can be defined as a symbolic constant as shown in the following code.

#include <stdio.h>
#define N 100
main( )
{
int arr[N];
…….
}
C array indices start from 0. So for an array with N elements, the index of the last element is N-1.

1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th
element element element element element element element element element element
marks[0] marks[1] marks[2] marks[3] marks[4] marks[5] marks[6] marks[7] marks[8] marks[9]

Figure: Memory representation of an array of 10 elements


3.1.2 Accessing the elements of an array

For accessing an individual element of the array, the array subscript must be used.For example, to
access the fourth element of the array, we must write arr[3]. The subscript or index must be an integral
value or an expression that evaluates to an integral value. No single function that can operate on all the
elements of the array. To access all the elements of the array, we must use a loop. That is, we can access
all the elements of the array by varying the value of the subscript into the array. But note that the
subscript must be an integral value or an expression that evaluates to an integral value.

//set each element of the array to -1

int i, marks[10];
for(i=0; i<10; i++)
marks[i] = -1;
Code to initialize each element of the array to -1

The code accesses every individual element of the array and sets its value to -1. In the for loop,
the first value of marks[0] is set to -1, the value of the index (i) is incremented and the next value, i.e.,
marks[1] is set to -1. The procedure is continued until all the 10 elements of the array is set to -1.

3.1.2.1 Calculating the Address of array elements

C knows where an individual element of the array is located in the memory. The array name is
a symbolic reference to the address of the first byte of the array. The array name is actually referring to
the first byte of the array. The subscript or the index represents the offset from the beginning of the
array to the element being referenced. With just the array name and the index, C can calculate the
address of any element in the array.

Since an array stores all its data elements in consecutive memory locations, storing just the
base address, i.e., the address of the first element in the array is sufficient. The address of other data
elements can simply be calculated using the base address. The formula for doing this calculation is

Address of data element, A[k] =BA[A] +w(k – lower_bound)

Here, A is the array, k is the index of the element for which we have to calculate the address, BA is the
base address of the array A, w is the word size of one element in memory (for eg, the size of int is 2),
and lower_bound is the index of the first element in the array.

Since an array stores all its data elements in consecutive memory locations, storing just the base
address, i.e., the address of the first element in the array is sufficient. The address of other data
elements can simply be calculated using the base address. The formula for doing this calculation is

Address of data element, A[k] =BA[A] +w(k – lower_bound)


Here, A is the array, k is the index of the element for which we have to calculate the address, BA is the
base address of the array A, w is the word size of one element in memory (for eg, the size of int is 2),
and lower_bound is the index of the first element in the array.

Example:

Given an array int marks[]={99,67,78,56,88,90,34,85}. Calculate the address of marks[4] if base


address=1000.

Solution:

99 67 78 56 88 90 34 85
Marks [0] [1] [2] [3] [4] [5] [6] [7]

1000 1002 1004 1006 1008 1010 1012 1014

We know that storing an integer value requires 2 bytes, therefore , word size is 2 bytes.

Address(Marks[4]) =1000 +2(4-0)

=1000 + 2(4) =1008

Given an array float avg[]={99.0, 67.0, 78.0, 56.0, 88.0, 90.0, 34.0, 85.0}. Calculate the address of
avg[4] if base address=1000.

Solution:

99 67 78 56 88 90 34 85
avg [0] [1] [2] [3] [4] [5] [6] [7]

1000 1004 1008 1012 1016 1020 1024 1028

We know that storing a floating point number requires 4 bytes, therefore, word size is 4 bytes.

Address(avg[4]) =1000 +4(4-0)

=1000 =4(4) =1016

3.1.2.2 Calculating the Length of an Array

Length of the array is given by the number of elements stored in it. The general formula to
calculate the length of the array is:

Length =upper_bound – lower_bound + 1

Where upper_bound is the index of the last element and lower_bound is the index of the first element
in the array.
Example:

Let Age[5] be an array of integers such that

Age[0] =2 Age[1] =5 Age[2] =3 Age[3] =1 Age[4] =7

Solution:

Show the memory representation of the array and calculate its length.

Memory representation of the array Age is as given

2 5 3 1 7
Age[0] Age[1] Age[2] Age[3] Age[4]

Length- upper_bound – lower_bound + 1

Here lower_bound=0, upper_bound=4

Therefore, length=4 – 0 + 1 =5

3.1.3 Storing values in Arrays

To store values in the array, there are three ways – first, to initialize the array element at
the time of declaration; second , to input value for every individual element at the run time; third
to assign values to the individual elements. This is shown in fig

Initialize the elements during declaration

Input values for the elements from the keyboard

Assign values to individual elements

Initializing Arrays during Declaration

Elements of the array can also be initialized at the time of declaration as other variables. When an
array is initialized, we need to provide a value for every element in the array. Arrays are initialized by
writing,
type array_name[size]={list of values};

The values are written within curly brackets and every value is separated by a comma.It is a compiler
error to specify more number of values than the number of elements in the array. When we write,

int marks[5]= {90,82,78,95,88};


an array with name marks is declared that has enough space to store 5 elements. The first element, i.e.,
marks[0] is assigned with the value 90. Similarly the second element of the array, i.e., marks[1] is
assigned 82, and so on.

While initializing the array at the time of declaration, the programmer may omit the size of the array.
For example,

Intmarks[]={98,97,90};

The above statement is absolutely legal.Here the compiler will allocate enough space for all initialized
elements.If the number of values provided is less than the number of elements in the array,the
un-assigned elements are filled with zeros.

int marks[5] ={90,45,67,85,78};

90 45 67 85 78
[0] [1] [2] [3] [4]

int marks [5]={90,45};

90 45 0 0 0
[0] [1] [2] [3] [4]

int marks [5]={90,45,72,81,63,54};

90 45 72 81 63 54
[0] [1] [2] [3] [4] [5]

int marks [5]={0};

0 0 0 0 0 0
[0] [1] [2] [3] [4] [5]

Inputting values from the keyboard

An array can be filled by inputting values from the keyboard. In this method, a while/do-while or a for
loop is executed to input the value for each element of the array. For example

// Input value of each element of the array

inti, marks[10];

for (i=0;i<10;i++)

scanf(“%d”, &marks[i]);
In the code, we start with the index I at 0 and input the value for the first element of the array.since the
array can have 10 elements, we must input values for elements whose index varies from 0 to 9.
Therefore, in the for loop, we test for condition (i<10) which means the number of elements in the
array.

Assigning values to Individual elements

To assign values to individual elements of the array by using the assignment operator. Any value that
evaluates to the data type of the array can be assigned to the individual array element. A simple
assignment statement can be written as:

marks [3]=100;

Here, 100 is assigned to the fourth element of the array which is specified as marks [3]

We cannot assign one array to another array, even if the two arrays have the same type and size. To
copy an array, you must copy the value of every element of the first array into the element of the
second array. The following code illustrates copy an array

//copy an array at the individual element level

int i, arr1[10],arr2[10];

arr[1]={0,1,2,3,4,5,6,7,8,9};

for(i=0;i<10;i++)

arr2[i]=arr1[i];

The code accesses each element of the first array and simultaneously assigns its value to the
corresponding element of the second array. Finally, the index value I is incremented to access the next
element in succession. Therefore, when this code is executed, arr2[0]=arr1[0], arr2[1]=arr1[1],
arrr2[2]=arr1[2], and so on.

We can also use a loop to assign a pattern of values to the array elements. For example, if we want to
fill an array with even integers starting from 0, then we will write the code as

// Fill an array with even numbers

int i, arr[10];

for(i=0;i<10;i++)

arr[i]=i*2;
3.2 TWO –DIMENSIONAL ARRAYS
A one-dimensional array is organized linearly and only in one direction. But at times, we need to store
data in the form of matrices or tables.Here the concept of one-dimensional array is extended to
incorporate two-dimensional data structures. A two –dimensional array is specified using two
subscripts where one subscript denotes row and the other denotes column. C considers the
two-dimensional array as an array of one-dimensional arrays. Fig shows a two –dimensional array
which can be viewed as an array of arrays.

First
Dimension
second dimension

Declaring two-dimensional arrays

Similar to one-dimensional arrays, two-dimensional arrays must be declared before being used. The
declaration statement tells the compiler the name of the array, the data type of each element in the
array, and the size of each dimension. A two –dimensional array is declared as

data_typearray_name[row_size][column_size];

Therefore, a two dimensional m x n data elements and each element is accessed using two subscripts, I
and j where i<=m and j<=n.

For example, if we want to store the marks obtained by 3 students in 5 different subjects, then we can
declare a two-dimensional array as

int marks[3][5];

A two- dimensional array called marks is declared that hasm(3) rows and n(5) columns. The first
element of the array is denoted by marks[0][0], the second element as marks[0][1], and so on.
Here,marks [0][0]stores the marks obtained by the first student in the first subject, marks[1][0] stores
the marks obtained by the second student in the first subject, and so on.

Rows
Column 0 Column 1 Column 2 Column 3 Column 4
columns

Row 0 marks[0][0] marks[0][1] marks[0][2] marks[0][3] marks[0][4]

Row 1 marks[1][0] marks[1][1] marks[1][2] marks[1][3] marks[1][4]


Row 2 marks[2][0] marks[2][1] marks[2][2] marks[2][3] marks[2][4]
Hence, we see that a 2D array is treated as a collection of 1D arrays. To understand this, we can also
see the representation of a two dimensional array as shown in fig.

marks[0] marks[0] marks[1] marks[2] marks[3] marks[4]

marks[1] marks[0] marks[1] marks[2] marks[3] marks[4]

marks[2] marks[0] marks[1] marks[2] marks[3] marks[4]

Fig : representation of two –dimensional array marks[3][5] as individual 1D arrays.

Fig shows a rectangular picture of a two-dimensional array, these elements will be actually stored
sequentially in memory. Since computer memory is basically one-dimensional, a multidimensional
array cannot be stored in memory as a grid.

There are two ways of storing a two- dimensional array in memory. The first way is row major order
and the second is column major order. Let us see how the elements of a 2D array are stored in row
major order. Here , the elements of the first row are stored before the elements of the second and third
row, i.e., the elements of the array are stored row by row where n elements of the first row will occupy
the first n locations.

(0, 0) (0, 1) (0, 2) (0, 3) (1, 0) (1, 1) (1, 2) (1, 3) (2, 0) (2, 1) (2, 2) (2, 3)

Fig: elements of a 3X4 2D array in row major order

When we store the elements in a column major order, the elements of the first column are stored
before the elements of the second and third column, i.e., the elements of the array are stored column
by column where m elements of the first column will occupy the first m locations. This is illustrated in
fig.

(0, 0) (1,0) (2, 0) (3,0) (0, 1) (1, 1) (2, 1) (3, 1) (0, 2) (1, 2) (2, 2) (3, 2)

Fig: elements of a 4X3 2D array in column major order

In one-dimensional arrays, we have seen that computer does not keep track of the address of every
element in the array. It stores only the address of the first element and calculates the addresses of other
elements from the base address. Same is the case with a two –dimensional array. Here also, the
computer stores the base address and the address of the other elements is calculated using the
following formula.

Address(A[I][J])= B_A=w{M(J-1)+(I-1)}, if the array elements are stored in column major order, and

Address(A[I][J])= B_A+w{n(I-1)+(J-1)}, if the array elements are stored in row major order.

Where, w is the word size, i.e., number of bytes required to store element, M is the number of rows,
Nis the number of columns, I and J are the subscripts of the array element, and B_A is the base
address.

OPERATIONS ON TWO DIMENSIONAL ARRAYS

Two –dimensional arrays can be used to implement the mathematical concept of matrices. In
mathematics, a matrix is a grid of numbers, arranged in rows and columns. Thus, using
two-dimensional arrays, we can perform the following operations on an mXn matrix.

Transpose: Transpose of a m x n matrix A is given as a n X m matrix B where,

Bi,j= Aj,i

Sum :Two matrices that are compatible with each other can be added together thereby storing the
result in the third matrix. Two matrices are said to be compatible when they have the same number of
rows and columns. Elements of the matrices can be added by writing:

Ci,j =Ai.j+ Bi, j

Difference:Two matrices that are compatible with each other can be subtracted thereby storing the
result in the third matrix. Two matrices are said to be compatible when they have the same number of
rows and columns. Elements of the matrices can be subtracted by writing:

Ci,j = Ai,j - Bi,j

Product: Two matrices canbe multiplied with each other if the number of columns in the first matrix
is equal to the number of rows in the second matrix. Therefore, m X n matrix A can be multiplied with
a pXq matrix if n=p, Elements of the matrices can be multiplied by writing:

Ci,j=∑Ai,kBk,j for k=1 to k<n

MULTIDIMENSIONAL ARRAYS

A multidimensional array in simple terms is an array of arrays. Like we have one index in a one
dimensional array, two indices in atwo-dimensional array, in the same way we have n indices in an n-
dimensional array or multidimensional array. Conversely, an n-dimensional array is specified using n
indices. An n –dimensional m1X m2 X m3X…mn array is a collectionm1*m2 * m3*…*mnelements. In a
multidimensional array, a particular element is specified by using n subscripts as A[I1 ] [I2] [I3]…[In],
where,

I1 <=M1 I2<=M2 I3<=M3 ……In<=Mn

A multidimensional array can contain as many indices as needed and the requirement of the memory
increases with the number of indices used. However, practically speaking we will hardly use more
than three indices in any program. Figure 5.32 shows a three- dimensional array. The array has three
pages, four rows, and two columns.

Page 3

Q U
R V
S W
SECOND T X
DIMENSION
(COLUMNS)
I M
FIRST
DIMENSION J N
(ROWS)
K O
Page 2
L P
Page 1
A E

Figure: Three-dimensional array B F

A multidimensional array is declared and C G initialized similar to one and two


dimensional arrays.
D H
3.3 ARRAY OPERATIONS

Operations on an Array:

While there are many operations that can be implemented and studied, we only need to be familiar
with the primary ones at this point. An array supports the following operations:

● Traversal
● Insertion
● Deletion
● Search

Other operations include sorting ascending, sorting descending, etc. Let's follow up on these
individually.
Traversal:
Visiting every element of an array once is known as traversing the array.
Why Traversal?
For use cases like:

● Storing all elements – Using scanf()


● Printing all elements – Using printf()
● Updating elements.

An array can easily be traversed using a for loop in C language.


An important note on Arrays:
If we create an array of length 100 using a[100] in C language, we need not use all the elements. It is
possible for a program to use just 60 elements out of these 100. (But we cannot go beyond 100
elements).

Insertion:
An element can be inserted in an array at a specific position. For this operation to succeed, the array
must have enough capacity. Suppose we want to add an element 10 at index 2 in the
below-illustrated array, then the elements after index 1 must get shifted to their adjacent right to
make way for a new element.

When no position is specified, it’s best to insert the element at the end to avoid shifting, and this is
when we achieve the best runtime O(1).
Deletion:
An element at a specified position can be deleted, creating a void that needs to be fixed by shifting
all the elements to their adjacent left, as illustrated in the figure below.
We can also bring the last element of the array to fill the void if the relative ordering is not important.
:)

Searching:
Searching can be done by traversing the array until the element to be searched is found.O(n) There is
still a better method. As you may remember, we talked about binary search in some previous
tutorials. Don't forget to look it up if you missed it. We had analyzed both linear and binary search.
This search method is only applicable for sorted arrays. Therefore, for sorted arrays, the time taken
to search is much less than an unsorted array. O(logn)
Sorting:
Sorting means arranging an array in an orderly fashion (ascending or descending). We have different
algorithms to sort arrays.

3.4 Pointers
Pointer is a variable which contains the memory address of another variable. (Or) A pointer is a
variable whose value is the address of another variable.

The memory address is the location where program instructions and data are stored; pointers
can be used to access and manipulate data stored in the memory.

Example

a=10

a🡪 Variable

10🡪 Value

80F🡪 Address
● The variable that holds memory address is called pointer variables.
● A pointer variable is therefore nothing but a variable that contains an address, which is a
location of another variable.
● Value of pointer variable will be stored in another memory location.

Pointer Operator :
Operator Operator Name Purpose
* Value at Operator Gives Value stored at Particular address

& Address Operator Gives Address of Variable

● In order to create pointer to a variable we use “*” operator


● Find the address of variable we use “&” operator.
● Don’t Consider “&” and “*” operator as Logical AND and Multiplication Operator in Case of
Pointer.

Important Notes :

‘&’ operator is called as address Operator

‘*’ is called as ‘Value at address’ Operator

‘Value at address’ Operator gives ‘Value stored at Particular address.

‘Value at address’ is also called as ‘Indirection Operator’


Pointer Operators -Program

Output:
The address of n is 1002

The Value of n is 20

Features of Pointers
● It is more efficient in handling array and structure.
● It is used for saving memory space.
● It reduces the length and complexity of the program.
● It provides dynamic memory allocation.

Advantages of Pointers
● It is more compact and efficient code.
● It is used to achieve clarity and simplicity.
● It enables us to access the memory directly.

Example Program
#include<stdio.h>

#include<conio.h>

void main()

{
int x=5;

printf("\n The Address of x = %u",&x); printf("\n The Value of x = %d",x);

Output

The Address of x = 8714

The Value of x = 5

Declaring a Pointer Variable

● Pointer is a variable that contains the address of another variable.

Syntax:data_type *pointer-name;

Eg:int *a;

Initialization of Pointer Variable (Accessing the Pointer Variable)

● Pointer Initialization is the process of assigning address of variable to pointer variable.


● Pointer variable contains address of variable of same data type.
● In C language address operator (&) is used to determine the address of a variable.
● The ampersand (&) returns the address of the variable associated with it. int a = 10 ;

int *ptr ; // Pointer Declaration ptr = &a ; // Pointer Initialization (Or)

int *ptr = &a ; // Initialization and Declaration Together

● The ampersand (&) is an operator, which is used to access the address of a variable and assign
it to a pointer to initialize it.

Dereferencing of Pointer

● Once a pointer has been assigned the address of a variable. To access the value of variable,
pointer is dereferenced, using the indirection operator (*).

Example Program 1

#include<stdio.h>

#include<conio.h>

void main()

{
int x=5; int *a; a=&x;

printf("\n The Value of x = %d",x);

printf("\n The Address of x = %u",&x);

printf("\n The Value of a = %d",a);

printf("\n The Value of x = %d",*a);

Output

The Value of x = 5

The Address of x = 8758

The Value of a = 8758

The Value of x = 5

Example Program2

#include<stdio.h>

#include<conio.h>

void main()

int y=10;

int *a;

a=&y;

printf("\n The Value of y = %d",y);

printf("\n The Address of y = %u",&y);

printf("\n The Value of a = %d",a);

printf("\n The Address of a = %u",&a);

Output
The Value of y = 10

The Address of y = 5001

The Value of a = 5001

The Address of a = 8000

Null Pointer

● A pointer is said to be null pointer if zero is assigned to the pointer.

Example

int *a,*b;

a=b=0;

Pointer to Pointer

● Here one pointer stores the address of another pointer variable.

Example:

int x=10,*a,**b;

a=&x;

b=&a;

Example Program

#include<stdio.h>

#include<conio.h>

void main()
{

int a=10;

int *b,**c;

b=&a;

c=&b;

printf("\n The Value of a = %d",a);

printf("\n The Address of a = %u",&a);

printf("\n The Value of b = %d",b);

printf("\n The Address of b = %u",&b);

printf("\n The Value of c = %d",c);

printf("\n The Address of c = %u",&c);

Output

The Value of a = 10

The Address of a = 5001

The Value of b = 5001

The Address of b = 8000

The Value of c = 8000

The Address of c = 9000

3.5 Pointers Arithmetic


● A pointer in C is an address, which is a numeric value. Therefore we can perform arithmetic
operations on a pointer as we do on a numeric value.
● The arithmetic operations on pointer variable affect the memory address pointed by pointer.
● The different types of arithmetic operations performed on pointers are,
⮚ Incrementing Pointer
⮚ Decrementing Pointer
⮚ Pointer Addition
⮚ Pointer Subtraction
⮚ `Pointer Comparison

Incrementing Pointer

● Incrementing a pointer to an integer data will cause its value to be incremented by 2.


● This differs from compiler to compiler as memory required to store integer vary compiler to
compiler
● Incrementing Pointer Variable Depends Upon data type of the Pointer variable.

Syntax:

new_value = current_address + i * sizeof(pointer_data type)

Data Type Older Address stored in Next Address stored in pointer


pointer after incrementing (ptr++)
int 1000 1002
float 1000 1004
char 1000 1001

Example

#include<stdio.h>

#include<conio.h>

void main()

int a[3] = {10,20,30};

int i, *ptr;

clrscr();

ptr = a;

for(i=3; i>0; i--)


{

printf("\n Address=%x",ptr);

printf("\t Value=%d",*ptr);

ptr++;

getch();

Output:

Address = fff0 Value=10

Address = fff2 Value=20

Address = fff4 Value=30

Decrementing Pointer

● Decrementing a pointer to an integer data will cause its value to be decremented by 2.


● This differs from compiler to compiler as memory required to store integervary compiler to
compiler.
● Decrementing of pointer variable depends upon data type of the pointer variable.

Syntax:

new_address = current_address - i * sizeof(pointer_data type)

Data Type Older Address stored in pointer Next Address stored in pointer after
decrementing (ptr–)
Int 1000 0998
Float 1000 0996
Char 1000 0999

Example

#include<stdio.h>

#include<conio.h>

void main()

int a[3] = {10,20,30};

int i, *ptr;

clrscr();

ptr = a;

for(i=0; i<3; i--)

printf("\n Address=%x",ptr);

printf("\t Value=%d",*ptr);

ptr++;

getch();

Output:

Address = fff4 Value=30

Address = fff2 Value=20

Address = fff0 Value=10

Pointer Addition

● In C Programming we can add any integer number to Pointer variable. It is perfectly legal in c
programming to add integer to pointer variable.
Syntax:

final_value = (address) + (number * sizeof(pointer_data type))

Consider the following example,

int *ptr , n;

ptr = &n ;

ptr = ptr + 3;

Example

#include<stdio.h>

#include<conio.h>

void main()

int a = 5, b = 10;

int *x, *y;

clrscr();

x = &a, y = &b;

printf(“%d”, (*x + *y));

getch();

Output:

15

Pointer Subtraction

● In C Programming we can add any integer number to Pointer variable. It is perfectly legal in c
programming to add integer to pointer variable.
Syntax:

ptr = initial_address - n * (sizeof(pointer_data_type))

For Example,

int *ptr , n;

ptr = &n ;

ptr = ptr - 3;

Example

#include<stdio.h>

#include<conio.h>

void main()

int a = 5, b = 10;

int *x, *y;

clrscr();

x = &a, y = &b;

printf(“%d”, (*x - *y));

getch();

Output:

-5

Pointer Comparison

● Pointer comparison is valid only if the two pointers are pointing to same array.
● All Relational Operators can be used for comparing pointers of same type.
● All Equality and Inequality Operators can be used with all Pointer types.
● Pointers cannot be Divided or Multiplied.
Example

#include<stdio.h>

int main()

int *ptr1;

float *ptr2;

ptr1 = (int *) 1000;

ptr2 = (float *) 2000;

if(ptr2 > ptr1)

printf("ptr2 is far from ptr1");

return(0);

Output:

ptr2 is far from ptr1

Array and Pointer

● Arrays are closely related to pointers in C programming but the important difference between
them is that, a pointer variable can take different addresses as value whereas; in case of array it
is fixed.

Eg:inta[5]={1,2,3,4,5};

Memory Address a[0] a[1] a[2] a[3] a[4]


Value 1 2 3 4 5
Base Address 4000 4002 4004 4006 4008

Explanation

● a[5] means the array ‘a’ has 5 elements and of integer data type.
● The base address (Assume 4000) of the array starts with 0th element of the array.
● The array is in integer type, the integer will have 2 bytes and hence the address of the next
address element is incremented by 2.

Example

#include<stdio.h>

int main()

char c[4];

int i;

for(i=0;i<4;++i) {

printf("Address of c[%d]=%x\n",i,&c[i]);

return 0;

Output:

Address of c[0]=28ff44

Address of c[1]=28ff45

Address of c[2]=28ff46

Address of c[3]=28ff47

Relation between Arrays and Pointers

intnum[5];
● In arrays, name of the array always points to the first element of an array.
● Here, address of first element of an array is &num[0].
● Also, num represents the address of the pointer where it is pointing. Hence, &num[0] is
equivalent to arr.
● Also, value inside the address &num[0] and address num are equal. Value in address &num[0]
is num[0] and value in address num is *num.
● Hence, num[0] is equivalent to *arr.

Similarly,

&a[1] is equivalent to (a+1) AND, a[1] is equivalent to *(a+1).

&a[2] is equivalent to (a+2) AND, a[2] is equivalent to *(a+2).

&a[3] is equivalent to (a+1) AND, a[3] is equivalent to *(a+3).

&a[i] is equivalent to (a+i) AND, a[i] is equivalent to *(a+i).

Example

// Program to find the sum of six numbers with arrays and pointers.

#include<stdio.h>

int main()

inti,class[6],sum=0;

printf("Enter 6 Numbers:\n");

for(i=0;i<6;++i){

scanf("%d",(class+i)); // (class+i) is equivalent to &class[i]

sum += *(class+i); // *(class+i) is equivalent to class[i]

printf("Sum=%d",sum);

return 0;
}

Output:

Enter 6 Numbers:

Sum=21

Program of Sorting of names

#include<stdio.h>

void main()

char *T;

int I,J,K;

char *ARRAY[5]={"SUNIL","ANIL","DILIP","JAY","BHARAT"};

clrscr();

for(I=0;I<5;I++)

printf("%s \t",ARRAY[I]);

printf("\n");

for(I=0;I<4;I++)

{
for(J=0;J<4-I;J++)

{ K=strcmp(ARRAY[J],ARRAY[J+1]);

if(K>0)

T=ARRAY[J];

ARRAY[J]=ARRAY[J+1];

ARRAY[J+1]=T;

} for(I=0;I<5;I++)

printf("%s \t",ARRAY[I]);

getch();

Output:

"SUNIL","ANIL","DILIP","JAY","BHARAT”

"ANIL","BHARAT”, “DILIP"," JAY”, “SUNIL”

Example of Pointer and Functions

/* C Program to swap two numbers using pointers and function. */

#include <stdio.h>

void swap(int *a,int *b);

int main()

int num1=5,num2=10;
swap(&num1,&num2); /* address of num1 and num2 is passed to swap function*/

printf("Number 1 = %d\n",num1);

printf("Number 2 = %d",num2);

return 0;

void swap(int *a,int *b) /* pointer a and b points to address of num1 and num2 respectively */

int temp;

temp=*a;

*a=*b;

*b=temp;

Output:

Number 1 = 10

Number 2 = 5

Explanation

● The address of memory location num1 and num2 are passed to function and the pointers *a and
*b accept those values.
● So, the pointer a and b points to address of num1 and num2 respectively.
● When, the values of pointer are changed, the value in memory location also changed
correspondingly.
● Hence, change made to *a and *b was reflected in num1 and num2 in main
function.

Pointers with Multi-Dimensional Array

● A multidimensional array can also be represented with an equivalent pointer notation.

Syntax

data-type (*pointer variable) [Expression2];


Example

int (*a)[20]; 🡪 Pointer

int a[10][20]; 🡪Array

Example Program

#include<stdio.h>

main()

intarr[3][2] = {

{5, 100},

{10, 101},

{15, 102},

};

int a, b;

for(a=0;a<3;a++)

printf(“address of %d array=%u”,a,&arr[a]);

for(b=0;b<2;b++)

printf(“value =%d”,arr[a][b]);

Output

Address of 0 Array=4000

Value=5

Value=100

Address of 1 Array=4002
Value=10

Value=101

Address of 2 Array=4000

Value=15

Value=102

Pointers and Strings

1.Character and Pointer

● A character pointer is a pointer to the character.


● It can be declared as,

char *pointer_character;

2.String and Pointer

char *pointers message;

3.6 STRINGS IN C

A String in C programming is a sequence of characters terminated with a null character ‘\0’. The C
String is stored as an array of characters. The difference between a character array and a C string is
that the string in C is terminated with a unique character ‘\0’.

C String Declaration Syntax

Declaring a string in C is as simple as declaring a one-dimensional array. Below is the basic syntax for
declaring a string.

char string_name[size];

In the above syntax string_name is any name given to the string variable and size is used to define the
length of the string, i.e the number of characters strings will store.

There is an extra terminating character which is the Null character (‘\0’) used to indicate the
termination of a string that differs strings from normal character arrays.

C String Initialization

A string in C can be initialized in different ways. We will explain this with the help of an example.
Below are the examples to declare a string with the name str and initialize it with “GeeksforGeeks”.
We can initialize a C string in 4 different ways which are as follows:

1. Assigning a String Literal without Size

String literals can be assigned without size. Here, the name of the string str acts as a pointer because it
is an array.

char str[] = "GeeksforGeeks";

2. Assigning a String Literal with a Predefined Size

String literals can be assigned with a predefined size. But we should always account for one extra
space which will be assigned to the null character. If we want to store a string of size n then we should
always declare a string with a size equal to or greater than n+1.

char str[50] = "GeeksforGeeks";

3. Assigning Character by Character with Size

We can also assign a string character by character. But we should remember to set the end character as
‘\0’ which is a null character.

char str[14] = { 'G','e','e','k','s','f','o','r','G','e','e','k','s','\0'};

4. Assigning Character by Character without Size

We can assign character by character without size with the NULL character at the end. The size of the
string is determined by the compiler automatically.

char str[] = { 'G','e','e','k','s','f','o','r','G','e','e','k','s','\0'};

Note: When a Sequence of characters enclosed in the double quotation marks is encountered by the
compiler, a null character ‘\0’ is appended at the end of the string by default.

C String Example

// C program to illustrate strings

#include <stdio.h>

#include <string.h>

int main()

// declare and initialize string


char str[] = "Geeks";

// print string

printf("%s\n", str);

int length = 0;

length = strlen(str);

// displaying the length of string

printf("Length of string str is %d", length);

return 0;

Output

Geeks

Length of string str is 5

We can see in the above program that strings can be printed using normal printf statements just like we
print any other variable. Unlike arrays, we do not need to print a string, character by character.

Note: The C language does not provide an inbuilt data type for strings but it has an access specifier
“%s” which can be used to print and read strings directly.

Read a String Input From the User

The following example demonstrates how to take string input using scanf() function in C

// C program to read string from user

#include<stdio.h>

int main()

// declaring string

char str[50];

// reading string

scanf("%s",str);
// print string

printf("%s",str);

return 0;

Input

GeeksforGeeks

Output

GeeksforGeeks

You can see in the above program that the string can also be read using a single scanf statement. Also,
you might be thinking that why we have not used the ‘&’ sign with the string name ‘str’ in scanf
statement! To understand this you will have to recall your knowledge of scanf.

We know that the ‘&’ sign is used to provide the address of the variable to the scanf() function to store
the value read in memory. As str[] is a character array so using str without braces ‘[‘ and ‘]’ will give
the base address of this string. That’s why we have not used ‘&’ in this case as we are already
providing the base address of the string to scanf.

Now consider one more example,

// C Program to take input string which is separated by

// whitespaces

#include <stdio.h>

// driver code

int main()

char str[20];

// taking input string

scanf("%s", str);

// printing the read string


printf("%s", str);

return 0;

Input

Geeks for Geeks

Output

Geeks

Here, the string is read only till the whitespace is encountered.

Note: After declaration, if we want to assign some other text to the string, we have to assign it one by
one or use the built-in strcpy() function because the direct assignment of the string literal to character
array is only possible in declaration.

How to Read a String Separated by Whitespaces in C?

We can use multiple methods to read a string separated by spaces in C. The two of the common ones
are:

We can use the fgets() function to read a line of string and gets() to read characters from the standard
input (stdin) and store them as a C string until a newline character or the End-of-file (EOF) is reached.

We can also scanset characters inside the scanf() function

1. Example of String Input using gets()

// C program to illustrate

// fgets()

#include <stdio.h>

#define MAX 50

int main()

char str[MAX];

// MAX Size if 50 defined

fgets(str, MAX, stdin);


printf("String is: \n");

// Displaying Strings using Puts

puts(str);

return 0;

Input

GeeksforGeeks

Output

String is:

GeeksforGeeks

2. Example of String Input using scanset

// C Program to take string separated by whitespace using

// scanset characters

#include <stdio.h>

// driver code

int main()

char str[20];

// using scanset in scanf

scanf("%[^\n]s", str);

// printing read string

printf("%s", str);

return 0;

}
Input

Geeks for Geeks

Output

Geeks for Geeks

C String Length

The length of the string is the number of characters present in the string except for the NULL
character. We can easily find the length of the string using the loop to count the characters from the
start till the NULL character is found.

Passing Strings to Function

As strings are character arrays, we can pass strings to functions in the same way we pass an array to a
function. Below is a sample program to do this:

// C program to illustrate how to

// pass string to functions

#include <stdio.h>

void printStr(char str[]) { printf("String is : %s", str); }

int main()

// declare and initialize string

char str[] = "GeeksforGeeks";

// print string by passing string

// to a different function

printStr(str);

return 0;

Output:

String is : GeeksforGeeks
Note: We can’t read a string value with spaces, we can use either gets() or fgets() in the C
programming language.

Strings and Pointers in C

In Arrays, the variable name points to the address of the first element.

Below is the memory representation of the string str = “Geeks”.

Similar to arrays, In C, we can create a character pointer to a string that points to the starting address
of the string which is the first character of the string. The string can be accessed with the help of
pointers as shown in the below example.

// C program to print string using Pointers

#include <stdio.h>

int main()

char str[20] = "GeeksforGeeks";

// Pointer variable which stores

// the starting address of

// the character array str

char* ptr = str;

// While loop will run till

// the character value is not

// equal to null character

while (*ptr != '\0') {

printf("%c", *ptr);

// moving pointer to the next character.

ptr++;

return 0;
}

Output

GeeksforGeeks

Standard C Library – String.h Functions

The C language comes bundled with <string.h> which contains some useful string-handling functions.
Some of them are as follows:

strlen(string_name)

Returns the length of string name.

strcpy(s1, s2)

Copies the contents of string s2 to string s1.

strcmp(str1, str2)

Compares the first string with the second string. If strings are the same it returns 0.

strcat(s1, s2)

Concat s1 string with s2 string and the result is stored in the first string.

strlwr()

Converts string to lowercase.

strupr()

Converts string to uppercase.

strstr(s1, s2)

Find the first occurrence of s2 in s1.

Parameter Passing Methods

● Function is good programming style in which we can write reusable code that can be called
whenever require.
● Whenever we call a function then sequence of executable statements gets executed. We can
pass some of the information to the function for processing called argument / parameter.
● There are two ways that the parameters can be passed to a function. They are,
⮚ Call by Value (Pass by Value)
⮚ Call by Reference (Pass by Reference / Address / Pointers)
Call by Value

● This method copies the values of actual parameters into the formal parameters of the function.

ie.,xerox copy of original parameter is created and passed to the called function.

● Here, the changes to the formal parameter do not affect the actual parameter.

Example Program

#include<stdio.h>

#include<conio.h>

void swap(int num1, int num2); //Function Definition

int main()

int n1=50, n2=70;

clrscr();

swap(n1, n2); // Calling Function

printf("\n Number 1: %d",n1);

printf("\n Number 2: %d",n2);

getch();

return(0);

void swap(int num1, int num2) // Called Function

int temp;

temp = num1;

num1 = num2;

num2 = temp;

}
Output:

Number 1: 50

Number 2: 70

● In the above example, n1 and n2 are the original values and xerox copy of these values is
passed to the function and is copied into formal parameter num1 and num2 variable of same
function respectively.

3.7 Call by Reference

● It is another way of passing parameters to the function.


● While passing parameter using call by address method, we are passing the actual address of the
variable to the called function.
● Any changes to the formal parameter will affect the actual parameter.

Example Program

#include<stdio.h>

#include<conio.h>

void swap(int *num1, int *num2); //Function Definition

int main()

int n1=50, n2=70;


clrscr();

swap(&n1, &n2); //Calling Function

printf("\n Number 1: %d",n1);

printf("\n Number 2: %d",n2);

getch();

return(0);

void swap(int *num1, int *num2) //Called Function

int temp;

temp = *num1;

*num1 = *num2;

*num2 = temp;

Output:

Number 1: 70

Number 2: 50

● In the above example, n1 and n2 are the original values and address of these values is passed to
the function and is copied into formal parameter num1 and num2 variable of same function
respectively.
Difference between Call by Value and Call by Reference

Call by Value Call by Reference


● Values are passed in function call. ● Address or pointers are passed in function
● This method copies the values of actual call.
parameters into the formal parameters of ● This method copies the addresses of actual
the function. parameters into the formal parameters of
● Here, the changes to the formal parameter the function.
do not affect the actual parameter. ● Any changes to the formalparameter will
affect the actual parameter.

Memory allocation in C programs:


C supports three kinds of memory allocation through the variables in C programs:

Static Allocation:

When we declare a static or global variable, static allocation is done for the variable. Each static or
global variable is allocated a fixed size of memory space. The number of bytes reserved for the
variable cannot change during execution of the program. Till now we have been using this technique
to define variables, arrays and pointers.
Automatic Allocation

When we declare an automatic variable such as a function argument or a local variable, automatic
memory allocation is done. The space for an automatic variable is allocated when the compound
statement containing the declaration is entered, and is freed when it exits from a compound statement.

Dynamic Allocation:

A third important kind of memory allocation is known as Dynamic allocation. In the following
sections we will read about dynamic memory allocation through pointers.

3.8 Dynamic Memory Allocation


The process of allocating memory to the variables during execution of the program or at run time is
known as dynamic memory allocation. C language has four library routines which allow this function.

Till now whenever we needed an array we had declared a static array of fixed size, say

intarr[100];

When this statement is executed, consecutive space for 100 integers is allocated. It is uncommon that
we may be using only 10% or 20% of the allocated space thereby wasting rest of the space. To
overcome this problem and to utilize the memory efficiently C language provides a mechanism of
dynamically allocating memory so that only the amount of memory that is actually required is
reserved. We reserve space only at the run time for the variables that are actually required. Dynamic
memory allocation gives best performance in situations in which we do not know memory
requirements in advance.

C provides four library routines to automatically allocate memory at the run time.

Function Task
Malloc( Allocates memory and returns a pointer to the first byte of
) allocated space
Calloc() Allocates space for an array of elements and initialize them
to zero. Like malloc(), calloc() also returns a pointer to the
memory
free() Frees previously allocated memory
realloc() Alters the size of previously allocated memory
When we have to dynamically allocate memory for variables in our programs then pointers are the
only way to go. when we use malloc() for dynamic memory allocation, then you need to manage the
memory allocated for variables yourself.
Memory Allocation Process

In computer science, the free memory region is called the heap. The size of heap is not constant as it
keeps changing when the program is executed. In the course of program execution, some new
variables are created and some variables cease to exist when the block in which they were declared is
existed. For this reason it is not uncommon to encounter memory overflow problems during dynamic
allocation process. When an overflow condition occurs, the memory allocation functions mentioned
above will return a null pointer.

Allocating a block of memory

Let us see how memory is allocated using the malloc(). malloc is declared in <stdlib.h>, so we include
this header file in any program that calls malloc. The malloc function reserves a block of memory of
specified size and returns a pointer of type void. This means that we can assign it to any type of
pointer. The general syntax of the malloc() is

ptr=( cast-type*)malloc( byte-size);

whereptr is a pointer of type cast-type. The malloc() returns a pointer to an area of memory with size
byte-size. For example,

arr=(int*)malloc(10*sizeof(int));

This statement is used to dynamically allocate memory equivalent to 10 times the area of int byes. On
successful execution of the statement the space is reserved and the address of the first byte of memory
allocated is assigned to the pointer arr of type int.

3.9 FUNCTION POINTERS:

A function pointer, also called a subroutine pointer or procedure pointer, is a pointer referencing
executable code, rather than data. Dereferencing the function pointer yields the referenced function,
which can be invoked and passed arguments just as in a normal function call. Such an invocation is
also known as an "indirect" call, because the function is being invoked indirectly through a variable
instead of directly through a fixed identifier or address.

Function pointers allow different code to be executed at runtime. They can also be passed to a function
to enable callbacks.

Function pointers are supported by third-generation programming languages (such as PL/I, COBOL,
Fortran, dBASE dBL, and C) and object-oriented programming languages (such as C++, C#, and D).

Simple function pointers


The simplest implementation of a function (or subroutine) pointer is as a variable containing the
address of the function within executable memory. Older third-generation languages such as PL/I and
COBOL, as well as more modern languages such as Pascal and C generally implement function
pointers in this manner.

Example

The following C program illustrates the use of two function pointers:

func1 takes one double-precision (double) parameter and returns another double, and is assigned to a
function which converts centimeters to inches.

func2 takes a pointer to a constant character array as well as an integer and returns a pointer to a
character, and is assigned to a C string handling function which returns a pointer to the first occurrence
of a given character in a character array.

#include <stdio.h> /* for printf */

#include <string.h> /* for strchr */

double cm_to_inches(double cm) {

return cm / 2.54;

// "strchr" is part of the C string handling (i.e., no need for declaration)

int main(void) {

double (*func1)(double) = cm_to_inches;

char * (*func2)(const char *, int) = strchr;

printf("%f %s", func1(15.0), func2("Wikipedia", 'p'));

/* prints "5.905512 pedia" */

return 0;

}
The next program uses a function pointer to invoke one of two functions (sin or cos) indirectly from
another function (compute_sum, computing an approximation of the function's Riemann integration).
The program operates by having function main call function compute_sum twice, passing it a pointer
to the library function sin the first time, and a pointer to function cos the second time. Function
compute_sum in turn invokes one of the two functions indirectly by dereferencing its function pointer
argument funcp multiple times, adding together the values that the invoked function returns and
returning the resulting sum. The two sums are written to the standard output by main.

#include <math.h>

#include <stdio.h>

// Function taking a function pointer as an argument

double compute_sum(double (*funcp)(double), double lo, double hi) {

double sum = 0.0;

// Add values returned by the pointed-to function '*funcp'

int i;

for (i = 0; i <= 100; i++) {

// Use the function pointer 'funcp' to invoke the function

double x = i / 100.0 * (hi - lo) + lo;

double y = funcp(x);

sum += y;

return sum / 101.0 * (hi - lo);

double square(double x) {

return x * x;
}

int main(void) {

double sum;

// Use standard library function 'sin()' as the pointed-to function

sum = compute_sum(sin, 0.0, 1.0);

printf("sum(sin): %g\n", sum);

// Use standard library function 'cos()' as the pointed-to function

sum = compute_sum(cos, 0.0, 1.0);

printf("sum(cos): %g\n", sum);

// Use user-defined function 'square()' as the pointed-to function

sum = compute_sum(square, 0.0, 1.0);

printf("sum(square): %g\n", sum);

return 0;

}
TWO MARK QUESTIONS

1. What is Pointer? (Or) Define Pointer. (Or) What is the use of Pointers? (Jan 2014)

Pointer is a variable which contains the memory address of another variable.

The memory address is the location where program instructions and data are stored; pointers can be
used to access and manipulate data stored in the memory.

It is always denoted by ‘*’ operator.

2. Write down the features of pointer.

It is efficient in handling data.

It is used for saving memory space.

It reduces the length and complexity of the program.

It provides dynamic memory allocation.

Two dimensional and multidimensional array representations are easy in pointers.

3. What are the advantages of pointer?

It is more compact and efficient code.

It is used to achieve clarity and simplicity.

It enables us to access the memory directly.

4. How will you declare a pointer?

Pointer is a variable that contains the address of another variable.

Syntax: data_type *pointer-name;

Eg: int *a;

5. What is & and * operator?

& - Address operator

* - Indirection Operator / Dereferencing Operator

6. What is Dereferencing Pointer?

Dereferencing Operation is performed to access or manipulate data contained in memory location


pointed to by a pointer.
Any Operation performed on the de-referenced pointer directly affects the value of variable it points
to.

7. What is indirection operator?

Asterisk (*) indirection operator is used along with pointer variable while dereferencing the pointer
variable.

Asterisk operator is also called as value at operator.

When used with pointer variable, it refers to variable being pointed to; this is called as Dereferencing
of Pointers.

8. What is the difference between the indirection and address operators? (Or) What is an
address operator and indirection operator? (Nov / Dec 2014) (Nov / Dec 2015)

The indirection operator (*) returns the value of the variable stored in a pointer.

The address operator (&) returns the memory address of the variable.

9. What does null pointer mean?

A pointer is said to be a null pointer when its right side value is 0.

A null pointer can never point to a valid data. For checking a pointer, if it is assigned to 0, then it is a
null pointer and is not valid.

10. What is a Character Pointer?

A character pointer can also be used to access character arrays and string constants in the same way as
accessing numeric arrays using their respective pointer variable.

Syntax: char *pointer_character;

11.Define Array of Pointers.

Array notation is a form of relative addressing.

The compiler treats the subscripts as a relative offset from the beginning of the array.

When a pointer variable is set to the start of an array and is incremented to find the next element,
absolute addressing is being implemented.

12. What is Pointer to Pointer?

Here one pointer stores the address of another pointer variable.

Example:
int x=10,*a,**b; a=&x;b=&a;

13. What is Dynamic Memory Allocation? (April / May 2017)

The process of allocating memory at runtime is known as dynamic memory allocation.

Library routines known as "memory management functions" are used for allocating and freeing
memory during execution of a program.

These functions are defined in stdlib.h.

14. What are the various dynamic memory allocation functions? (April / May 2017)

malloc() - Used to allocate blocks of memory in required size of bytes.

free() - Used to release previously allocated memory space.

calloc() - Used to allocate memory space for an array of elements.

realloac() - Used to modify the size of the previously allocated memory space.

15. Difference between Call by Value and Call by Reference. (Or) What is the difference between
pass by value and pass by reference? (May/June 2014)

Call by Value

Values are passed in function call.

This method copies the values of actual parameters into the formal parameters of the function.

Here, the changes to the formal parameter do not affect the actual parameter.

Call by Reference

Address or pointers are passed in function call.

This method copies the addresses of actual parameters into the formal parameters of the function.

Any changes to the formal parameter will affect the actual parameter.

16. How is pointer arithmetic done? (May/June 2016)

Pointers arithmetic is done by adding, subtracting, comparing, incrementing and decrementing the
values assigned to the pointer variables.
UNIT-4 COLLECTIVE DATA TYPES AND FILE HANDLING
4.1 Structure and Union

Structure

• Structure is a collection of data items of different data types which are

grouped together and each element in a C structure is called member.

• A simple structure contains integer, float & character elements, etc.


• A Structure is a collection of different data items that are stored under a

common name

Structure Declaration

The structure can be declared with the keyword struct following the name and
opening braces with data elements of different types, then closing brace with
semicolon.

Syntax
struct structure_name
{
structure element 1;
structure element 2;
…………………….
…………………….
structure element n;
};
struct structure_name v1,v2……vn;
where v1,v2…vn are called as structure variables.

Example
struct Person {
char name[50];
int age;
float salary;
};
Rules for Declaring a Structure
• A structure must end with a semicolon.
• Usually a structure appears at the top of the source program.
• Each structure element must be terminated.
• The members of the structure can be accessed using the structure variables

along with dot (.) operator.

Accessing Structure Elements

After declaring the structure type, variables and members, the member of the
structure can be accessed by using the structure variable along with the dot (.)
operator.

Example
struct std
{
int no;
char name[15]; int marks;

};
struct std s;
We can access the structure members from the above example by,

s.no; s.name; s.marks;

Where ‘s’ is the structure variable.


Initialization of a Structure
Like normal variables, the structure variables can also be initialized, but this
initialization can be made at the compile time.

Example 1
struct
{
int sno; float avg;

} std = {39, 39.11};

This assigns the value 39 to std.sno and 39.11 to std.avg. There is a one-to-one
correspondence between the members and their initializing values.

Example 2
struct std
{
int sno; float avg;

main()
{
struct std person1 = {39, 39.11};
struct std person2 = {17, 17.25};
}
C language does not permit the initialization of individual structure member
within the template. The initialization must be done only in the declaration of the
actual variables.

Rules for Initializing Structure


• The individual data members of structure cannot be initialized.
• The structure variables can be initialized at compile time only.
• The order of data members in a structure must match the order of values in

enclosed brackets.

• The uninitialized data members can be initialized by default with zero (0)

for int and float, ‘\0’ for character and strings.

Structure within Structure (Structure Assignment / Nested Structure)


It is possible to assign one structure information to another structure of same type
using simple assignment statement.

User Defined Data types


C provides a capability that enables the programmer to assign an alternate same
to a data type. This is done with a statement known as typedef.

Syntax

typedef type dataname;

Difference between Array and Structure

Array Structure

 An array is a  Structure is a
collection of similar collection of different
data items of same data items of different
type. type.

 An array is a  It is a user defined


derived data type. data type.
 An array behaves  It must be declared
like a built-in data and defined.
type.

Example Program (Accessing Structure Elements)


#include<stdio.h> #include<conio.h> struct stud

{
int regno;
char name[10]; int m1;

int m2; int m3;

};
struct stud s; void main() { float total,avg;

printf("\nEnter the student regno,name,m1,m2,m3:");


scanf("%d%s%d%d%d",&s.regno,&s.name,&s.m1,&s.m2,&s.m3);
total=s.m1+s.m2+s.m3;

avg=total/3;
printf("\n The student Details are:");
printf("\n %d\t%s\t%f\t%f",s.regno,s.name,total,avg);
}

Output:
Enter the student regno, name, m1, m2, m3:
100
Mani 87

98

78
The student Details are:
100 Mani 263.000000 87.666664

Example
Student Mark Details using Structure
Write a C program to create a mark sheet for students using structure.

#include<stdio.h>

#include<conio.h>

struct stud {

int regno;
char name[10],grade; int m1,m2,m3;

float avg,tot;

} s[10];
void main() { int i,n;

printf("\n Enter the no.of students:"); scanf("%d",&n);

for(i=0;i<n;i++) {
printf("\n Enter the student regno,name,m1,m2,m3:");
scanf("%d%s%d%d%d",&s[i].regno,&s[i].name,&s[i].m1,&s[i].m2,&s[i].m3);

s[i].tot=s[i].m1+s[i].m2+s[i].m3;

s[i].avg=s[i].tot/3; if(s[i].m1<35||s[i].m2<35||s[i].m3<35) s[i].grade='F';

else { if(s[i].avg>=75)

s[i].grade='D';

else if(s[i].avg>=60)
s[i].grade='A';
else if(s[i].avg>=50) s[i].grade='B';

else if(s[i].avg>=35) s[i].grade='C';


}}

printf("\n STUDENT MARK LIST\n");


printf("\n REGNO\tNAME\tTOTAL\tAvg\tGRADE"); for(i=0;i<n;i++)

printf("\n%d\t%s\t%f\t%f\t%c",s[i].regno,s[i].name,s[i].tot,s[i].avg,s[i].grade);
getch();

Output
Enter the no. of students: b2
Enter the student regno, name, m1, m2, m3: 101 Babu

89

98
78
Enter the student regno, name, m1, m2, m3: 102 Mani

59

68
76

STUDENT MARK LIST


REGNO NAME TOTAL Avg GRADE
101 Babu 265.0 88.333336 D
102 Mani 203.0 67.666664 A

Nested Structure
● Nested structure in C is nothing but structure within structure.

● One structure can be declared inside other structure as we declare structure


members inside a structure.

Structure within structure in C using normal variable:


This program explains how to use structure within structure in C using normal
variable. “student_college_detail’ structure is declared inside “student_detail”
structure in this program. Both structure variables are normal structure variables.
Please note that members of “student_college_detail” structure are accessed by 2
dot(.) operator and members of “student_detail” structure are accessed by single
dot(.) operator.
Example
#include <stdio.h> #include <string.h>
struct student_college_detail

{
int college_id;
char college_name[50];

};
struct student_detail
{
int id;

char name[20]; float percentage;


// structure within structure

struct student_college_detail clg_data;


} stu_data;
int main()
{
struct student_detail stu_data = {1, "Raju", 90.5, 71145,

"Anna University"}; printf(" Id is: %d \n", stu_data.id);


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

printf(" Percentage is: %f \n\n", stu_data.percentage);


printf(" College Id is: %d \n",
stu_data.clg_data.college_id);
printf(" College Name is: %s \n", stu_data.clg_data.college_name); return 0;

Output:

Union
Unions are similar to structures but all members share the same memory location.
Only one member can contain a value at any time.

Union provides an efficient way of reusing the memory location, as only one of
its members can be accessed at a time

Union Declaration

union union_name {

datatype member1;

datatype member2;

...
};

Different Ways to Define a Union Variable

We need to define a variable of the union type to start using union members.
There are two methods using which we can define a union variable.
1. With Union Declaration
2. After Union Declaration

Defining Union Variable with Declaration

union union_name {

datatype member1;

datatype member2;

...

} var1, var2, ...;

Defining Union Variable after Declaration

union union_name var1, var2, var3...;

Example of Union

// C Program to demonstrate how to use union

#include <stdio.h>

// union template or declaration


union un {
int member1;
char member2;
float member3;
};

// driver code
int main()
{
// defining a union variable
union un var1;

// initializing the union member


var1.member1 = 15;

printf("The value stored in member1 = %d",


var1.member1);

return 0;
}
Output

The value stored in member1 = 15

4.2 Enumeration
Definition

Enumerations (or enums) are a user-defined type consisting of named integer


constants, which improve code readability.

In C programming, an enumeration type (also called enum) is a data type that


consists of integral constants.

To define enums, the enum keyword is used.

Syntax

enum flag {const1, const2, ..., constN};

By default, const1 is 0,const2 is 1 and so on. You can change default values of
enum elements during declaration

Enumerated Type Declaration

When you define an enum type, the blueprint for the variable is created. Here's
how you can create variables
of enum types.
enum boolean {false, true};
enum boolean check; // declaring an enum variable

Example: Enumeration Type


#include <stdio.h>
enum week {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday,
Saturday};

int main()

{
// creating today variable of enum week type
enum week today;
today = Wednesday;
printf("Day %d",today+1);
return 0;
}

Output

Day 4

4.3 Type defining structure

Typedef
✔ typedef is a keyword used in C language to assign alternative names to
existing datatypes.
✔ Its mostly used with user defined datatypes, when names of the
datatypes become slightly complicated to use in programs.

✔ Following is the general syntax for using typedef, typedef


<existing_name> <alias_name>

Application of typedef
✔ typedef can be used to give a name to user defined data type as well.
✔ Lets see its use with structures.

Example
typedef struct

type member1; type member2; type member3;

} type_name;
Example of Structure definition using typedef

#include<stdio.h>

#include<string.h>

typedef struct employee

char name[50]; int salary;

}emp;

void main( )

emp e1;

printf("\nEnter Employee record:\n"); printf("\nEmployee name:\t");

scanf("%s", e1.name);

printf("\nEnter Employee salary: \t");

scanf("%d", &e1.salary);

printf("\nstudent name is %s", e1.name);

printf("\nroll is %d", e1.salary);

4.4 Structures and Pointers

In C, structures and pointers are fundamental concepts that can be used together
to manage and manipulate complex data efficiently. Understanding how to use
pointers with structures can help you create more dynamic and flexible programs.

Structures in C
A structure (or struct) is a user-defined data type that allows you to group
different types of data under a single name. Here’s a basic example:

#include <stdio.h>

// Define a structure to hold student information

typedef struct {

int id;

char name[50];

float score;

} Student;

int main() {

// Create an instance of Student

Student student1;

// Assign values to the fields

student1.id = 1;

snprintf(student1.name, sizeof(student1.name), "Alice");

student1.score = 95.5;

// Print the student information

printf("ID: %d\n", student1.id);

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

printf("Score: %.2f\n", student1.score);


return 0;

Output:

ID: 1

Name: Alice

Score: 95.50

Pointers to Structures

Pointers to structures are useful for dynamic memory management, passing


structures to functions without copying them, and creating linked data structures.
Example of Using Pointers with Structures
Below is an example that demonstrates how to use pointers with structures:
#include <stdio.h>

#include <stdlib.h>

#include <string.h>

// Define a structure to hold student information

typedef struct {

int id;

char name[50];

float score;

} Student;
// Function to create a new student dynamically

Student* createStudent(int id, const char* name, float score) {

// Allocate memory for a new Student

Student* newStudent = (Student*)malloc(sizeof(Student));

if (newStudent == NULL) {

perror("Error allocating memory");

exit(EXIT_FAILURE);

// Assign values to the fields

newStudent->id = id;

strncpy(newStudent->name, name, sizeof(newStudent->name) - 1);

newStudent->name[sizeof(newStudent->name) - 1] = '\0';

// Ensure null-termination

newStudent->score = score;

return newStudent;

// Function to print student information

void printStudent(const Student* student) {

printf("ID: %d\n", student->id);

printf("Name: %s\n", student->name);

printf("Score: %.2f\n", student->score);


}

int main() {

// Create a student dynamically

Student* student1 = createStudent(1, "Alice", 95.5);

// Print the student information

printStudent(student1);

// Free allocated memory

free(student1);

return 0;

Output

ID: 1

Name: Alice

Score: 95.50

Explanation:
1. Structure Definition:
o typedef struct is used to define a Student structure with id, name, and
score fields.
2. Dynamic Memory Allocation:
o malloc(sizeof(Student)) allocates memory for a Student structure.
o createStudent function initializes the fields of the structure and returns a
pointer to it.

3. Pointer Access:
o The -> operator is used to access fields of the structure through a pointer.
o printStudent function takes a const Student* pointer and prints the
structure's fields.
4. Memory Management:
o After using malloc to allocate memory, it's crucial to free the allocated
memory to avoid memory leaks.

Using Pointers for Arrays of Structures

Here’s an example of how to use pointers to manage an array of structures:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

// Define a structure to hold student information

typedef struct {

int id;

char name[50];

float score;
} Student;

// Function to create an array of students dynamically

Student* createStudentArray(size_t size) {

return (Student*)malloc(size * sizeof(Student));

// Function to print an array of students

void printStudentArray(const Student* students, size_t size) {

for (size_t i = 0; i < size; ++i) {

printf("ID: %d, Name: %s, Score: %.2f\n", students[i].id, students[i].name,


students[i].score);

int main() {

size_t numStudents = 3;

// Create an array of students dynamically

Student* students = createStudentArray(numStudents);

if (students == NULL) {

perror("Error allocating memory");

exit(EXIT_FAILURE);

}
// Initialize the students

students[0] = (Student){1, "Alice", 95.5};

students[1] = (Student){2, "Bob", 88.0};

students[2] = (Student){3, "Charlie", 76.2};

// Print the students

printStudentArray(students, numStudents);

// Free allocated memory

free(students);

return 0;

Output

ID: 1, Name: Alice, Score: 95.50

ID: 2, Name: Bob, Score: 88.00

ID: 3, Name: Charlie, Score: 76.20

Explanation:

1. Structure Definition:
o typedef struct is used to define a Student structure with id, name, and
score fields.
2. Dynamic Memory Allocation:
o malloc(sizeof(Student)) allocates memory for a Student structure.
o createStudent function initializes the fields of the structure and returns a
pointer to it.
3. Pointer Access:
o The -> operator is used to access fields of the structure through a pointer.
o printStudent function takes a const Student* pointer and prints the
structure's fields.
4. Memory Management:
o After using malloc to allocate memory, it's crucial to free the allocated

memory to avoid memory leaks.

Using Pointers for Arrays of Structures

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

// Define a structure to hold student information

typedef struct {

int id;

char name[50];

float score;

} Student;
// Function to create an array of students dynamically

Student* createStudentArray(size_t size) {

return (Student*)malloc(size * sizeof(Student));

// Function to print an array of students

void printStudentArray(const Student* students, size_t size) {

for (size_t i = 0; i < size; ++i) {

printf("ID: %d, Name: %s, Score: %.2f\n", students[i].id, students[i].name,


students[i].score);

int main() {

size_t numStudents = 3;

// Create an array of students dynamically

Student* students = createStudentArray(numStudents);

if (students == NULL) {

perror("Error allocating memory");

exit(EXIT_FAILURE);

}
// Initialize the students

students[0] = (Student){1, "Alice", 95.5};

students[1] = (Student){2, "Bob", 88.0};

students[2] = (Student){3, "Charlie", 76.2};

// Print the students

printStudentArray(students, numStudents);

// Free allocated memory

free(students);

return 0;

Output

ID: 1, Name: Alice, Score: 95.50

ID: 2, Name: Bob, Score: 88.00

ID: 3, Name: Charlie, Score: 76.20

4.5 Self –Referential Structures


Incomplete Declarations


Initializing Structures
Accessing structure member through pointer using dynamic memory
allocation
To access structure member using pointers, memory can be allocated
dynamically using malloc() function defined under "stdlib.h" header file.

Syntax to use malloc()


ptr = (cast-type*) malloc(byte-size)

Example to use structure's member through pointer using malloc()


function.

#include <stdio.h>
#include <stdlib.h>
struct person {
int age;
float weight; char name[30];
};

int main()

{
struct person *ptr; int i, num;

printf("Enter number of persons: "); scanf("%d", &num);

ptr = (struct person*) malloc(num * sizeof(struct person));


// Above statement allocates the memory for n structures with pointer
personPtr pointing to base address */

for(i = 0; i < num; ++i)


{
printf("Enter name, age and weight of the person respectively:\n");
scanf("%s%d%f", &(ptr+i)->name, &(ptr+i)->age, &(ptr+i)->weight);
}

printf("Displaying Infromation:\n"); for(i = 0; i < num; ++i)


printf("%s\t%d\t%.2f\n", (ptr+i)->name, (ptr+i)->age, (ptr+i)->weight);

return 0;
}
Output
Enter number of persons: 2
Enter name, age and weight of the person respectively: Adam
2
3.2
Enter name, age and weight of the person respectively: Eve
6
2.3
Displaying Information: Adam 2 3.20
Eve 6 2.30

4.6 Sequential and Random-Access File Handling


Files:

Introduction to Files:

● A file is a collection of related data that a computers treats as a single

unit.

● A File is a collection of data stored in the secondary memory.

● C uses a structure called FILE (defined in stdio.h) to store the

attributes of a file.

● Files are not only used for storing the data, programs are also stored
in files.
How is a file stored?

Stored as sequence of bytes, logically contiguous. (may not be physically contiguous on


disk).
Why files are needed?
​When a program is terminated, the entire data is lost.
​Storing in a file will preserve your data even if the program terminates.

​If you have to enter a large number of data, it will take a lot of time to enter them all.

​ owever, if you have a file containing all the data, you can easily access the contents of
H
the file using few commands in C.
​You can easily move your data from one computer to another without any changes.

Types of Files

​There are two types of files.

⮚ Text :contains ASCII codes only

⮚ Binary :can contain non-ASCII characters Image, audio, video, executable, etc.

Sequential access:

I​ n computer science, sequential access means that a group of elements (such as data in a
memory array or a disk file or on magnetic tape data storage) is accessed in a
predetermined, ordered sequence.

​Example: JIO
​ equential access is sometimes the only way of accessing the data, for example if it is on
S
a tape.

​It may also be the access method of choice, for example if all that is wanted is to process
a sequence of data elements in order.[1]

I​ n spatial dimension, request size, strided distance, backward accesses, re-accesses can
affect sequentiality.
​ For temporal sequentiality, characteristics such as multi-stream and inter-arrival time
threshold has impact on the definition of sequentiality.

I​ n data structures, a data structure is said to have sequential access if one can only visit
the values it contains in one particular order.

​The canonical example is the linked list.


​Indexing into a list that has sequential access requires O(n) time, where n is the index.

​ s a result, many algorithms such as quicksort and binary search degenerate into bad
A
algorithms that are even less efficient than their naive alternatives; these algorithms are
impractical without random access.

​ n the other hand, some algorithms, typically those that do not have index, require only
O
sequential access, such as mergesort, and face no penalty.

Random-Access File
✔ Individual records of a random-access file are normally fixed in length and may
be accessed directly (and thus quickly) without searching through other records.
✔ Example: facebook

This makes random-access files appropriate for:


​airline reservation systems, banking systems, point-of-sale systems, other kinds of
transaction-processing systems that require rapid access to specific data.
Random-Access File

✔ Fixed-length :records enable data to be inserted in a random-access file without

destroying other data in the file.

✔ Data stored previously can also be updated or deleted without rewriting the entire
file.

Function used in Random Access To File


There is no need to read each record sequentially, if we want to access a particular
record.C supports these functions for random access file processing.

1. fseek()
2. ftell()
3. rewind()
fseek():
This function is used for seeking the pointer position in the file at the specified byte.

Syntax: fseek( file pointer, displacement, pointer position);

Where
file pointer It is the pointer which points to the file.

displacement ---- It is positive or negative.This is the number of bytes which are skipped
backward (if negative) or forward( if positive) from the current position.This is attached
with L because this is a long integer.
Pointer position:
This sets the pointer position in the file.

Value pointer position

0 Beginning of file.

1 Current position
2 End of file
EX:
1) fseek( p,10L,0)
0 means pointer position is on beginning of the file,from this statement pointer position is
skipped 10 bytes from the beginning of the file.

2) fseek( p,5L,1)
1 means current position of the pointer position.From this statement pointer position is
skipped 5 bytes forward from the current position.

3) fseek(p,-5L,1)
From this statement pointer position is skipped 5 bytes backward from the current
position.

ftell()
This function returns the value of the current pointer position in the file.The value is
count from the beginning of the file.

Syntax: ftell(fptr);

Where fptr is a file pointer.


rewind()
This function is used to move the file pointer to the beginning of the given file.
Syntax: rewind( fptr); Where fptr is a file pointer.
Example program for fseek():

Write a program to read last ‘n’ characters of the file using appropriate file
functions(Here we need fseek() and fgetc()).

#include<stdio.h

>

#include<conio.h>

void main()

FILE *fp;

char ch;

clrscr();

fp=fopen("file1.c", "r");

if(fp==NULL)

printf("file cannot be opened");

else

printf("Enter value of n to read last ‘n’ characters");

scanf("%d",&n);

fseek(fp,-n,2);

while((ch=fgetc(fp))!=EOF)

{
printf(“%c\t”, ch);

fclose(fp);

getch();

OUTPUT: It depends on the content in the file.

Example Program: Finding average of numbers stored in sequential access file

#include<stdio.h> int main()


{

int num1, num2, num3, num4, sum, gsize; FILE *inFile;


char fname[30];
printf("Enter a file name: "); gets(fname);

inFile = fopen(fname, "r"); if (inFile == NULL)


{
printf("\nFailed to open file.\n"); exit(1);
}

while (fscanf(inFile, "%d %d %d %d %d %d",

&gsize, &num1, &num2, &num3, &num4) != EOF)


{

printf("Group Size = %d\n num1 = %-12d num2 = %-18d num3 = %-24d num4 = %-
30d %d\n", gsize, num1, num2, num3, num4, sum);

}
fclose(inFile);
}

Output

Enter an input file name: numbers.dat Group Size = 2


i = 1 number = 1 Sum = 1

i = 2 number = 2 Sum = 3

Average = 1.50
Group Size = 3

i = 1 number = 1 Sum = 1
i = 2 number = 2 Sum = 3
i = 3 number = 3 Sum = 6

Average = 2.00

Group Size = 4

i = 1 number = 1 Sum = 1

i = 2 number = 2 Sum = 3

i = 3 number = 3 Sum = 6

i = 4 number = 4 Sum = 10

Average = 2.50

Example: A Transaction-Processing Program

• Instant access for bank accounts

–Use random access file (data in client.dat)


• Give user menu

–Option 1: store accounts to print.txt


–Option 2: update record
Menu options (continued)

–Option 3: add new record

Enter new account number (1 -100): 22 Enter lastname, firstname, balance

? Johnston Sarah 247.45

–Option 4: delete record

Enter account to delete (1-100): 29

Account #29 deleted.

● To open file for reading and writing

–Use fstreamobject

–"Or" file
-open modes together
fstream inOutCredit( "credit.dat", ios::in | ios::out );
4.7 File Handling
4.7.1 Opening and Closing of a File

Open a File in C

For opening a file in C, the fopen() function is used with the filename or file path along
with the required access modes.

Syntax of fopen()

FILE* fopen(const char *file_name, const char *access_mode);


Parameters

● file_name: name of the file when present in the same directory as the source file.
Otherwise, full path.
● access_mode: Specifies for what operation the file is being opened.
Return Value

● If the file is opened successfully, returns a file pointer to it.


● If the file is not opened, then returns NULL.

File opening modes in C

File opening modes or access modes specify the allowed operations on the file to be
opened. They are passed as an argument to the fopen() function. Some of the commonly
used file access modes are listed below:
Example of Opening a File

// C Program to illustrate file opening


#include <stdio.h>
#include <stdlib.h>

int main()
{
// file pointer variable to store the value returned by
// fopen
FILE* fptr;

// opening the file in read mode


fptr = fopen("filename.txt", "r");

// checking if the file is opened successfully


if (fptr == NULL) {
printf("The file is not opened. The program will "
"now exit.");
exit(0);
}
return 0;
}
Output

The file is not opened. The program will now exit.


The file is not opened because it does not exist in the source directory. But the fopen()
function is also capable of creating a file if it does not exist.

Create a File in C
The fopen() function can not only open a file but also can create a file if it does not exist
already. For that, we have to use the modes that allow the creation of a file if not found
such as w, w+, wb, wb+, a, a+, ab, and ab+.

Example:
FILE *fptr;
fptr = fopen("filename.txt", "w");
Example of Opening a File

// C Program to create a file


#include <stdio.h>
#include <stdlib.h>

int main()
{
// file pointer
FILE* fptr;

// creating file using fopen() access mode "w"


fptr = fopen("file.txt", "w");

// checking if the file is created


if (fptr == NULL) {
printf("The file is not opened. The program will exit now");
exit(0);
}
else {
printf("The file is created Successfully.");
}

return 0;
}

Output
The file is created Successfully.

Closing a File
The fclose() function is used to close the file. After successful file operations, you must
always close a file to remove it from the memory.
Syntax of fclose()

Example: Enumeration Type


where the file_pointer is the pointer to the opened file.

Example 1: Program to Create a File, Write in it, And Close the File

// C program to Open a File,


// Write in it, And Close the File
#include <stdio.h>
#include <string.h>
int main()
{
// Declare the file pointer
FILE* filePointer;

// Get the data to be written in file


char dataToBeWritten[50] = "GeeksforGeeks-A Computer "
"Science Portal for Geeks";

// Open the existing file GfgTest.c using fopen()


// in write mode using "w" attribute
filePointer = fopen("GfgTest.c", "w");

// Check if this filePointer is null


// which maybe if the file does not exist
if (filePointer == NULL) {
printf("GfgTest.c file failed to open.");
}
else {

printf("The file is now opened.\n");

// Write the dataToBeWritten into the file


if (strlen(dataToBeWritten) > 0) {
// writing in the file using fputs()
fputs(dataToBeWritten, filePointer);
fputs("\n", filePointer);
}

// Closing the file using fclose()


fclose(filePointer);

printf("Data successfully written in file "


"GfgTest.c\n");
printf("The file is now closed.");
}

return 0;
}

Output
The file is now opened.
Data successfully written in file GfgTest.c
The file is now closed.

4.8 Input and Output Operations on a File


File Operations

Reading from and writing information to a file

For reading and writing to a text file, we use the functions fprintf() and fscanf().
They are just the file versions of printf() and scanf(). The only difference is that fprintf()
and fscanf() expects a pointer to the structure FILE.

Example 1: Write to a text file


#include <stdio.h>
#include <stdlib.h>

int main()
{
int num;
FILE *fptr;

// use appropriate location if you are using MacOS or Linux


fptr = fopen("C:\\program.txt","w");

if(fptr == NULL)
{
printf("Error!");
exit(1);
}
printf("Enter num: ");
scanf("%d",&num);
fprintf(fptr,"%d",num);
fclose(fptr);
return 0;
}
This program takes a number from the user and stores in the file program.txt.

After you compile and run this program, you can see a text file program.txt created in C
drive of your computer. When you open the file, you can see the integer you entered.

Example 2: Read from a text file

#include <stdio.h>
#include <stdlib.h>

int main()
{
int num;
FILE *fptr;

if ((fptr = fopen("C:\\program.txt","r")) == NULL){


printf("Error! opening file");

// Program exits if the file pointer returns NULL.


exit(1);
}

fscanf(fptr,"%d", &num);

printf("Value of n=%d", num);


fclose(fptr);
return 0;
}

This program reads the integer present in the program.txt file and prints it onto the
screen.

If you successfully created the file from Example 1, running this program will get you the
integer you entered.

Other functions like fgetchar(), fputc() etc. can be used in a similar way.

4.9 Handling of Binary files


Binary Files

Handling binary files in C involves using file operations functions provided by the
standard library. Here's a basic overview of how to work with binary files in C:

1. Opening a Binary File: Use fopen() with the "rb" mode for reading or "wb" mode
for writing. For both reading and writing, you can use "r+b" or "w+b" modes.
2. Reading from a Binary File: Use fread() to read data from a file into a buffer.
3. Writing to a Binary File: Use fwrite() to write data from a buffer to a file.
4. Closing a File: Use fclose() to close the file when done.
5. Error Handling: Always check if file operations succeed by checking return
values and using perror() or strerror() for error descriptions.
Here's a simple example program that demonstrates these concepts. This program writes
an array of integers to a binary file and then reads the data back:

#include <stdio.h>
#include <stdlib.h>
// Define a structure to write/read to/from the binary file
typedef struct {
int id;
char name[50];
float score;
} Student;

// Function to write data to a binary file


void writeBinaryFile(const char *filename, Student *students, size_t num_students) {
FILE *file = fopen(filename, "wb"); // Open file for writing in binary mode
if (file == NULL) {
perror("Error opening file for writing");
exit(EXIT_FAILURE);
}

// Write the number of students first


fwrite(&num_students, sizeof(size_t), 1, file);

// Write student data


fwrite(students, sizeof(Student), num_students, file);

fclose(file); // Close the file


}

// Function to read data from a binary file


void readBinaryFile(const char *filename) {
FILE *file = fopen(filename, "rb"); // Open file for reading in binary mode
if (file == NULL) {
perror("Error opening file for reading");
exit(EXIT_FAILURE);
}

size_t num_students;
// Read the number of students first
fread(&num_students, sizeof(size_t), 1, file);

Student *students = (Student *)malloc(num_students * sizeof(Student));


if (students == NULL) {
perror("Error allocating memory");
fclose(file);
exit(EXIT_FAILURE);
}

// Read student data


fread(students, sizeof(Student), num_students, file);

// Display student data


printf("Student Data Read from File:\n");
for (size_t i = 0; i < num_students; ++i) {
printf("ID: %d, Name: %s, Score: %.2f\n", students[i].id, students[i].name,
students[i].score);
}
free(students); // Free allocated memory
fclose(file); // Close the file
}

int main() {
// Example student data
Student students[] = {
{1, "Alice", 95.5},
{2, "Bob", 88.0},
{3, "Charlie", 76.2}
};
size_t num_students = sizeof(students) / sizeof(students[0]);

// Write the student data to a binary file


writeBinaryFile("students.dat", students, num_students);

// Read the student data from the binary file and display it
readBinaryFile("students.dat");

return EXIT_SUCCESS;
}

Output
Student Data Read from File:
ID: 1, Name: Alice, Score: 95.50
ID: 2, Name: Bob, Score: 88.00
ID: 3, Name: Charlie, Score: 76.20

Explanation:

1. Writing Data:
o fopen("data.bin", "wb") opens the file for writing in binary mode.
o fwrite(data, 1, dataSize, writeFile) writes the entire array to the file.
o fclose(writeFile) closes the file after writing.
2. Reading Data:
o fopen("data.bin", "rb") opens the file for reading in binary mode.
o fread(readData, 1, dataSize, readFile) reads the content of the file into
a buffer.
o fclose(readFile) closes the file after reading.
3. Error Handling:
o perror() is used to print a description of the error if an operation fails.
This basic example covers the essentials of handling binary files in C. Depending on
your application, you might need to handle more complex scenarios, such as dynamic
memory allocation, more complex data structures, or file position management.
UNIT-V ADVANCED CONCEPTS AND APPLICATION
DEVELOPMENT
5.1 Bit Fields
Certainly! Let’s explore bit fields in C. These nifty constructs allow you to use
memory efficiently when you know that the value of a field or group of fields will
never exceed a certain limit or is within a small range. We’ll cover the basics, provide
some notes, and include a simple program to illustrate their usage.

What Are Bit Fields?


o Bit fields are variables defined with a predefined width (in bits).
o They allow you to pack multiple fields into a single memory location.
o Useful when storage is limited or when specific values fit within a small range.

Syntax for Declaring Bit Fields:


struct MyStruct {
data_type member_name : width_of_bit_field;
};
o data_type: An integer type (e.g., int, signed int, or unsigned int).
o member_name: Name of the bit field.
o width_of_bit_field: Number of bits allocated to the field.

Applications of Bit Fields:


o Reducing memory consumption.
o Making programs more efficient and flexible.
o Common in device communication and encryption routines.

Example: Optimizing Date Storage


Consider a date structure without bit fields:
struct Date {
unsigned int d;
unsigned int m;
unsigned int y;
};

This takes 12 bytes (3 integers).Now, let’s optimize it using bit fields:

struct DateWithBitField {
int month : 4; // Month has values between 0 and 15, so 4 bits are sufficient.
};

▪ This structure takes less memory.

Interesting Fact:
If you use signed integers for bit fields and the value exceeds the allocated bits,
something intriguing can happen. For example:
struct Date {
int d : 5;
int m : 4;
int y;
};

The output might be negative due to how signed integers represent values.

Simple Program: Printing Date Using Bit Fields


#include <stdio.h>
struct Date {
int day : 5; // 5 bits for day (values 0-31)
int month : 4; // 4 bits for month (values 0-15)
int year; // Regular integer for year
};

void main() {
struct Date dt = { 31, 12, 2014 };
printf("Date: %d/%d/%d\n", dt.day, dt.month, dt.year);
}
Output:
Date: 31/12/2014
Remember, bit fields are like tiny compartments within a structure—each carefully
sized to hold just what’s needed!

5.2 typedef
typedef in C is keyword allows you to create aliases for existing data types, making
your code more readable and flexible

What is Typedef?
o typedef is used to assign alternative names (aliases) to existing data types.
o It’s especially useful for user-defined data types or when existing type names
become cumbersome.

Common Uses of Typedef:


o Giving meaningful names to existing data types.
o Improving code readability.
o Simplifying complex type declarations.

Example 1: Typedef with Structures


o Define an alias for a structure:

#include <stdio.h>
#include <string.h>
typedef struct {
char name[50];
int age;
} Person;

void main() {
Person p1;
strcpy(p1.name, "John");
p1.age = 30;
printf("Name: %s, Age: %d\n", p1.name, p1.age);
}

o Here, Person is an alias for the structure.

Example 2: Typedef with Pointers


o Create an alias for a pointer type:
#include <stdio.h>
typedef int* IntPtr;
void main() {
IntPtr ptr;
int value = 42;
ptr = &value;
printf("Value: %d\n", *ptr);
return 0;
}
o IntPtr is an alias for int*.

Example 3: Typedef with Arrays


o Define an alias for an array:
#include <stdio.h>
typedef int IntArray[5];
void main() {
IntArray arr = { 10, 20, 30, 40, 50 };
printf("Array elements: ");
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
return 0;

}
o IntArray is an alias for an array of 5 integers.

5.3 macro functions


Macro functions in C are like little code snippets that get expanded by the
preprocessor before your program is compiled. They’re handy for creating reusable
code fragments and simplifying complex expressions.

What Are Macro Functions?


o Macro functions are defined using the #define preprocessor directive.
o They allow you to create simple, inline replacements for code snippets.
o Think of them as “textual substitutions” performed by the preprocessor.

Syntax for Defining a Macro Function:


#define MACRO_NAME(parameters) replacement_code
o MACRO_NAME: The name of your macro function.
o parameters: Optional parameters (like function arguments).
o replacement_code: The code snippet to replace the macro call.

Example 1: Square of a Number


o Let’s create a macro function to calculate the square of a number:
#include <stdio.h>
#define SQUARE(x) ((x) * (x))
int main() {
int num = 5;
printf("Square of %d is %d\n", num, SQUARE(num));

return 0;
}
Output:
Square of 5 is 25

Example 2: Maximum of Two Numbers


o Another macro function to find the maximum of two numbers:

#include <stdio.h>
#define MAX(a, b) ((a) > (b) ? (a) : (b))

void main() {
int x = 10, y = 20;
printf("Max of %d and %d is %d\n", x, y, MAX(x, y));
}
Output:
Max of 10 and 20 is 20

Note:
o Be cautious with macro functions—they don’t have type checking.
o Parentheses are crucial to avoid unexpected behavior.

5.4 User Defined Libraries


user-defined libraries are custom libraries created by programmers to organize and
reuse their own functions across multiple programs.

What Are User-Defined Libraries?


User-defined libraries (also called custom libraries) are collections of functions created

by programmers.

They allow you to organize your code, improve modularity, and reuse functions across
different programs.

Creating a User-Defined Library:

To create your own library:


▪ Write your functions in a separate .c file (e.g., mylibrary.c).
▪ Declare function prototypes in a corresponding header file (e.g., mylibrary.h).
▪ Compile the .c file into an object file (e.g., mylibrary.o).
▪ Link the object file with your main program.

Example: Creating a Simple User-Defined Library

Let’s create a custom library with a function to calculate the square of a number:
// mylibrary.h
#ifndef MYLIBRARY_H
#define MYLIBRARY_H

double square(double num);

#endif
// mylibrary.c
#include "mylibrary.h"

double square(double num) {


return num * num;

}
// main.c
#include <stdio.h>
#include "mylibrary.h"

int main() {
double x = 5.0;
printf("Square of %.2f is %.2f\n", x, square(x));
return 0;
}

Compile and link the files:


gcc -c mylibrary.c
gcc main.c mylibrary.o -o myprogram

Output:
Square of 5.00 is 25.00

Note:

• Always include header guards (#ifndef, #define, and #endif) in your header
files to prevent multiple inclusion.
• You can create more complex libraries with additional functions.

5.5 Variable Arguments

Variable arguments in C allows function to accept a variable number of arguments


(parameters) instead of a predefined number. The C programming language provides a
solution for this using variable arguments

What Are Variable Arguments?

o Variable arguments allow a function to accept a varying number of parameters.


o Commonly used in functions like printf and scanf.

Using Variable Arguments: Steps

o Define a function with its last parameter as ellipses (...).


o The parameter just before the ellipses is always an int, representing the total
number of variable arguments.
o Use the stdarg.h header for the necessary functions and macros.

Example: Calculating the Average

Let’s create a function that calculates the average of a variable number of integers:
#include <stdio.h>
#include <stdarg.h>

double average(int num, ...) {


va_list valist;
double sum = 0.0;
int i;

va_start(valist, num); // Initialize valist for num arguments

for (i = 0; i < num; i++) {


sum += va_arg(valist, int); // Access each argument
}

va_end(valist); // Clean up memory reserved for valist


return sum / num;
}

int main() {
printf("Average of 2, 3, 4, 5 = %.6f\n", average(4, 2, 3, 4, 5));
printf("Average of 5, 10, 15 = %.6f\n", average(3, 5, 10, 15));
return 0;
}

Output:
Average of 2, 3, 4, 5 = 3.500000
Average of 5, 10, 15 = 10.000000

Note:

• The function average() has been called twice, each time specifying the total
number of variable arguments.
• Only ellipses (...) are used to pass the variable number of arguments.Remember,
variable arguments are like a flexible toolbox—you can use them to handle different
scenarios!

5.6 Command Line Arguments


Command-line arguments are values passed to a program when it is invoked from the
command line or terminal. These arguments allow users to control program behavior
without modifying the source code. In C, command-line arguments are handled by the
main() function.
Here are the key points about command-line arguments:

Syntax for main():

The main() function can accept two arguments:

• int argc: The number of command-line arguments (including the program


name).
• char* argv[]: An array of strings (character pointers) containing the actual
arguments.

Example Usage:
#include <stdio.h>
int main(int argc, char* argv[]) {
printf("You have entered %d arguments:\n", argc);
for (int i = 0; i < argc; i++) {
printf("%s\n", argv[i]);
}
return 0;
}

Explanation:
The program above prints the total number of arguments (argc) and lists each
argument.
argv[0] contains the program name itself.
The remaining elements (argv[1] to argv[argc-1]) hold the actual command-line
arguments.

Example : Suppose you compile the program and run it with the following command:
$ gcc myprogram.c -o myprogram
$ ./myprogram hello world 123

Output:
You have entered 4 arguments:

./myprogram
hello
world
123

Remember that command-line arguments provide flexibility and allow users to


customize program behavior without recompiling the code.

To find the sum of n numbers whose values are given as command line
parameters?

#include <stdio.h>
#include <stdlib.h>

void main(int argc, char *argv[]) {


int sum = 0;

// Start from index 1 to skip the program name


for (int i = 1; i < argc; ++i) {
int num = atoi(argv[i]); // Convert string to integer
sum += num;
}

printf("Sum of %d numbers: %d\n", argc - 1, sum);

Compile this program (let’s assume you save it as sum_program.c):


gcc -o sum_program sum_program.c

Now run it with some numbers as command line arguments:


./sum_program 10 20 30

The output will be:


Sum of 3 numbers: 60

5.7 Recursive Functions

Recursive functions are like mirrors reflecting themselves—each call creates a smaller
version of the same problem until a base case is reached.

Recursive Functions in C: The Magic of Self-Reflection

What Are Recursive Functions?

o A recursive function is one that calls itself during its execution.


o It’s like a Russian nesting doll—each layer contains a smaller version of itself.

How Recursion Works: The Basics

A recursive function has two parts:

• Base Case: The condition that stops the recursion (otherwise, we’d go forever!).
• Recursive Case: The part where the function calls itself with a modified
argument.

Example: Sum of Natural Numbers

Let’s calculate the sum of the first N natural numbers using recursion:
#include <stdio.h>
int sum(int n) {
if (n == 0) {
return 0; // Base case: sum of 0 numbers is 0
} else {
return n + sum(n - 1); // Recursive case
}
}

void main() {
int number = 5;
printf("Sum of first %d natural numbers = %d\n", number, sum(number));
}
Output:
Sum of first 5 natural numbers = 15

Note:
• In the sum() function, we check if n is 0 (base case) or not.
• If not, we add n to the sum of the first n-1 natural numbers (recursive case).

To find the value of nth factorial using a recursive function.


// Factorial of a given number using Recursion
#include <stdio.h>
void main() {
int n;
printf("Enter a positive integer: ");
scanf("%d", &n);
if ( n >= 0)
printf("Factorial of %d = %d", n, fact(n));
else
printf("PLZ Enter postive integer");
}
// Function to calculate factorial
fact(int n) {
if (n == 0 || n == 1)
return 1;
else
return n * fact(n - 1);
}

OUTPUT:

Enter a positive integer: 5


Factorial of 5 = 120

5.8 Modular programming:

Modular programming in C allows you to break down a large program into smaller,
manageable modules or functions. By doing so, you can improve code organization,
maintainability, and reusability

What Is Modular Programming?

o Modular programming is the process of subdividing a large computer program


into separate sub-programs or modules.
o Each module focuses on a specific aspect of functionality, making the overall
program more organized and easier to maintain.

Advantages of Modular Programming:

o Ease of Use: Instead of dealing with thousands or millions of lines of code at


once, we can work with smaller modules.
o Reusability: Modules can be reused across different programs or projects.
o Ease of Maintenance: Collaboration within a team becomes smoother when
working on smaller, well-defined modules.

Example: Modular Programming in C

o Let’s create a simple example. Suppose we want to calculate the average of a


set of numbers. We’ll break it down into modules:
▪ main.c: The main program that interacts with the user.
▪ average.c: Contains the function to calculate the average.
▪ average.h: The header file with function prototypes.

Program Structure:
main.c:
#include <stdio.h>
#include "average.h"

int main() {
int numbers[] = { 10, 20, 30, 40, 50 };
int count = sizeof(numbers) / sizeof(numbers[0]);
double avg = calculate_average(numbers, count);
printf("Average: %.2f\n", avg);
return 0;
}
average.c:
#include "average.h"
double calculate_average(int arr[], int n) {
double sum = 0.0;
for (int i = 0; i < n; i++) {
sum += arr[i];
}
return sum / n;
}
average.h:
#ifndef AVERAGE_H
#define AVERAGE_H
double calculate_average(int arr[], int n);
#endif

Output:

Average: 30.00

5.9 Package Development.


The term “package” isn’t commonly used in C programming, I assume you’re
interested in creating reusable modules or libraries. These modules can be thought of
as “packages” that encapsulate related functionality. I’ll guide you through a simple
example of creating a basic C program and its output.
Creating a Simple C Program
Let’s start with a classic “Hello, World!” program. This is often the first program
beginners write when learning a new programming language. It’s a great way to get
acquainted with the basics:

#include <stdio.h>
void main() {
printf("Hello, World!\n");
}
Here’s what’s happening in this program:
1. We include the standard input/output library (<stdio.h>), which provides
functions like printf.
2. The main() function is the entry point of our program.
3. Inside main(), we use printf to display the message “Hello, World!” followed by
a newline (\n).
4. Finally, we return 0 to indicate successful execution.
Compile and run this program, and you’ll see the output:
Hello, World!
Understanding the Output
● The printf function is used to print text to the console. In this case, it displays
our friendly greeting.
● The \n character represents a newline, so the cursor moves to the next line after
printing “Hello, World!”.
Going Beyond: Creating Your Own Functions
Now, let’s take a step further and create a custom function. Imagine we want to
calculate the factorial of a given positive integer. We can encapsulate this logic in a
separate function:

#include <stdio.h>
// Function to calculate factorial
unsigned long long factorial(int n) {
if (n == 0 || n == 1)
return 1;
else
return n * factorial(n - 1);
}

int main() {
int num = 5;
printf("Factorial of %d is %llu\n", num, factorial(num));
return 0;
}
Here’s what’s happening now:
1. We define a custom function called factorial that takes an integer argument (n).
2. Inside the function, we use recursion to calculate the factorial.
3. In main(), we call this function with num = 5 and display the result.
Compile and run this program, and you’ll see the output:
Factorial of 5 is 120

To develop simple arithmetic calculator in a modular way and make it as a


package.

We’ll create a header file (.h) and a source file (.c) to achieve this. Here’s an improved
version of the calculator:
1. Calculator.h (Header File):
// Calculator.h

#ifndef CALCULATOR_H
#define CALCULATOR_H

// Function prototypes
double add(double a, double b);
double subtract(double a, double b);
double multiply(double a, double b);
double divide(double a, double b);
#endif // CALCULATOR_H
2. Calculator.c (Source File):
// Calculator.c

#include "Calculator.h"

// Function to add two numbers


double add(double a, double b) {
return a + b;
}

// Function to subtract two numbers


double subtract(double a, double b) {
return a - b;
}

// Function to multiply two numbers


double multiply(double a, double b) {
return a * b;
}

// Function to divide two numbers


double divide(double a, double b) {
if (b != 0) {
return a / b;
} else {
// Handle division by zero
return 0.0;
}
}

3. Main Program:
#include <stdio.h>
#include "Calculator.h"

int main() {
double num1, num2;
char operator;

printf("Enter an operator (+, -, *, /): ");


scanf(" %c", &operator);

printf("Enter two numbers: ");


scanf("%lf %lf", &num1, &num2);

switch (operator) {
case '+':
printf("Result: %.2lf\n", add(num1, num2));
break;
case '-':
printf("Result: %.2lf\n", subtract(num1, num2));
break;
case '*':
printf("Result: %.2lf\n", multiply(num1, num2));
break;
case '/':
printf("Result: %.2lf\n", divide(num1, num2));
break;
default:
printf("Invalid operator!\n");
}

return 0;
}

Now we have a modular structure:


● The Calculator.h header file contains function prototypes.
● The Calculator.c source file defines the actual functions.
● The main program includes the header file and uses the functions.
Compile both Calculator.c and the main program together (e.g., gcc Calculator.c
main.c -o calculator) to create an executable.

OUTPUT :
Enter an operator (+, -, *, /): +
Enter two numbers: 5.5 3.2
Result: 8.70

You might also like