0% found this document useful (0 votes)
58 views114 pages

CDS

The document summarizes some of the fundamental elements of the C programming language, including its character set, identifiers, keywords, data types, constants, arrays, and declarations. It describes the basic building blocks that are used to construct C programs and combine to form more complex program components.

Uploaded by

Sonu Lakra
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
58 views114 pages

CDS

The document summarizes some of the fundamental elements of the C programming language, including its character set, identifiers, keywords, data types, constants, arrays, and declarations. It describes the basic building blocks that are used to construct C programs and combine to form more complex program components.

Uploaded by

Sonu Lakra
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 114

Fundamental of c language:-

The basic elements used to construct a simple C program are:


the C character set, identifiers and keywords, data types,
constants, arrays, declarations , expressions and statements.
Let us see how these elements can be combined to form more
comprehensive program components.
The C Character Set:-
C uses letters A to Z in lowercase and uppercase, the digits 0 to
9, certain special characters, and white spaces to form basic
program elements (e.g variables , constants, expressions etc.)
The special characters are:
+ – */ =%&#!?^”‘/ |<>()[ ] { }:;.,~@!
The white spaces used in C programs are: blank space,
horizontal tab, carriage return, new line and form feed.
Identifiers and Keywords:-
Identifiers are names given to various program elements such
as variables, functions, and arrays. Identifiers consist of letters
and digits, in any order, except that the first character must be
a letter. Both uppercase and lowercase letters are permitted and
the underscore may also be used, as it is also regarded as a
letter. Uppercase and lowercase letters are not equivalent, thus
not interchangeable. This is why it is said that C is case
sensitive. An identifier can be arbitrarily long.
The same identifier may denote different entities in the same
program, for example, a variable and an array may be denoted
by the same identifier, example below.
int sum, average, A[10]; // sum, average and the array
name A are all identifiers.
The _ _func_ _ predefined identifier:-
The predefined identifier __func__ makes a function name
available for use within the function. Immediately following the
opening brace of each function definition, _ _func_ _ is
implicitly declared by the compiler in the following way:
static const char _ _func_ _[] = "function-name";
where function-name is the name of the function.

1
consider the following example
#include <stdio.h>
void func1(void) {
printf("%sn",__func__);
return;
}
int main() {
myfunc();
}
The output would be
func1
Keywords

Keywords are reserved words that have standard predefined


meanings. These keywords can only be used for their intended
purpose; they cannot be used as programmer defined
identifiers. Examples of some keywords are: int, main, void, if.

Data Types

Data values passed in a program may be of different types. Each


of these data types are represented differently within the
computer’s memory and have different memory requirements.
These data types can be augmented by the use of data type
qualifiers/modifiers.

The data types supported in C are described below:

int:

It is used to store an integer quantity. An ordinary int can store


a range of values from INT_MIN to INT_MAX as defined by in
header file <limits.h>. The type modifiers for the int data type
are: signed, unsigned, short, long and long long.

• A short int occupies 2 bytes of space and a long int


occupies 4 bytes.
• A short unsigned int occupies 2 bytes of space but it can
store only positive values in the range of 0 to 65535.

2
• An unsigned int has the same memory requirements as a
short unsigned int. However, in case of an ordinary int, the
leftmost bit is reserved for the sign.
• A long unsigned int occupies 4 bytes of memory and stores
positive integers in the range of 0 to 4294967295.
• By default the int data type is signed.
• A long long int occupies 64 bits of memory. It may be
signed or unsigned. The signed long long int stores values
from −9,223,372,036,854,775,808 to
9,223,372,036,854,775,807 and the unsigned long long
ranges from 0 to 18,446,744,073,709,551,615.

char:

It stores a single character of data belonging to the C character


set. It occupies 1 byte of memory, and stores any value from the
C character set. The type modifiers for char
are signed and unsigned.

Both signed and unsigned char occupy 1 byte of memory but


the range of values differ. An unsigned char can store values
from 0 to 255 and a signed char can store values from -128 to
+127. Each char type has an equivalent integer interpretation,
so that a char is really a special kind of short integer. By default,
char is unsigned.

float:

It is used to store real numbers with single precision i.e. a


precision of 6 digits after decimal point. It occupies 4 bytes of
memory. The type modifier for float is long. It has the same
memory requirements as double.

double:

It is used to store real numbers with double precision. It


occupies 8 bytes of memory. The type modifier for double
is long. A long double occupies 10 bytes of memory.

void:
It is used to specify an empty set containing no values. Hence,
it occupies 0 bytes of memory.

_Bool:
A boolean data type, which is an unsigned integer type, that can

3
store only two values, 0 and 1. Include the
file <stdbool.h> when using _Bool.

_Complex:

It is used to store complex numbers. There are three complex


types: float _Complex, double _Complex, and long double
_ComplexIt is found in the <complex.h> file.

Arrays:

An array is an identifier that refers to a collection of data items


of that have the same name. They must also have the same data
type (i.e. all characters, all integers etc.). Each data item is
represented by its array element. The individual array elements
are distinguished from one another by their subscripts.

Syntax for array declaration:

Suppose arr is a 5 element integer array which stores the


numbers 5, 4, 2, 7, 3 in that order. The first element is referred
to as arr[0]which stores the data value 5, the second element
is arr[1] which stores the value 4 and so on. The last element
is arr[4] which stores the value 3. The subscript assosciated
with each element is shown in square braces. For an n-element
array the subscripts will range from 0 to n-1.

In case of a character array of size n, the array will be able to


store only n-1 elements as a null character is automatically
stored at the end of the string to terminate it. Therefore, a
character array letter that stores 5 elements must be declared
of size 6. The fifth element would be stored
at letter[4] and letter[5] will store the null character.

Constants:

A constant is an identifier whose value remains unchanged


throughout the program. To declare any constant the syntax is:
const datatype varname = value; where const is a keyword that
declares the variable to be a fixed value entity.

There are four basic types of constants inC. They are integer
constants, floating point constants, character constants and
string constants. Integer and floating point constants cannot
contain commas or blank spaces; but they can be prefixed by a
minus sign to indicate a negative quantity.

4
Integer Constants:

An integer constant is an integer valued number. It consists of


a sequence of digits. Integer constants can be written in the
following three number systems:

Decimal(base 10): A decimal constant can consist of any


combination of digits from 0 to 9. If it contains two or more
digits, the first digit must be something other than 0, for
example: const int size =50;

Octal(base 8): An octal constant can consist of any combination


of digits from 0 to 7. The first digit must be a 0 to identify the
constant as an octal number, for example: const int a= 074;
const int b= 0;

Hexadecimal constant(base 16): A hexadecimal constant can


consist of any combination of digits from 0 to 9 and a to f (either
uppercase or lowercase). It must begin with 0x or oX to identify
the constant as a hexadecimal number, for example: const int
c= 0x7FF;

Integer constants can also be prefixed by the type modifiers


unsigned and long. Unsigned constants must end with u or U,
long integer constants must end with lor L and unsigned long
integer constants must end with ul or UL. Long long integer
constants end with LL or ll. Unsigned long long end
with UL or ul

Floating Point Constant:

Its a base 10 or a base 16 number that contains a decimal point


or an exponent or both. In case of a decimal floating point
constant the exponent the base 10 is replaced by e or E. Thus,
1.4 *10^-3 would be written as 1.4E-3 or 1.4e-3.

In case of a hexadecimal character constant, the exponent is in


binary and is replaced by p or P. For example:

const float a= 5000. ;


const float b= .1212e12;
const float c= 827.54;

Floating point constants are generally double precision


quantities that occupy 8 bytes. In some versions of C, the

5
constant is appended by Fto indicate single precision and
by L to indicate a long floating point constant.

Character Constants:

A character constant is a sequence of one or more characters


enclosed in apostrophes. Each character constant has an
equivalent integer value that is determined by the computer’s
character set. It may also contain escape sequences. A character
literal may be prefixed with the letter L, u or U, for example L'c'.

A character literal without the L prefix is an ordinary character


constant or a narrow character constant. A character literal with
the L prefix is a wide character constant. The type of a narrow
character constant and a multicharacter constant is int. The
type of a wide character constant with
prefix L is wchar_t defined in the header file <stddef.h> .A wide
character constant with prefix u or U is of
type char16_t or char32_t. These are unsigned character types
defined in <uchar.h>.

An ordinary character literal that contains more than one


character or escape sequence is a multicharacter constant, for
example: const char p= 'A';

Escape Sequences are also character constants that are used to


express certain non printing characters such as the tab or the
carriage return.An escape sequence always begins with a
backward slash and is followed by one or more special
characters. for eg. b will represent the bell, n will represent the
line feed.

String Literals:

A string literal consists of a sequence of multibyte characters


enclosed in double quotation marks. They are of two types, wide
string literal and UTF-8 string literal. A UTF-8 string literal is
prefixed by u8 and a wide string literal by L, u or U.

The compiler recognizes and supports the additional characters


(the extended character set) which you can meaningfully use in
string literals and character constants. The support for
extended characters includes the multibyte character sets. A

6
multibyte character is a character whose bit representation fits
into one or more bytes.

Symbolic Constants:

A symbolic constant is a name that substitutes for a numeric


constant, a character constant or a string constant throughout
the program. When the program is compiled each occurrence of
a symbolic constant is replaced by its actual value.

A symbolic constant is defined at the beginning of a program


using the # define feature. The # define feature is called a
preprocessor directive, more about the C preprocessor in a later
article.

A symbolic constant definition never ends with a semi colon as


it is not a C statement rather it is a directive, for example:

#define PI 3.1415 //PI is the constant that will represent


value 3.1415
#define True 1
#define name "Alice"

These were the some of the basic elements of C. Elements like


scope of an identifier, declarations, statements, expressions,
etc., will be explained in future articles with the help of practical
examples. The next article will discuss the operators provided
in the C language.

Operators Precedence in C:-


Operator precedence determines the grouping of terms in an
expression and decides how an expression is evaluated. Certain
operators have higher precedence than others; for example, the
multiplication operator has a higher precedence than the
addition operator.
For example, x = 7 + 3 * 2; here, x is assigned 13, not 20 because
operator * has a higher precedence than +, so it first gets
multiplied with 3*2 and then adds into 7.
Here, operators with the highest precedence appear at the top
of the table, those with the lowest appear at the bottom. Within

7
an expression, higher precedence operators will be evaluated
first.

Category Operator Associativity

Postfix () [] -> . ++ - - Left to right

Unary + - ! ~ ++ - - (type)* & sizeof Right to left

Multiplicative * / % Left to right

Additive +- Left to right

Shift << >> Left to right

Relational < <= > >= Left to right

Equality == != Left to right

Bitwise AND & Left to right

Bitwise XOR ^ Left to right

Bitwise OR | Left to right

Logical AND && Left to right

Logical OR || Left to right

Conditional ?: Right to left

Assignment = += -= *= /= %=>>= <<= &= ^= Right to left


|=

Comma , Left to right

Example
Try the following example to understand operator precedence
in C –

8
#include <stdio.h>

main() {

int a = 20;
int b = 10;
int c = 15;
int d = 5;
int e;

e = (a + b) * c / d; // ( 30 * 15 ) / 5
printf("Value of (a + b) * c / d is : %d\n", e );

e = ((a + b) * c) / d; // (30 * 15 ) / 5
printf("Value of ((a + b) * c) / d is : %d\n" , e );

e = (a + b) * (c / d); // (30) * (15/5)


printf("Value of (a + b) * (c / d) is : %d\n", e );

e = a + (b * c) / d; // 20 + (150/5)
printf("Value of a + (b * c) / d is : %d\n" , e );

return 0;
}
When you compile and execute the above program, it produces
the following result −
Value of (a + b) * c / d is : 90
Value of ((a + b) * c) / d is : 90
Value of (a + b) * (c / d) is : 90
Value of a + (b * c) / d is : 50

Input and Output Devices:-


An input/output device, often known as an IO device, is any
hardware that allows a human operator or other systems to
interface with a computer. Input/output devices, as the name
implies, are capable of delivering data (output) to and receiving
data from a computer (input).
An input/output (I/O) device is a piece of hardware that can
take, output, or process data. It receives data as input and
provides it to a computer, as well as sends computer data to
storage media as a storage output.

9
There are many IO Devices available, some of them are:

Input Devices

Keyboard

The keyboard is the most frequent and widely used input


device for entering data into a computer. Although there are
some additional keys for performing other operations, the
keyboard layout is similar to that of a typical typewriter.
Generally, keyboards come in two sizes: 84 keys or 101/102
keys, but currently keyboards with 104 keys or 108 keys are
also available for Windows and the Internet.
Types of Keys
• Numeric Keys: It is used to enter numeric data or move
the cursor. It usually consists of a set of 17 keys.
• Typing Keys: The letter keys (A-Z) and number keys
(09) are among these keys.
• Control Keys: These keys control the pointer and the
screen. There are four directional arrow keys on it.
Home, End, Insert, Alternate(Alt), Delete, Control(Ctrl),
etc., and Escape are all control keys (Esc).
• Special Keys: Enter, Shift, Caps Lock, NumLk, Tab, etc.,
and Print Screen are among the special function keys on
the keyboard.
• Function Keys: The 12 keys from F1 to F12 on the
topmost row of the keyboard.
Mouse
The most common pointing device is the mouse. The mouse is
used to move a little cursor across the screen while clicking
and dragging. The cursor will stop if you let go of the mouse.
The computer is dependent on you to move the mouse; it won’t
move by itself. As a result, it’s an input device.
A mouse is an input device that lets you move the mouse on a
flat surface to control the coordinates and movement of the on-
screen cursor/pointer.
The left mouse button can be used to select or move items,
while the right mouse button when clicked displays extra
menus.

10
Joystick

A joystick is a pointing device that is used to move the cursor


on a computer screen. A spherical ball is attached to both the
bottom and top ends of the stick. In a socket, the lower
spherical ball slides. You can move the joystick in all four
directions.

The joystick’s function is comparable to that of a mouse. It is


primarily used in CAD (Computer-Aided Design) and playing
video games on the computer.
Light Pen
A light pen is a type of pointing device that looks like a pen. It
can be used to select a menu item or to draw on the monitor
screen. A photocell and an optical system are enclosed in a tiny
tube.
When the tip of a light pen is moved across a monitor screen
while the pen button is pushed, the photocell sensor element
identifies the screen location and provides a signal to the CPU.
Scanner
A scanner is an input device that functions similarly to a
photocopier. It’s employed when there’s information on paper
that needs to be transferred to the computer’s hard disc for
subsequent manipulation.
Scanner collects images from the source and converts them to
a digital format that may be saved on a disc. Before they are
printed, these images can be modified.
OCR
OCR stands for optical character recognition, and it is a device
that reads printed text. OCR optically scans the text, character
by character, turns it into a machine-readable code, and saves
it to the system memory.
Bar Code Reader
A bar code reader is a device that reads data that is bar-coded
(data that is represented by light and dark lines).
Bar-coded data is commonly used to mark things, number
books, and so on. It could be a handheld scanner or part of a
stationary scanner.
A bar code reader scans a bar code image, converts it to an
alphanumeric value, and then sends it to the computer to which
it is connected.

11
Web Camera
Because it records a video image of the scene in front of it, a
webcam is an input device. It is either built inside the computer
(for example, a laptop) or attached through a USB connection.
A webcam is a computer-connected tiny digital video camera.
It’s also known as a web camera because it can take images and
record video. These cameras come with software that must be
installed on the computer in order to broadcast video in real-
time over the Internet. It can shoot images and HD videos,
however, the video quality isn’t as good as other cameras (In
Mobiles or other devices or normal cameras).
Output Devices
Monitor
Monitors, also known as Visual Display Units (VDUs), are a
computer’s primary output device. It creates images by
arranging small dots, known as pixels, in a rectangular pattern.
The amount of pixels determines the image’s sharpness.
The two kinds of viewing screen used for monitors are:
(1) Cathode-Ray Tube (CRT): Pixels are minuscule visual
elements that make up a CRT display. The higher the image
quality or resolution, the smaller the pixels.
(2) Flat-Panel Display Cathode-Ray Tube Monitor: In
comparison to the CRT, a flat-panel display is a type of video
display with less volume, weight, and power consumption.
They can be hung on the wall or worn on the wrist.
Flat-panel displays are currently used in calculators, video
games, monitors, laptop computers, and graphical displays.

Printer
Printers are output devices that allow you to print information
on paper.
There are two types of printers:
(a) Impact Printer:
Characters are printed on the ribbon, which is subsequently
crushed against the paper, in impact printers. The following
are the characteristics of impact printers:
• Exceptionally low consumable cost.
• Quite noisy
• Because of its low cost, it is ideal for large-scale
printing.
• To create an image, there is physical contact with the
paper.

12
(b) Non-Impact Printers:
Characters are printed without the need for a ribbon in non-
impact printers. Because these printers print a full page at a
time, they’re also known as Page Printers. The following are the
characteristics of non-impact printers:
• Faster
• They don’t make a lot of noise.
• Excellent quality
• Supports a variety of typefaces and character sizes

Control Structures:-

Control Structures are just a way to specify flow of control in


programs. Any algorithm or program can be more clear and
understood if they use self-contained modules called as logic
or control structures. It basically analyzes and chooses in
which direction a program flows based on certain parameters
or conditions. There are three basic types of logic, or flow of
control, known as:
1. Sequence logic, or sequential flow
2. Selection logic, or conditional flow
3. Iteration logic, or repetitive flow
Let us see them in detail:
1. Sequential Logic (Sequential Flow)
Sequential logic as the name suggests follows a serial
or sequential flow in which the flow depends on the
series of instructions given to the computer. Unless
new instructions are given, the modules are executed in
the obvious sequence. The sequences may be given, by
means of numbered steps explicitly. Also, implicitly
follows the order in which modules are written. Most of
the processing, even some complex problems, will
generally follow this elementary flow pattern.

13
Sequential Control flow

2. Selection Logic (Conditional Flow)


Selection Logic simply involves a number of conditions
or parameters which decides one out of several written
modules. The structures which use these type of logic
are known as Conditional Structures. These structures
can be of three types:
• Single AlternativeThis structure has the form:
• If (condition) then:

• [Module A]
[End of If structure]
Implementation:
• C/C++ if statement with Examples
• Java if statement with Examples
• Double AlternativeThis structure has the form:
• If (Condition), then:
• [Module A]
• Else:
• [Module B]
• [End if structure]
Implementation:
• C/C++ if-else statement with Examples
• Java if-else statement with Examples
• Multiple AlternativesThis structure has the
form:

14
• If (condition A), then:
• [Module A]
• Else if (condition B), then:
• [Module B]
• ..
• ..
• Else if (condition N), then:
• [Module N]
• [End If structure]
Implementation:
• C/C++ if-else if statement with Examples
• Java if-else if statement with Examples
In this way, the flow of the program depends on the set
of conditions that are written. This can be more
understood by the following flow charts:

Double Alternative Control Flow

3. Iteration Logic (Repetitive Flow)


The Iteration logic employs a loop which involves a
repeat statement followed by a module known as the

15
body of a loop.
The two types of these structures are:
• Repeat-For Structure
This structure has the form:
• Repeat for i = A to N by I:

• [Module]
• [End of loop]
Here, A is the initial value, N is the end value
and I is the increment. The loop ends when A>B.
K increases or decreases according to the
positive and negative value of I respectively.

Repeat-For Flow

Implementation:
• C/C++ for loop with Examples
• Java for loop with Examples

16
• Repeat-While Structure
It also uses a condition to control the loop. This
structure has the form:
• Repeat while condition:
• [Module]
• [End of Loop]

Repeat While Flow

Implementation:
• C/C++ while loop with Examples
• Java while loop with Examples
In this, there requires a statement that initializes the
condition controlling the loop, and there must also be
a statement inside the module that will change this
condition leading to the end of the loop.

Decision making and brancing:-


There come situations in real life when we need to make some
decisions and based on these decisions, we decide what should
we do next. Similar situations arise in programming also where
we need to make some decisions and based on these decisions
we will execute the next block of code.
For example, in C if x occurs then execute y else execute z.

17
There can also be multiple conditions like in C if x occurs then
execute p, else if condition y occurs execute q, else execute r.
This condition of C else-if is one of the many ways of importing
multiple conditions. The Decision Making Statements are used
to evaluate the one or more conditions and make the decision
whether to execute set of statement or not.

Decision-making statements in programming languages decide


the direction of the flow of program execution. Decision-
making statements available in C or C++ are:
1. if statement
2. if-else statements
3. nested if statements
4. if-else-if ladder
5. switch statements
6. Jump Statements:
• break
• continue
• goto
• return
1. if statement in C/C++
if statement is the most simple decision-making statement. It
is used to decide whether a certain statement or block of
statements will be executed or not i.e if a certain condition is
true then a block of statement is executed otherwise not.
Syntax:
if(condition)

18
{
// Statements to execute if
// condition is true
}
Here, the condition after evaluation will be either true or false.
C if statement accepts boolean values – if the value is true then
it will execute the block of statements below it otherwise not.
If we do not provide the curly braces ‘{‘ and ‘}’ after
if(condition) then by default if statement will consider the first
immediately below statement to be inside its block.
Example:
If Ram can having 100 GeekBits then he can redeem these
GeekBits and get the GFG T-shirt .
if(condition)
statement1;
statement2;
// Here if the condition is true, if block
// will consider only statement1 to be inside
// its block.
Flowchart

• C
• C++

19
// C program to illustrate If statement
#include <stdio.h>

int main()
{
int i = 10;

if (i > 15) {
printf("10 is greater than 15");
}

printf("I am Not in if");


}

Output:
I am Not in if
As the condition present in the if statement is false. So, the
block below the if statement is not executed.
2. if-else in C/C++
The if statement alone tells us that if a condition is true it will
execute a block of statements and if the condition is false it
won’t. But what if we want to do something else if the condition
is false. Here comes the C else statement. We can use
the else statement with the if statement to execute a block of
code when the condition is false.
Syntax:
if (condition)
{
// Executes this block if
// condition is true
}
else
{
// Executes this block if

20
// condition is false
}
Flowchart:

Example:
The person who having correct 50 Geek Bits is redeem the gifts
otherwise they can’t redeem.

• C
• C++
// C program to illustrate If statement
#include <stdio.h>

21
int main()
{
int i = 20;

if (i < 15) {

printf("i is smaller than 15");


}
else {

printf("i is greater than 15");


}
return 0;
}

Output:
i is greater than 15
The block of code following the else statement is executed as
the condition present in the if statement is false.
3. nested-if in C/C++
A nested if in C is an if statement that is the target of another
if statement. Nested if statements mean an if statement inside
another if statement. Yes, both C and C++ allow us to nested if
statements within if statements, i.e, we can place an if
statement inside another if statement.
Syntax:
if (condition1)
{
// Executes when condition1 is true
if (condition2)
{
// Executes when condition2 is true

22
}
}
Flowchart

Example:

If the person having more than 50 Geek Bits and less than 150
Geek Bits he won the GFG T-shirt.

// C program to illustrate nested-if statement


#include <stdio.h>
int main()
{
int i = 10;
if (i == 10) {
// First if statement

23
if (i < 15)
printf("i is smaller than 15\n");
// Nested - if statement
// Will only be executed if statement above
// is true
if (i < 12)
printf("i is smaller than 12 too\n");
else
printf("i is greater than 15");
}
return 0;
}

Output:
i is smaller than 15
i is smaller than 12 too
4. if-else-if ladder in C/C++
Here, a user can decide among multiple options. The C if
statements are executed from the top down. As soon as one of
the conditions controlling the if is true, the statement
associated with that if is executed, and the rest of the C else-if
ladder is bypassed. If none of the conditions is true, then the
final else statement will be executed. if-else-if ladder is similar
to switch statement.
Syntax:
if (condition)
statement;
else if (condition)
statement;
else
statement;

24
Example:
If the person having the 50 Geek Bits then he get the GfG Course
Coupon otherwise he will having 100 Geek Bits then he get
the GfG T-shirt otherwise he will having the 200 Geek Bits then
he get the GfG Bag otherwise he will having less than 50 he
cant get anything.

• C
• C++

25
// C program to illustrate nested-if statement
#include <stdio.h>

int main()
{
int i = 20;

if (i == 10)
printf("i is 10");
else if (i == 15)
printf("i is 15");
else if (i == 20)
printf("i is 20");
else
printf("i is not present");
}

Output:
i is 20
5. Jump Statements in C/C++
These statements are used in C or C++ for the unconditional
flow of control throughout the functions in a program. They
support four types of jump statements:
A) break
This loop control statement is used to terminate the loop. As
soon as the break statement is encountered from within a loop,
the loop iterations stop there, and control returns from the
loop immediately to the first statement after the loop.
Syntax:
break;
Basically, break statements are used in situations when we are
not sure about the actual number of iterations for the loop or
we want to terminate the loop based on some condition.

26
Example:

• C
• C++
// C program to illustrate
// to show usage of break
// statement
#include <stdio.h>

void findElement(int arr[], int size, int key)


{
// loop to traverse array and search for key
for (int i = 0; i < size; i++) {
if (arr[i] == key) {
printf("Element found at position: %d",
(i + 1));
break;
}

27
}
}

int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6 };

// no of elements
int n = 6;

// key to be searched
int key = 3;

// Calling function to find the key


findElement(arr, n, key);

return 0;
}

Output:
Element found at position: 3
B) continue
This loop control statement is just like the break statement.
The continue statement is opposite to that of the
break statement, instead of terminating the loop, it forces to
execute the next iteration of the loop.
As the name suggests the continue statement forces the loop
to continue or execute the next iteration. When the continue
statement is executed in the loop, the code inside the loop
following the continue statement will be skipped and the next
iteration of the loop will begin.
Syntax:
continue;

28
Example:
• C
• C++
// C program to explain the use
// of continue statement
#include <stdio.h>

int main()
{
// loop from 1 to 10
for (int i = 1; i <= 10; i++) {

// If i is equals to 6,
// continue to next iteration

29
// without printing
if (i == 6)
continue;

else
// otherwise print the value of i
printf("%d ", i);
}

return 0;
}

Output:
1 2 3 4 5 7 8 9 10
If you create a variable in if-else in C/C++, it will be local to
that if/else block only. You can use global variables inside the
if/else block. If the name of the variable you created in if/else
is as same as any global variable then priority will be given to
`local variable`.

• C
• C++
#include <stdio.h>

int main()
{

int gfg = 0; // local variable for main


printf("Before if-else block %d\n", gfg);
if (1) {
int gfg = 100; // new local variable of if block
printf("if block %d\n", gfg);

30
}
printf("After if block %d", gfg);
return 0;
}

Output:
Before if-else block 0
if block 100
After if block 0
C) goto
The goto statement in C/C++ also referred to as the
unconditional jump statement can be used to jump from one
point to another within a function.
Syntax:
Syntax1 | Syntax2
----------------------------
goto label; | label:
. | .
. | .
. | .
label: | goto label;
In the above syntax, the first line tells the compiler to go to or
jump to the statement marked as a label. Here, a label is a user-
defined identifier that indicates the target statement. The
statement immediately followed after ‘label:’ is the destination
statement. The ‘label:’ can also appear before the ‘goto label;’
statement in the above syntax.

31
Examples:
• C
• C++
// C program to print numbers
// from 1 to 10 using goto
// statement
#include <stdio.h>

// function to print numbers from 1 to 10


void printNumbers()
{
int n = 1;
label:
printf("%d ", n);

32
n++;
if (n <= 10)
goto label;
}

// Driver program to test above function


int main()
{
printNumbers();
return 0;
}

Output:
1 2 3 4 5 6 7 8 9 10
D) return
The return in C or C++ returns the flow of the execution to the
function from where it is called. This statement does not
mandatorily need any conditional statements. As soon as the
statement is executed, the flow of the program stops
immediately and returns the control from where it was called.
The return statement may or may not return anything for a void
function, but for a non-void function, a return value must be
returned.
Syntax:
return[expression];
Example:
• C
• C++
// C code to illustrate return
// statement
#include <stdio.h>

// non-void return type

33
// function to calculate sum
int SUM(int a, int b)
{
int s1 = a + b;
return s1;
}

// returns void
// function to print
void Print(int s2)
{
printf("The sum is %d", s2);
return;
}

int main()
{
int num1 = 10;
int num2 = 10;
int sum_of = SUM(num1, num2);
Print(sum_of);
return 0;
}

Output:
The sum is 20

Monolithic programming
If, we write an entire program in a single function that is in main
function then, you call it as a monolithic type of programming.
But, it is not a good style of writing entire logic in a single
function.

34
Disadvantages
The disadvantages of monolithic programming include −
• Program seems to be very large and complex.
• Debugging, testing and maintenance of a program is
very difficult.
Modular Programming
If the program is divided into number of functional parts, then
we use to call it as modular programming.
If the main program is divided into sub programs, then we can
independently code each sub module later combine into single
unit. This type of individual modules is termed as functions.
Advantages
The advantages of modular programming include −
•It is easy to understand the program.
• Debugging and maintenance becomes easy.
• Saves programmers or user’s time.
• Reuse the code where ever necessary.
Example of modular programming
An example of modular programming is given below −

The splitting of a problem into its related sub problems is


analogous to the process of refining an algorithm.

User defined vs standard function:-


User-defined function: These functions are designed by the
user when they are writing any program because for every task
we do not have a library of functions where their definitions
are predefined. To perform the according to the requirement
of user the user have to develop some functions by itself, these
functions are called user-defined functions. For such
functions the user have to define the proper definition of the
function.

35
For Example: If we want to perform the addition of two
numbers then below is the program to illustrate the addition of
two numbers using user-defined functions:
• C
• C++

// C program to illustrate user-defined function


#include <stdio.h>

// Function Call to find the sum of a and b


void findSum(int a, int b)
{

// Print the sum


printf("Sum is: %d", a + b);
}

// Driver Code
int main()
{
// Given two numbers
int a = 3, b = 5;

// Function Call
findSum(a, b);
return 0;
}
Output:
Sum is: 8

Library function: These function are the built-in


functions i.e., they are predefined in the library of the C.
These are used to perform the most common operations like
calculations, updation, etc. Some of the library functions
are printf, scanf, sqrt, etc. To use this functions in the
program the user have to use associate header file associated
to the corresponding function in the program.
For Example: If, the user have to use print the data or scan the
data using input stream then we have to use
functions printf() and scanf() in C program and cin and cout in
C++ program. To use these functions the user have to
include #include<stdio.h> preprocessor directive in C

36
program and #include<iostream> preprocessor directive
in C++ program.
• C
• C++

// C program to illustrate inbuilt function


#include <stdio.h>

// Driver Code
int main()
{

// Print Statement
printf("GeeksforGeeks!");

return 0;
}
Output: GeeksforGeeks!
User-defined Library Functions
Functions
These functions are These functions are predefined in
not predefined in the the compiler of C language.
Compiler.
These function are These functions are not created by
created by user as per user as their own.
their own requirement.
User-defined functions Library Functions are stored in
are not stored in special library file.
library file.
There is no such kind In this if the user wants to use a
of requirement to add particular library function then the
the particular library. user have to add the particular
library of that function in header file
of the program.
Execution of the Execution of the program does not
program begins from begin from the library function.
the user-define
function.
Example: sum(), Example: printf(), scanf(),
fact(),…etc. sqrt(),…etc.

37
Difference Between Actual and Formal Parameters:-

The difference Between Actual and Formal Parameters is that


the actual parameter is used to invoke or pass the information
while executing the program. In contrast, formal parameters are
declared while calling the function. Actual and Formal
Parameters are an important part of a program.

It is always important to define the purpose of the parameter in


a program. Let us know more about the difference between
actual and formal parameters in the coming sections, along with
Actual Parameters Formal Parameters
Defined when it is Defined when the function is called.
invoked.
Passed on calling a They will be in the called function.
function
Data types will not be The data type must be included.
mentioned.
They are written in the They are written in the function
function call. definition.
They may be constant They can be local variables
values.
knowing what is actual and formal parameters.

The major difference between actual and formal parameters is


that formal parameters are defined when the function is called,
whereas actual parameters are defined when the function is
invoked.

Key Differences Between Actual and Formal Parameters


What are the Actual Parameters?

An actual parameter is the value of a function that is passed


when the function is being invoked. The caller will assign the
actual value. It is a parameter that is determined while inviting
a subroutine.

Example of Actual Parameters

#include <stdio.h>

void multiplication (int x, int y) {

int multiplication;

38
addition = x*y;

printf(“%d”,multiplication);

void main () {

multiplication (2,3);

multiplication (4,5);

What are the Formal Parameters?

Let us learn about the formal parameters. A formal parameter is


defined while determining the subroutine. Formal parameters
are also used in the header of the function.

The syntax of the formal parameters is:

<return type> <method name> (formal parameters) {

//set of statements to be executed

Function category:-
Depending on whether arguments are present or not and
whether a value is returned or not, functions are categorized
into −
• Functions without arguments and without return
values
• Functions without arguments and with return values
• Functions with arguments and without return values
• Functions with arguments and with return values

39
Functions without arguments and without return values

Example
#include<stdio.h>
main (){
void sum ();
clrscr ();
sum ();
getch ();
}
void sum (){
int a,b,c;
printf("enter 2 numbers:
");
scanf ("%d%d", &a, &b);
c = a+b;
printf("sum = %d",c);
}
Output
Enter 2 numbers:
3
5
Sum=8

40
Functions without arguments and with return values

Example
#include<stdio.h>
main (){
int sum ();
int c;
c= sum ();
printf(“sum = %d”,c);
getch ();
}
int sum (){
int a,b,c;
printf(“enter 2 numbers”);
scanf (“%d%d”, &a, &b);
c = a+b;
return c;
}
Output
Enter two numbers 10 20
30

41
Functions with arguments and without return values

Example
#include<stdio.h>
main (){
void sum (int, int );
int a,b;
printf("enter 2 numbers");
scanf("%d%d", &a,&b);
sum (a,b);
getch ();
}
void sum ( int a, int b){
int c;
c= a+b;
printf (“sum=%d”, c);
}
Output
Enter two numbers 10 20
Sum=30

42
Functions with arguments and with return values

Example
#include<stdio.h>
main (){
int sum ( int,int);
int a,b,c;
printf("enter 2 numbers");
scanf("%d%d", &a,&b);
c= sum (a,b);
printf ("sum=%d", c);
getch ();
}
int sum ( int a, int b ){
int c;
c= a+b;
return c;
}
Output
Enter two numbers 10 20
Sum=30

function prototype:-

43
Function prototype tells the compiler about a number of
parameters function takes data-types of parameters, and return
type of function. By using this information, the compiler cross-
checks function parameters and their data type with function
definition and function call. If we ignore the function
prototype, a program may compile with a warning and may
work properly. But sometimes, it will give strange output and
it is very hard to find such programming mistakes. Let us see
with examples

• C

#include <errno.h>
#include <stdio.h>

int main(int argc, char *argv[])


{
FILE *fp;

fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "%s\n", strerror(errno));
return errno;
}

printf("file exist\n");

fclose(fp);

return 0;
}
The above program checks the existence of a file, provided
from the command line, if a given file exists, then the program
prints “file exists”, otherwise it prints an appropriate error
message. Let us provide a filename, which does not exist in a
file system, and check the output of the program on x86_64
architecture.

[narendra@/media/partition/GFG]$ ./file_existence hello.c


Segmentation fault (core dumped)

44
Why this program crashed, instead it should show an
appropriate error message. This program will work fine on x86
architecture but will crash on x86_64 architecture. Let us see
what was wrong with the code. Carefully go through the
program, deliberately I haven’t included the prototype of the
“strerror()” function. This function returns “pointer to the
character”, which will print an error message which depends
on errno passed to this function. Note that x86 architecture is
an ILP-32 model, which means integer, pointers and long are
32-bit wide, that’s why the program will work correctly on this
architecture. But x86_64 is the LP-64 model, which means long
and pointers are 64 bit wide. In C language, when we don’t
provide a prototype of a function, the compiler assumes that
function returns an integer. In our example, we haven’t
included the “string.h” header file (strerror’s prototype is
declared in this file), that’s why the compiler assumed that
function returns an integer. But its return type is a pointer to a
character. In x86_64, pointers are 64-bit wide and integers are
32-bits wide, that’s why while returning from a function, the
returned address gets truncated (i.e. 32-bit wide address,
which is the size of integer on x86_64) which is invalid and
when we try to dereference this address, the result is a
segmentation fault.
Now include the “string.h” header file and check the output,
the program will work correctly.

[narendra@/media/partition/GFG]$ ./file_existence hello.c


No such file or directory

Parameter Passing Techniques in C:-

There are different ways in which parameter data can be passed


into and out of methods and functions. Let us assume that a
function B() is called from another function A(). In this case A is
called the “caller function” and B is called the “called
function or callee function”. Also, the arguments
which A sends to B are called actual arguments and the
parameters of B are called formal arguments.
Terminology
• Formal Parameter : A variable and its type as they
appear in the prototype of the function or method.
• Actual Parameter : The variable or expression
corresponding to a formal parameter that appears in
the function or method call in the calling environment.

45
• Modes:
IN: Passes info from caller to callee.

• OUT: Callee writes values in caller.
• IN/OUT: Caller tells callee value of variable,
which may be updated by callee.
Important methods of Parameter Passing
1. Pass By Value: This method uses in-mode semantics.
Changes made to formal parameter do not get
transmitted back to the caller. Any modifications to the
formal parameter variable inside the called function or
method affect only the separate storage location and
will not be reflected in the actual parameter in the
calling environment. This method is also called as call
by value.
o C
o CPP

// C program to illustrate
// call by value
#include <stdio.h>

void func(int a, int b)


{
a += b;
printf("In func, a = %d b = %d\n", a, b);
}
int main(void)
{
int x = 5, y = 7;

// Passing parameters
func(x, y);
printf("In main, x = %d y = %d\n", x, y);
return 0;
}
Output:
In func, a = 12 b = 7
In main, x = 5 y = 7
Languages like C, C++, Java support this type of
parameter passing. Java in fact is strictly call by value.
Shortcomings:
o Inefficiency in storage allocation

46
o For objects and arrays, the copy semantics are
costly
2. Pass by reference(aliasing): This technique
uses in/out-mode semantics. Changes made to formal
parameter do get transmitted back to the caller through
parameter passing. Any changes to the formal
parameter are reflected in the actual parameter in the
calling environment as formal parameter receives a
reference (or pointer) to the actual data. This method is
also called as call by reference. This method is
efficient in both time and space.
o C
o CPP

// C program to illustrate
// call by reference
#include <stdio.h>

void swapnum(int* i, int* j)


{
int temp = *i;
*i = *j;
*j = temp;
}

int main(void)
{
int a = 10, b = 20;

// passing parameters
swapnum(&a, &b);

printf("a is %d and b is %d\n", a, b);


return 0;
}
Output:
a is 20 and b is 10
C and C++ both support call by value as well as call by
reference whereas Java doesn’t support call by
reference.
Shortcomings:
o Many potential scenarios can occur

47
oPrograms are difficult to understand sometimes
Other methods of Parameter Passing
These techniques are older and were used in earlier
programming languages like Pascal, Algol and Fortran. These
techniques are not applicable in high level languages.
1. Pass by Result:This method uses out-mode semantics.
Just before control is transferred back to the caller, the
value of the formal parameter is transmitted back to the
actual parameter. This method is sometimes called call
by result. In general, pass by result technique is
implemented by copy.
2. Pass by Value-Result: This method uses in/out-
mode semantics. It is a combination of Pass-by-Value
and Pass-by-result. Just before the control is
transferred back to the caller, the value of the formal
parameter is transmitted back to the actual parameter.
This method is sometimes called as call by value-result
3. Pass by name : This technique is used in programming
language such as Algol. In this technique, symbolic
“name” of a variable is passed, which allows it both to
be accessed and update.
Example:
To double the value of C[j], you can pass its name (not
its value) into the following procedure.
4. procedure double(x);
5. real x;
6. begin
7. x:=x*2
8. end;
In general, the effect of pass-by-name is to textually
substitute the argument in a procedure call for the
corresponding parameter in the body of the procedure.
Implications of Pass-by-Name mechanism:
• The argument expression is re-evaluated each
time the formal parameter is passed.
• The procedure can change the values of
variables used in the argument expression and
hence change the expression’s value.

Recursion:-

48
Recursion is the process of repeating items in a self-similar way.
In programming languages, if a program allows you to call a
function inside the same function, then it is called a recursive
call of the function.
void recursion() {
recursion(); /* function calls itself */
}

int main() {
recursion();
}
The C programming language supports recursion, i.e., a
function to call itself. But while using recursion, programmers
need to be careful to define an exit condition from the function,
otherwise it will go into an infinite loop.
Recursive functions are very useful to solve many mathematical
problems, such as calculating the factorial of a number,
generating Fibonacci series, etc.
Number Factorial
The following example calculates the factorial of a given
number using a recursive function −
#include <stdio.h>

unsigned long long int factorial(unsigned int i) {

if(i <= 1) {
return 1;
}
return i * factorial(i - 1);
}

int main() {
int i = 12;
printf("Factorial of %d is %d\n", i, factorial(i));
return 0;
}
When the above code is compiled and executed, it produces the
following result −
Factorial of 12 is 479001600

49
Fibonacci Series
The following example generates the Fibonacci series for a given
number using a recursive function −
#include <stdio.h>

int fibonacci(int i) {

if(i == 0) {
return 0;
}

if(i == 1) {
return 1;
}
return fibonacci(i-1) + fibonacci(i-2);
}

int main() {

int i;

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


printf("%d\t\n", fibonacci(i));
}

return 0;
}
When the above code is compiled and executed, it produces the
following result −
0
1
1
2
3
5
8
13
21
34

Storage Classes:-
Storage Classes are used to describe the features of a
variable/function. These features basically include the scope,

50
visibility and life-time which help us to trace the existence of a
particular variable during the runtime of a program.
C language uses 4 storage classes, namely:

1. auto: This is the default storage class for all the


variables declared inside a function or a block. Hence,
the keyword auto is rarely used while writing programs
in C language. Auto variables can be only accessed
within the block/function they have been declared and
not outside them (which defines their scope). Of course,
these can be accessed within nested blocks within the
parent block/function in which the auto variable was
declared. However, they can be accessed outside their
scope as well using the concept of pointers given here
by pointing to the very exact memory location where
the variables reside. They are assigned a garbage value
by default whenever they are declared.

2. extern: Extern storage class simply tells us that the


variable is defined elsewhere and not within the same
block where it is used. Basically, the value is assigned
to it in a different block and this can be
overwritten/changed in a different block as well. So an
extern variable is nothing but a global variable
initialized with a legal value where it is declared in
order to be used elsewhere. It can be accessed within
any function/block. Also, a normal global variable can
be made extern as well by placing the ‘extern’ keyword
before its declaration/definition in any function/block.
This basically signifies that we are not initializing a new
variable but instead we are using/accessing the global
variable only. The main purpose of using extern
variables is that they can be accessed between two
different files which are part of a large program. For
more information on how extern variables work, have a
look at this link.

3. static: This storage class is used to declare static


variables which are popularly used while writing
programs in C language. Static variables have the
property of preserving their value even after they are
out of their scope! Hence, static variables preserve the
value of their last use in their scope. So we can say that
they are initialized only once and exist till the

51
termination of the program. Thus, no new memory is
allocated because they are not re-declared. Their scope
is local to the function to which they were defined.
Global static variables can be accessed anywhere in the
program. By default, they are assigned the value 0 by
the compiler.

4. register: This storage class declares register variables


that have the same functionality as that of the auto
variables. The only difference is that the compiler tries
to store these variables in the register of the
microprocessor if a free register is available. This
makes the use of register variables to be much faster
than that of the variables stored in the memory during
the runtime of the program. If a free registration is not
available, these are then stored in the memory only.
Usually few variables which are to be accessed very
frequently in a program are declared with the register
keyword which improves the running time of the
program. An important and interesting point to be
noted here is that we cannot obtain the address of a
register variable using pointers.

C auto:-

For backward compatibility.The predecessors of C used


the auto to declare variables. Back in the days there was a lot
of code that had to be ported to the new C language. Adding
the keyword to the language was of help in that case.

In the language C auto is a keyword for specifying a storage


duration. When you create an auto variable it has an “automatic
storage duration”. We call these objects “local variables”. In C,
all variables in functions are local by default. That’s why the
keyword auto is hardly ever used.

First code example

The two variables “count” and “count2” have automatic storage


duration. In other words, they will exist until the program
execution reaches the closing bracket of the block where they
were defined. In this case they will exist until we reach the end
of the function.

1 void some_function()

52
2{
3 auto int count = 0;
4 int count2 = 0;
5}

Block visibility with auto

While we are on the subject, let’s take another look at “block


lifetime” variable.

1 int main()
2 {
3 auto int number = 5;
4 {
5 auto int number = 20;
6 printf("inner number: %d", number);
7 }
8 printf("\n");
9 printf("outer number: %d", number);
10 return 0;
11 }

inner number: 20

outer number: 5
extern:-

Basically, the extern keyword extends the visibility of the C


variables and C functions. That’s probably the reason why it
was named extern.
Though most people probably understand the difference
between the “declaration” and the “definition” of a variable or
function, for the sake of completeness, I would like to clarify
them.
• Declaration of a variable or function simply declares
that the variable or function exists somewhere in the
program, but the memory is not allocated for them. The
declaration of a variable or function serves an
important role–it tells the program what its type is
going to be. In case of function declarations, it also tells
the program the arguments, their data types, the order
of those arguments, and the return type of the function.
So that’s all about the declaration.

53
• Coming to the definition, when we define a variable or
function, in addition to everything that a declaration
does, it also allocates memory for that variable or
function. Therefore, we can think of definition as a
superset of the declaration (or declaration as a subset
of definition).
• Extern is a short name for external.
• used when a particular files need to access a variable
from another file.
• C

#include <stdio.h>

extern int a; // int var; -> declaration and definition


// extern int var; -> declaration

int main()
{
printf("%d", a);

return 0;
}
When
• we write extern some_data_type
some_variable_name; no memory is allocated. Only
property of variable is announced.
• Multiple declarations of extern variable is allowed
within the file. This is not the case with automatic
variables.
• Extern variable says to compiler ” go outside my scope
and you will find the definition of the variable that I
declared.”
• Compiler believes that whatever that extern variable
said is true and produce no error. Linker throws an
error when it finds no such variable exists.
• When an extern variable is initialized, then memory for
this is allocated and it will be considered defined.
A variable or function can be declared any number of times,
but it can be defined only once. (Remember the basic principle
that you can’t have two locations of the same variable or
function).
Now back to the extern keyword. First, Let’s consider the use
of extern in functions. It turns out that when a function is

54
declared or defined, the extern keyword is implicitly assumed.
When we write.
int foo(int arg1, char arg2);
The compiler treats it as:
extern int foo(int arg1, char arg2);
Since the extern keyword extends the function’s visibility to
the whole program, the function can be used (called) anywhere
in any of the files of the whole program, provided those files
contain a declaration of the function. (With the declaration of
the function in place, the compiler knows the definition of the
function exists somewhere else and it goes ahead and compiles
the file). So that’s all about extern and functions.
Example 2:
• c

extern int var = 0;


int main(void)
{
var = 10;
return 0;
}

1. A declaration can be done any number of times but


defined only once.
2. the extern keyword is used to extend the visibility of
variables/functions.
3. Since functions are visible throughout the program by
default, the use of extern is not needed in function
declarations or definitions. Its use is implicit.
4. When extern is used with a variable, it’s only declared,
not defined.
5. As an exception, when an extern variable is declared
with initialization, it is taken as the definition of the
variable as well.

Global:-
The variables that are declared outside the given function are
known as global variables. These do not stay limited to a
specific function- which means that one can use any given
function to not only access but also modify the global variables.
The initialization of these variables occurs automatically to 0

55
during the time of declaration. Also, we generally write the
global variables before the main() function.

The global variables get defined outside any function- usually


at the very top of a program. After this, the variables hold their
actual values throughout the lifetime of that program, and one
can access them inside any function that gets defined for that
program.
As already stated earlier, any function can access a global
variable. It means that once you declare a program, its global
variable will be available for use throughout the running of the
entire program.

Example of Global Variable in C


Here is a program that shows how we use global variables
practically:
#include<stdio.h>
void func_a();
void func_b();
int x, y = 10; // declaration and initialization of global variables
here
int main()
{
printf(“The Global x is = %d\n”, x);
printf(“The Global y is = %d\n\n”, y);
func_a();
func_b();
// a signal to the operating system that the program ran fine
here
return 0;
}
void func_a()
{
printf(“From the func_a() the Global x is = %d\n”, x);
printf(“From the func_a() the Global y is = %d\n\n”, y);

56
}
void func_b()
{
int x = 5;
printf(“Inside the func_b() x is = %d\n”, x);
}
Output
The output obtained here will be:
The Global x is = 0
The Global y is = 10
From the func_a() the Global x is = 0
From the func_a() the Global y is = 10
Inside the func_b() x is = 5

Static functions in C:-


A static function in C is a function that has a scope that is
limited to its object file. This means that the static function is
only visible in its object file. A function can be declared as static
function by placing the static keyword before the function
name.
An example that demonstrates this is given as follows −
There are two files first_file.c and second_file.c. The contents
of these files are given as follows −
Contents of first_file.c
static void staticFunc(void)
{
printf("Inside the static function staticFunc() ");
}
Contents of second_file.c
int main()
{
staticFunc();
return 0;

57
}
Now, if the above code is compiled then an error is obtained i.e
“undefined reference to staticFunc()”. This happens as the
function staticFunc() is a static function and it is only visible in
its object file.
A program that demonstrates static functions in C is given as
follows −
Example
#include <stdio.h>

static void staticFunc(void){


printf("Inside the static function staticFunc() ");
}

int main()
{
staticFunc();
return 0;
}
Output
The output of the above program is as follows −
Inside the static function staticFunc()
In the above program, the function staticFunc() is a static
function that prints ”Inside the static function staticFunc()”.
The main() function calls staticFunc(). This program works
correctly as the static function is called only from its own
object file

Character handling in c:-


All data is entered into computers as characters, which includes
letters, digits and various special symbols. In this section, we
discuss the capabilities of C++ for examining and manipulating
individual characters.
The character-handling library includes several functions that
perform useful tests and manipulations of character data. Each
function receives a character, represented as an int, or EOF as
an argument. Characters are often manipulated as integers.

58
Remember that EOF normally has the value –1 and that some
hardware architectures do not allow negative values to be stored
in char variables. Therefore, the character-handling functions
manipulate characters as integers.
The following table summarizes the functions of the character-
handling library. When using functions from the character-
handling library, include the <cctype> header.
S.No. Prototype & Description
1 int isdigit( int c )
Returns 1 if c is a digit and 0 otherwise.
2 int isalpha( int c )
Returns 1 if c is a letter and 0 otherwise.
3 int isalnum( int c )
Returns 1 if c is a digit or a letter and 0 otherwise.
4 int isxdigit( int c )
Returns 1 if c is a hexadecimal digit character and 0
otherwise.
(See Appendix D, Number Systems, for a detailed
explanation of binary, octal, decimal and hexadecimal
numbers.)
5 int islower( int c )
Returns 1 if c is a lowercase letter and 0 otherwise.
6 int isupper( int c )
Returns 1 if c is an uppercase letter; 0 otherwise.
7 int isspace( int c )
Returns 1 if c is a white-space character—newline ('\n'),
space
(' '), form feed ('\f'), carriage return ('\r'), horizontal tab
('\t'), or vertical tab ('\v')—and 0 otherwise.
8 int iscntrl( int c )
Returns 1 if c is a control character, such as newline
('\n'), form feed ('\f'), carriage return ('\r'), horizontal

59
tab ('\t'), vertical tab ('\v'), alert ('\a'), or backspace
('\b')—and 0 otherwise.
9 int ispunct( int c )
Returns 1 if c is a printing character other than a space,
a digit, or a letter and 0 otherwise.
10 int isprint( int c )
Returns 1 if c is a printing character including space ('
') and 0 otherwise.
11 int isgraph( int c )
Returns 1 if c is a printing character other than space ('
') and 0 otherwise.
Examples
The following example demonstrates the use of the
functions isdigit, isalpha, isalnum and isxdigit.
Function isdigit determines whether its argument is a digit (0–
9). The function isalpha determines whether its argument is an
uppercase letter (A-Z) or a lowercase letter (a–z). The
function isalnum determines whether its argument is an
uppercase, lowercase letter or a digit.
Function isxdigit determines whether its argument is a
hexadecimal digit (A–F, a–f, 0–9).
String Handling Functions in C:-
C programming language provides a set of pre-defined
functions called string handling functions to work with string
values. The string handling functions are defined in a header
file called string.h. Whenever we want to use any string
handling function we must include the header file
called string.h.
The following table provides most commonly used string
handling function and their use:

Function Syntax (or) Example Description

strcpy() strcpy(string1, string2) Copies string2 value into string1

strncpy() strncpy(string1, Copies first 5 characters string2


string2, 5) into string1

60
strlen() strlen(string1) returns total number of characters
in string1

strcat() strcat(string1,string2) Appends string2 to string1

strncat() strncpy(string1, Appends first 4 characters of


string2, 4) string2 to string1

strcmp() strcmp(string1, string2) Returns 0 if string1 and string2 are


the same;
less than 0 if string1<string2;
greater than 0 if string1>string2

strncmp() strncmp(string1, Compares first 4 characters of both


string2, 4) string1 and string2

strcmpi() strcmpi(string1,string2) Compares two strings, string1 and


string2 by ignoring case (upper or
lower)

stricmp() stricmp(string1, Compares two strings, string1 and


string2) string2 by ignoring case (similar to
strcmpi())

strlwr() strlwr(string1) Converts all the characters of


string1 to lower case.

strupr() strupr(string1) Converts all the characters of


string1 to upper case.

strdup() string1 = Duplicated value of string2 is


strdup(string2) assigned to string1

strchr() strchr(string1, 'b') Returns a pointer to the first


occurrence of character 'b' in
string1

strrchr() 'strrchr(string1, 'b') Returns a pointer to the last


occurrence of character 'b' in
string1

strstr() strstr(string1, string2) Returns a pointer to the first


occurrence of string2 in string1

61
strset() strset(string1, 'B') Sets all the characters of string1 to
given character 'B'.

strnset() strnset(string1, 'B', 5) Sets first 5 characters of string1 to


given character 'B'.

strrev() strrev(string1) It reverses the value of string1

Pointers:-
Pointers in C are used to store the address of variables or a
memory location. This variable can be of any data type i.e,
int, char, function, array, or any other pointer. Pointers are
one of the core concepts of C programming language that
provides low-level memory access and facilitates dynamic
memory allocation.

A pointer is a derived data type in C that can store the address


of other variables or a memory. We can access and manipulate
the data stored in that memory location using pointers.
Syntax of C Pointers
datatype * pointer_name;
The above syntax is the generic syntax of C pointers. The actual
syntax depends on the type of data the pointer is pointing to.
C Pointer Declaration
In pointer declaration, we only declare the pointer but do not
initialize it. To declare a pointer, we use the * dereference
operator before its name.
data_type * pointer_name;
The pointer declared here will point to some random memory
address as it is not initialized. Such pointers are also called
wild pointers that we will study later in this article.
C Pointer Initialization
When we assign some value to the pointer, it is called Pointer
Initialization in C. There are two ways in which we can initialize
a pointer in C of which the first one is:

Method 1: C Pointer Definition

datatype * pointer_name = address;


The above method is called Pointer Definition as the pointer is
declared and initialized at the same time.

62
Types of Pointers:-
Pointers can be classified into many different types based on
the parameter on which we are defining their types. If we
consider the type of variable stored in the memory location
pointed by the pointer, then the pointers can be classified into
the following types:

1. Integer Pointers

As the name suggests, these are the pointers that point to the
integer values.
Syntax of Integer Pointers
int *pointer_name;
These pointers are pronounced as Pointer to Integer.
Similarly, a pointer can point to any primitive data type. The
syntax will change accordingly. It can point also point to
derived data types such as arrays and user-defined data types
such as structures.

2. Array Pointer

Pointers and Array are closely related to each other. Even the
array name is the pointer to its first element. They are also
known as Pointer to Arrays. We can create a pointer to an array
using the given syntax.
Syntax of Array Pointers
char *pointer_name = &array_name;
Pointer to Arrays exhibits some interesting properties which we
discussed later in this article.

3. Structure Pointer

The pointer pointing to the structure type is called Structure


Pointer or Pointer to Structure. It can be declared in the same
way as we declare the other primitive data types.
Syntax of Structure Pointer
struct struct_name *pointer_name;

63
4. Function Pointers

Function pointers point to the functions. They are different


from the rest of the pointers in the sense that instead of
pointing to the data, they point to the code. Let’s consider a
function prototype – int func (int, char), the function
pointer for this function will be
Syntax of Function Pointer
int (*pointer_name)(int, int);
Keep in mind that the syntax of the function pointers changes
according to the function prototype.

5. Double Pointers

In C language, we can define a pointer that stores the memory


address of another pointer. Such pointers are called double-
pointers or pointers-to-pointer. Instead of pointing to a data
value, they point to another pointer.
Syntax of Double Pointer in C
datatype ** pointer_name;
Dereferencing in Double Pointer
*pointer_name; // get the address stored in the inner level
pointer
**pointer_name; // get the value pointed by inner level pointer
Note: In C, we can create multi-level pointers with any number
of levels such as – ***ptr3, ****ptr4, ******ptr5 and so on.

6. NULL Pointer

The Null Pointers are those pointers that do not point to any
memory location. They can be created by assigning a NULL
value to the pointer. A pointer of any type can be assigned the
NULL value.
Syntax of NULL Pointer in C
data_type *pointer_name = NULL;
or
pointer_name = NULL
It is said to be good practice to assign NULL to the pointers
currently not in use.

64
7. Void Pointer

The Void pointers in C are the pointers of type void. It means


that they do not have any associated data type. They are also
called generic pointers as they can point to any type and can
be typecasted to any type.
Syntax of Void Pointer
void * pointer_name;
One of the main properties of void pointers is that they cannot
be dereferenced.

8. Wild Pointers

The Wild Pointers are pointers that have not been initialized
with something yet. These types of C-pointers can cause
problems in our programs and can eventually cause them to
crash.
Example of Wild Pointers
int *ptr;
char *str;

9. Constant Pointers

In constant pointers, the memory address stored inside the


pointer is constant and cannot be modified once it is defined.
It will always point to the same memory address.
Syntax of Constant Pointer
const data_type * pointer_name;

10. Pointer to Constant

The pointers pointing to a constant value that cannot be


modified are called pointers to a constant. Here we can only
access the data pointed by the pointer, but cannot modify it.
Although, we can change the address stored in the pointer to
constant.
Syntax to Pointer to Constant
data_type * const pointer_name;

Structures in C:-

65
What is Structure data type?
A structure is a keyword that creates user-defined data types
in C/C++. A structure creates a data type that can be used to
group items of possibly different types into a single type.
How to declare structure variables?
A structure variable can either be declared with structure
declaration or as a separate declaration like basic types.

• C
// A variable declaration with structure declaration.
struct Point
{
int x, y;
} p1; // The variable p1 is declared with 'Point'

// A variable declaration like basic data types


struct Point
{
int x, y;
};

int main()
{
struct Point p1; // The variable p1 is declared like a
normal variable
}

Note: In C++, the struct keyword is optional before in


declaration of a variable. In C, it is mandatory.
Time Complexity: O(1)
Auxiliary Space: O(1)

66
Where to use the Structure data type?
We can use this data type to store data of different attributes
of different data types.
For example, If we want to store data on multiple patients such
as patient name, age, and blood group.
How to create a structure?
‘struct’ keyword is used to create a structure. Following is an
example.

• C
struct address
{
char name[50];
char street[100];
char city[50];
char state[20];
int pin;

Limitations of C Structures:-
In C language, Structures provide a method for packing
together data of different types. A Structure is a helpful tool to
handle a group of logically related data items. However, C
structures have some limitations.
• The C structure does not allow the struct data type to
be treated like built-in data types:
• We cannot use operators like +,- etc. on Structure
variables. For example, consider the following code:
• C
struct number {
float x;
};
int main()
{
struct number n1, n2, n3;

67
n1.x = 4;
n2.x = 3;
n3 = n1 + n2;
return 0;
}

/*Output:

prog.c: In function 'main':


prog.c:10:7: error:
invalid operands to binary + (have 'struct number' and
'struct number') n3=n1+n2;

*/

Unions:-
A union is a special data type available in C that allows to
store different data types in the same memory location. You
can define a union with many members, but only one member
can contain a value at any given time. Unions provide an
efficient way of using the same memory location for
multiple-purpose.
To define a union, you must use the union statement in the
same way as you did while defining a structure. The union
statement defines a new data type with more than one member
for your program. The format of the union statement is as
follows −
union [union tag] {
member definition;
member definition;
...
member definition;
} [one or more union variables];
The union tag is optional and each member definition is a
normal variable definition, such as int i; or float f; or any other

68
valid variable definition. At the end of the union's definition,
before the final semicolon, you can specify one or more union
variables but it is optional. Here is the way you would define a
union type named Data having three members i, f, and str −
union Data {
int i;
float f;
char str[20];
} data;
Now, a variable of Data type can store an integer, a floating-
point number, or a string of characters. It means a single
variable, i.e., same memory location, can be used to store
multiple types of data. You can use any built-in or user defined
data types inside a union based on your requirement.
The memory occupied by a union will be large enough to hold
the largest member of the union. For example, in the above
example, Data type will occupy 20 bytes of memory space
because this is the maximum space which can be occupied by a
character string. The following example displays the total
memory size occupied by the above union −

#include <stdio.h>
#include <string.h>

union Data {
int i;
float f;
char str[20];
};

int main( ) {

union Data data;

printf( "Memory size occupied by data : %d\n", sizeof(data));

return 0;
}
When the above code is compiled and executed, it produces the
following result −
Memory size occupied by data : 20

69
File Handling:-

So far the operations using the C program are done on a


prompt/terminal which is not stored anywhere. But in the
software industry, most programs are written to store the
information fetched from the program. One such way is to
store the fetched information in a file. Different operations that
can be performed on a file are:
1. Creation of a new file (fopen() with attributes as “a” or
“a+” or “w” or “w+”)
2. Opening an existing file (fopen())
3. Reading from file (fscanf() or fgets())
4. Writing to a file (fprintf() or fputs())
5. Moving to a specific location in a file (fseek(), rewind())
6. Closing a file (fclose())
The text in the brackets denotes the functions used for
performing those operations.
types of Files in C:-
Generally, a text file contains alphabets, digits, and special
characters or symbols, while a binary file contains bytes or a
compiled version of the text. It is important to recognize two
types of files when dealing with files:
• Text Files
• Binary Files
Text Files: Text files contain data in the form of ASCII
characters and are generally used to store a stream of
characters. Each line in a text file ends with a new line character
(‘\n’). Text files are used to store the source code.
Binary Files: Binary files contain data that is stored in a similar
manner to how it is stored in the main memory. Instead of ASCII
characters, it is stored in binary format. The binary files can be
created only from within a program and their contents can only
be read by a program.

Opening or Creating a File:-


For opening a file, fopen() function is used with the required
access modes. Some of the commonly used file access modes
are mentioned below.
File opening modes in C:
Opening Description
Modes

70
r Searches file. If the file is opened successfully
fopen( ) loads it into memory and sets up a pointer
that points to the first character in it. If the file
cannot be opened fopen( ) returns NULL.
rb Open for reading in binary mode. If the file does
not exist, fopen( ) returns NULL.
w Searches file. If the file exists, its contents are
overwritten. If the file doesn’t exist, a new file is
created. Returns NULL, if unable to open the file.
wb Open for writing in binary mode. If the file exists,
its contents are overwritten. If the file does not
exist, it will be created.
a Searches file. If the file is opened successfully
fopen( ) loads it into memory and sets up a pointer
that points to the last character in it. If the file
doesn’t exist, a new file is created. Returns NULL,
if unable to open the file.
ab Open for append in binary mode. Data is added to
the end of the file. If the file does not exist, it will
be created.
r+ Searches file. It is opened successfully fopen( )
loads it into memory and sets up a pointer that
points to the first character in it. Returns NULL, if
unable to open the file.
rb+ Open for both reading and writing in binary mode.
If the file does not exist, fopen( ) returns NULL.
w+ Searches file. If the file exists, its contents are
overwritten. If the file doesn’t exist a new file is
created. Returns NULL, if unable to open the file.
wb+ Open for both reading and writing in binary mode.
If the file exists, its contents are overwritten. If the
file does not exist, it will be created.
a+ Searches file. If the file is opened successfully
fopen( ) loads it into memory and sets up a pointer
that points to the last character in it. If the file
doesn’t exist, a new file is created. Returns NULL,
if unable to open the file.
ab+ Open for both reading and appending in binary
mode. If the file does not exist, it will be created.
Pointers and its importance:-

pointers in C are easy and fun to learn. Some C programming


tasks are performed more easily with pointers, and other tasks,
such as dynamic memory allocation, cannot be performed

71
without using pointers. So it becomes necessary to learn
pointers to become a perfect C programmer. Let's start learning
them in simple and easy steps.
As you know, every variable is a memory location and every
memory location has its address defined which can be accessed
using ampersand (&) operator, which denotes an address in
memory. Consider the following example, which prints the
address of the variables defined −
#include <stdio.h>

int main () {

int var1;
char var2[10];

printf("Address of var1 variable: %x\n", &var1 );


printf("Address of var2 variable: %x\n", &var2 );

return 0;
}
When the above code is compiled and executed, it produces the
following result −
Address of var1 variable: bff5a400
Address of var2 variable: bff5a3f6
What are Pointers?
A pointer is a variable whose value is the address of another
variable, i.e., direct address of the memory location. Like any
variable or constant, you must declare a pointer before using it
to store any variable address. The general form of a pointer
variable declaration is −
type *var-name;
Here, type is the pointer's base type; it must be a valid C data
type and var-name is the name of the pointer variable. The
asterisk * used to declare a pointer is the same asterisk used for
multiplication. However, in this statement the asterisk is being
used to designate a variable as a pointer. Take a look at some of
the valid pointer declarations −
int *ip; /* pointer to an integer */
double *dp; /* pointer to a double */
float *fp; /* pointer to a float */
char *ch /* pointer to a character */

72
The actual data type of the value of all pointers, whether
integer, float, character, or otherwise, is the same, a long
hexadecimal number that represents a memory address. The
only difference between pointers of different data types is the
data type of the variable or constant that the pointer points to.
How to Use Pointers?
There are a few important operations, which we will do with the
help of pointers very frequently. (a) We define a pointer
variable, (b) assign the address of a variable to a pointer
and (c) finally access the value at the address available in the
pointer variable. This is done by using unary operator * that
returns the value of the variable located at the address specified
by its operand. The following example makes use of these
operations −
#include <stdio.h>

int main () {

int var = 20; /* actual variable declaration */


int *ip; /* pointer variable declaration */

ip = &var; /* store address of var in pointer variable*/

printf("Address of var variable: %x\n", &var );

/* address stored in pointer variable */


printf("Address stored in ip variable: %x\n", ip );

/* access the value using the pointer */


printf("Value of *ip variable: %d\n", *ip );

return 0;
}
When the above code is compiled and executed, it produces the
following result −
Address of var variable: bffd8b3c
Address stored in ip variable: bffd8b3c
Value of *ip variable: 20
NULL Pointers
It is always a good practice to assign a NULL value to a pointer
variable in case you do not have an exact address to be assigned.

73
This is done at the time of variable declaration. A pointer that
is assigned NULL is called a null pointer.
The NULL pointer is a constant with a value of zero defined in
several standard libraries. Consider the following program −
#include <stdio.h>

int main () {

int *ptr = NULL;

printf("The value of ptr is : %x\n", ptr );

return 0;
}
When the above code is compiled and executed, it produces the
following result −
The value of ptr is 0
In most of the operating systems, programs are not permitted
to access memory at address 0 because that memory is reserved
by the operating system. However, the memory address 0 has
special significance; it signals that the pointer is not intended
to point to an accessible memory location. But by convention, if
a pointer contains the null (zero) value, it is assumed to point
to nothing.
To check for a null pointer, you can use an 'if' statement as
follows −
if(ptr) /* succeeds if p is not null */
if(!ptr) /* succeeds if p is null */
Pointers in Detail
Pointers have many but easy concepts and they are very
important to C programming. The following important pointer
concepts should be clear to any C programmer −

Sr.No. Concept & Description

1 Pointer arithmetic
There are four arithmetic operators that can be used
in pointers: ++, --, +, -

74
2 Array of pointers
You can define arrays to hold a number of pointers.

3 Pointer to pointer
C allows you to have pointer on a pointer and so on.

4 Passing pointers to functions in C


Passing an argument by reference or by address
enable the passed argument to be changed in the
calling function by the called function.

5 Return pointer from functions in C


C allows a function to return a pointer to the local
variable, static variable, and dynamically allocated
memory as well.

Pointer Arithmetics in C:-

Pointers variables are also known as address data


types because they are used to store the address of another
variable. The address is the memory location that is assigned
to the variable. It doesn’t store any value.
Hence, there are only a few operations that are allowed to
perform on Pointers in C language. The operations are slightly
different from the ones that we generally use for mathematical
calculations. The operations are:
1. Increment/Decrement of a Pointer
2. Addition of integer to a pointer
3. Subtraction of integer to a pointer
4. Subtracting two pointers of the same type
5. Comparison of pointers of the same type.
Increment/Decrement of a Pointer
Increment: It is a condition that also comes under addition.
When a pointer is incremented, it actually increments by the
number equal to the size of the data type for which it is a
pointer.
For Example:
If an integer pointer that stores address 1000 is incremented,
then it will increment by 4(size of an int) and the new address

75
it will points to 1004. While if a float type pointer is
incremented then it will increment by 4(size of a float) and the
new address will be 1004.
Decrement: It is a condition that also comes under subtraction.
When a pointer is decremented, it actually decrements by the
number equal to the size of the data type for which it is a
pointer.
For Example:
If an integer pointer that stores address 1000 is decremented,
then it will decrement by 4(size of an int) and the new address
it will points to 996. While if a float type pointer is
decremented then it will decrement by 4(size of a float) and
the new address will be 996.
Below is the program to illustrate pointer
increment/decrement:
Pointers can be outputted using %p, since, most of the
computers store the address value in hexadecimal form using
%p gives the value in that form. But for simplicity and
understanding we can also use %u to get the value in Unsigned
int form.

• C

#include <stdio.h>
// pointer increment and decrement
//pointers are incremented and decremented by the size
of the data type they point to
int main()
{
int a = 22;
int *p = &a;
printf("p = %u\n", p); // p = 6422288
p++;
printf("p++ = %u\n", p); //p++ = 6422292 +4 // 4
bytes
p--;
printf("p-- = %u\n", p); //p-- = 6422288 -4 //
restored to original value

float b = 22.22;
float *q = &b;
printf("q = %u\n", q); //q = 6422284
q++;

76
printf("q++ = %u\n", q); //q++ = 6422288 +4 // 4
bytes
q--;
printf("q-- = %u\n", q); //q-- = 6422284 -4 //
restored to original value

char c = 'a';
char *r = &c;
printf("r = %u\n", r); //r = 6422283
r++;
printf("r++ = %u\n", r); //r++ = 6422284 +1 // 1
byte
r--;
printf("r-- = %u\n", r); //r-- = 6422283 -1 //
restored to original value

return 0;
}
Output
p = 1441900792
p++ = 1441900796
p-- = 1441900792
q = 1441900796
q++ = 1441900800
q-- = 1441900796
r = 1441900791
r++ = 1441900792
r-- = 1441900791
Addition
When a pointer is added with a value, the value is first
multiplied by the size of data type and then added to the
pointer.

• C

// C program to illustrate pointer Addition


#include <stdio.h>

77
// Driver Code
int main()
{
// Integer variable
int N = 4;

// Pointer to an integer
int *ptr1, *ptr2;

// Pointer stores the address of N


ptr1 = &N;
ptr2 = &N;

printf("Pointer ptr2 before Addition: ");


printf("%p \n", ptr2);

// Addition of 3 to ptr2
ptr2 = ptr2 + 3;
printf("Pointer ptr2 after Addition: ");
printf("%p \n", ptr2);

return 0;
}
Output
Pointer ptr2 before Addition: 0x7ffca373da9c
Pointer ptr2 after Addition: 0x7ffca373daa8
Subtraction
When a pointer is subtracted with a value, the value is first
multiplied by the size of the data type and then subtracted
from the pointer.
Below is the program to illustrate pointer Subtraction:

• C

// C program to illustrate pointer Subtraction


#include <stdio.h>

// Driver Code
int main()
{
// Integer variable

78
int N = 4;

// Pointer to an integer
int *ptr1, *ptr2;

// Pointer stores the address of N


ptr1 = &N;
ptr2 = &N;

printf("Pointer ptr2 before Subtraction: ");


printf("%p \n", ptr2);

// Subtraction of 3 to ptr2
ptr2 = ptr2 - 3;
printf("Pointer ptr2 after Subtraction: ");
printf("%p \n", ptr2);

return 0;
}
Output
Pointer ptr2 before Subtraction: 0x7ffd718ffebc
Pointer ptr2 after Subtraction: 0x7ffd718ffeb0
Subtraction of Two Pointers
The subtraction of two pointers is possible only when they
have the same data type. The result is generated by calculating
the difference between the addresses of the two pointers and
calculating how many bits of data it is according to the pointer
data type. The subtraction of two pointers gives the increments
between the two pointers.
For Example:
Two integer pointers
say ptr1(address:1000) and ptr2(address:1004) are
subtracted. The difference between address is 4 bytes. Since
the size of int is 4 bytes, therefore the increment between
ptr1 and ptr2 is given by (4/4) = 1.
Below is the implementation to illustrate the Subtraction of
Two Pointers:

• C

// C program to illustrate Subtraction

79
// of two pointers
#include <stdio.h>

// Driver Code
int main()
{
int x = 6; // Integer variable declaration
int N = 4;

// Pointer declaration
int *ptr1, *ptr2;

ptr1 = &N; // stores address of N


ptr2 = &x; // stores address of x

printf(" ptr1 = %u, ptr2 = %u\n", ptr1, ptr2);


// %p gives an hexa-decimal value,
//We convert it into an unsigned int value by using %u

// Subtraction of ptr2 and ptr1


x = ptr1 - ptr2;

// Print x to get the Increment


// between ptr1 and ptr2
printf("Subtraction of ptr1 "
"& ptr2 is %d\n",
x);

return 0;
}
Output
ptr1 = 2715594428, ptr2 = 2715594424
Subtraction of ptr1 & ptr2 is 1
Pointer Arithmetic on Arrays:
Pointers contain addresses. Adding two addresses makes no
sense because there is no idea what it would point to.
Subtracting two addresses lets you compute the offset between
the two addresses. An array name acts like a pointer constant.
The value of this pointer constant is the address of the first
element. For Example: if an array named arr then arr and
&arr[0] can be used to reference array as a pointer.

80
Below is the program to illustrate the Pointer Arithmetic on
arrays:
Program 1:
• C

// C program to illustrate the array


// traversal using pointers
#include <stdio.h>

// Driver Code
int main()
{

int N = 5;

// An array
int arr[] = { 1, 2, 3, 4, 5 };

// Declare pointer variable


int* ptr;

// Point the pointer to first


// element in array arr[]
ptr = arr;

// Traverse array using ptr


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

// Print element at which


// ptr points
printf("%d ", ptr[0]);
ptr++;
}
}
Output
12345
Program 2:
• C

// C program to illustrate the array


// traversal using pointers in 2D array

81
#include <stdio.h>

// Function to traverse 2D array


// using pointers
void traverseArr(int* arr,
int N, int M)
{

int i, j;

// Traverse rows of 2D matrix


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

// Traverse columns of 2D matrix


for (j = 0; j < M; j++) {

// Print the element


printf("%d ", *((arr + i * M) + j));
}
printf("\n");
}
}

// Driver Code
int main()
{

int N = 3, M = 2;

// A 2D array
int arr[][2] = { { 1, 2 },
{ 3, 4 },
{ 5, 6 } };

// Function Call
traverseArr((int*)arr, N, M);
return 0;
}
Output
12
34
56

82
Declaration structure:-
The structure is a collection of different datatype variables,
grouped together under a single name. It is a heterogeneous
collection of data items that share a common name.
Features of structure
• It is possible to copy the contents of all structural
elements of different data types to another structure
variable of its type by using an assignment operator.
• To handle complex datatypes, it is possible to create
a structure within another structure, which is called
nested structures.
• It is possible to pass an entire structure, individual
elements of structure, and address of structure to a
function.
• It is possible to create structure pointers.
The general form of structure declaration is as follows −
datatype member1;
struct tagname{
datatype member2;
datatype member n;
};
Here,
struct is the keyword.

• tagname specifies the name of a structure
• member1, member2 specifies the data items that
makeup structure.
For example,
struct book{
int pages;
char author [30];
float price;
};
Structure variables
There are three ways of declaring structure variables, which are
as follows −
Type 1

83
struct book{
int pages;
char author[30];
float price;
}b;
Type 2
struct{
int pages;
char author[30];
float price;
}b;
Type 3
struct book{
int pages;
char author[30];
float price;
};
struct book b;

Pointer to Pointer:-
A pointer to a pointer is a form of multiple indirection, or a
chain of pointers. Normally, a pointer contains the address of a
variable. When we define a pointer to a pointer, the first pointer
contains the address of the second pointer, which points to the
location that contains the actual value as shown below.

A variable that is a pointer to a pointer must be declared as such.


This is done by placing an additional asterisk in front of its
name. For example, the following declaration declares a pointer
to a pointer of type int −
int **var;
When a target value is indirectly pointed to by a pointer to a
pointer, accessing that value requires that the asterisk operator
be applied twice, as is shown below in the example −

84
#include <stdio.h>

int main () {

int var;
int *ptr;
int **pptr;

var = 3000;

/* take the address of var */


ptr = &var;

/* take the address of ptr using address of operator & */


pptr = &ptr;

/* take the value using pptr */


printf("Value of var = %d\n", var );
printf("Value available at *ptr = %d\n", *ptr );
printf("Value available at **pptr = %d\n", **pptr);

return 0;
}
When the above code is compiled and executed, it produces the
following result −
Value of var = 3000
Value available at *ptr = 3000
Value available at **pptr = 3000

pointers to structures:-
Pointer to structure holds the add of the entire structure.
It is used to create complex data structures such as linked lists,
trees, graphs and so on.
The members of the structure can be accessed using a special
operator called as an arrow operator ( -> ).
Declaration
Following is the declaration for pointers to structures in C
programming −
struct tagname *ptr;
For example − struct student *s −

85
Accessing
It is explained below how to access the pointers to structures.
Ptr-> membername;
For example − s->sno, s->sname, s->marks;
Example Program
The following program shows the usage of pointers to
structures −
#include<stdio.h>
struct student{
int sno;
char sname[30];
float marks;
};
main ( ){
struct student s;
struct student *st;
printf("enter sno, sname, marks:");
scanf ("%d%s%f", & s.sno, s.sname, &s. marks);
st = &s;
printf ("details of the student are");
printf ("Number = %d
", st ->sno);
printf ("name = %s
", st->sname);
printf ("marks =%f
", st ->marks);
getch ( );
}
Output
Let us run the above program that will produce the following
result −
enter sno, sname, marks:1 Lucky 98
details of the student are:
Number = 1

86
name = Lucky
marks =98.000000

Pointer to function:-
In C, like normal data pointers (int *, char *, etc), we can have
pointers to functions. Following is a simple example that shows
declaration and function call using function pointer.
#include <stdio.h>
// A normal function with an int parameter
// and void return type
void fun(int a)
{
printf("Value of a is %d\n", a);
}

int main()
{
// fun_ptr is a pointer to function fun()
void (*fun_ptr)(int) = &fun;

/* The above line is equivalent of following two


void (*fun_ptr)(int);
fun_ptr = &fun;
*/

// Invoking fun() using fun_ptr


(*fun_ptr)(10);

return 0;
}
Output:
Value of a is 10
Following are some interesting facts about function
pointers.

1) Unlike normal pointers, a function pointer points to code,


not data. Typically a function pointer stores the start of
executable code.
2) Unlike normal pointers, we do not allocate de-allocate
memory using function pointers.

3) A function’s name can also be used to get functions’ address.

87
For example, in the below program, we have removed address
operator ‘&’ in assignment. We have also changed function call
by removing *, the program still works.
#include <stdio.h>
// A normal function with an int parameter
// and void return type
void fun(int a)
{
printf("Value of a is %d\n", a);
}

int main()
{
void (*fun_ptr)(int) = fun; // & removed

fun_ptr(10); // * removed

return 0;
}
Output:
Value of a is 10

4) Like normal pointers, we can have an array of function


pointers. Below example in point 5 shows syntax for array of
pointers.

5) Function pointer can be used in place of switch case. For


example, in below program, user is asked for a choice between
0 and 2 to do different tasks.
#include <stdio.h>
void add(int a, int b)
{
printf("Addition is %d\n", a+b);
}
void subtract(int a, int b)
{
printf("Subtraction is %d\n", a-b);
}
void multiply(int a, int b)
{
printf("Multiplication is %d\n", a*b);

88
}

int main()
{
// fun_ptr_arr is an array of function pointers
void (*fun_ptr_arr[])(int, int) = {add, subtract, multiply};
unsigned int ch, a = 15, b = 10;

printf("Enter Choice: 0 for add, 1 for subtract and 2 "


"for multiply\n");
scanf("%d", &ch);

if (ch > 2) return 0;

(*fun_ptr_arr[ch])(a, b);

return 0;
}
Enter Choice: 0 for add, 1 for subtract and 2 for multiply
2
Multiplication is 150

6) Like normal data pointers, a function pointer can be passed


as an argument and can also be returned from a function.
For example, consider the following C program where
wrapper() receives a void fun() as parameter and calls the
passed function.
// A simple C program to show function pointers as
parameter
#include <stdio.h>

// Two simple functions


void fun1() { printf("Fun1\n"); }
void fun2() { printf("Fun2\n"); }

// A function that receives a simple function


// as parameter and calls the function
void wrapper(void (*fun)())
{
fun();
}

89
int main()
{
wrapper(fun1);
wrapper(fun2);
return 0;
}
This point in particular is very useful in C. In C, we can use
function pointers to avoid code redundancy. For example a
simple qsort() function can be used to sort arrays in ascending
order or descending or by any other order in case of array of
structures. Not only this, with function pointers and void
pointers, it is possible to use qsort for any data type.
// An example for qsort and comparator
#include <stdio.h>
#include <stdlib.h>

// A sample comparator function that is used


// for sorting an integer array in ascending order.
// To sort any array for any other data type and/or
// criteria, all we need to do is write more compare
// functions. And we can use the same qsort()
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}

int main ()
{
int arr[] = {10, 5, 15, 12, 90, 80};
int n = sizeof(arr)/sizeof(arr[0]), i;

qsort (arr, n, sizeof(int), compare);

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


printf ("%d ", arr[i]);
return 0;
}
Output:
5 10 12 15 80 90

90
Similar to qsort(), we can write our own functions that can be
used for any data type and can do different tasks without code
redundancy. Below is an example search function that can be
used for any data type. In fact we can use this search function
to find close elements (below a threshold) by writing a
customized compare function.

#include <stdio.h>
#include <stdbool.h>

// A compare function that is used for searching an


integer
// array
bool compare (const void * a, const void * b)
{
return ( *(int*)a == *(int*)b );
}

// General purpose search() function that can be used


// for searching an element *x in an array arr[] of
// arr_size. Note that void pointers are used so that
// the function can be called by passing a pointer of
// any type. ele_size is size of an array element
int search(void *arr, int arr_size, int ele_size, void *x,
bool compare (const void * , const void *))
{
// Since char takes one byte, we can use char pointer
// for any type/ To get pointer arithmetic correct,
// we need to multiply index with size of an array
// element ele_size
char *ptr = (char *)arr;

int i;
for (i=0; i<arr_size; i++)
if (compare(ptr + i*ele_size, x))
return i;

// If element not found


return -1;
}

int main()
{
int arr[] = {2, 5, 7, 90, 70};

91
int n = sizeof(arr)/sizeof(arr[0]);
int x = 7;
printf ("Returned index is %d ", search(arr, n,
sizeof(int), &x, compare));
return 0;
}
Output:
Returned index is 2
The above search function can be used for any data type by
writing a separate customized compare().

7) Many object oriented features in C++ are implemented using


function pointers in C. For example virtual functions. Class
methods are another example implemented using function
pointers.

Dynamic memory allocation:-

The concept of dynamic memory allocation in c


language enables the C programmer to allocate memory at
runtime. Dynamic memory allocation in c language is possible
by 4 functions of stdlib.h header file.

1. malloc()
2. calloc()
3. realloc()
4. free()

Now let's have a quick look at the methods used for dynamic
memory allocation.

malloc() allocates single block of requested memory.


calloc() allocates multiple block of requested memory.
realloc() reallocates the memory occupied by malloc() or calloc()
functions.
free() frees the dynamically allocated memory.
malloc() function in C

The malloc() function allocates single block of requested


memory.

92
PlayNext
Unmute

Current Time 0:00

Duration 18:10
Loaded: 0.37%
Â
Fullscreen
Backward Skip 10sPlay VideoForward Skip 10s

It doesn't initialize memory at execution time, so it has garbage


value initially.

It returns NULL if memory is not sufficient.

The syntax of malloc() function is given below:

1. ptr=(cast-type*)malloc(byte-size)

Let's see the example of malloc() function.

1. #include<stdio.h>
2. #include<stdlib.h>
3. int main(){
4. int n,i,*ptr,sum=0;
5. printf("Enter number of elements: ");
6. scanf("%d",&n);
7. ptr=(int*)malloc(n*sizeof(int)); //memory allocated usi
ng malloc
8. if(ptr==NULL)
9. {
10. printf("Sorry! unable to allocate memory");
11. exit(0);
12. }
13. printf("Enter elements of array: ");

93
14. for(i=0;i<n;++i)
15. {
16. scanf("%d",ptr+i);
17. sum+=*(ptr+i);
18. }
19. printf("Sum=%d",sum);
20. free(ptr);
21. return 0;
22. }

Output

Enter elements of array: 3


Enter elements of array: 10
10
10
Sum=30

calloc() function in C

The calloc() function allocates multiple block of requested


memory.

It initially initialize all bytes to zero.

It returns NULL if memory is not sufficient.

The syntax of calloc() function is given below:

1. ptr=(cast-type*)calloc(number, byte-size)

Let's see the example of calloc() function.

1. #include<stdio.h>
2. #include<stdlib.h>
3. int main(){
4. int n,i,*ptr,sum=0;
5. printf("Enter number of elements: ");
6. scanf("%d",&n);
7. ptr=(int*)calloc(n,sizeof(int)); //memory allocated usin
g calloc
8. if(ptr==NULL)
9. {

94
10. printf("Sorry! unable to allocate memory");
11. exit(0);
12. }
13. printf("Enter elements of array: ");
14. for(i=0;i<n;++i)
15. {
16. scanf("%d",ptr+i);
17. sum+=*(ptr+i);
18. }
19. printf("Sum=%d",sum);
20. free(ptr);
21. return 0;
22. }

Output

Enter elements of array: 3


Enter elements of array: 10
10
10
Sum=30

realloc() function in C

If memory is not sufficient for malloc() or calloc(), you can


reallocate the memory by realloc() function. In short, it changes
the memory size.

Let's see the syntax of realloc() function.

1. ptr=realloc(ptr, new-size)
free() function in C

The memory occupied by malloc() or calloc() functions must be


released by calling free() function. Otherwise, it will consume
memory until program exit.

Let's see the syntax of free() function.

1. free(ptr)

95
What is an Algorithm? Algorithm Basics:-
The word Algorithm means ” A set of finite rules or instructions
to be followed in calculations or other problem-solving
operations ” Or ” A procedure for solving a mathematical
problem in a finite number of steps that frequently involves
recursive operations”.
Therefore Algorithm refers to a sequence of finite steps to
solve a particular problem.

Use of the Algorithms:-

Algorithms play a crucial role in various fields and have many


applications. Some of the key areas where algorithms are used
include:
Computer Science: Algorithms form the basis of computer
programming and are used to solve problems ranging from
simple sorting and searching to complex tasks such as artificial
intelligence and machine learning.
Mathematics: Algorithms are used to solve mathematical
problems, such as finding the optimal solution to a system of
linear equations or finding the shortest path in a graph.
Operations Research: Algorithms are used to optimize and
make decisions in fields such as transportation, logistics, and
resource allocation.
Artificial Intelligence: Algorithms are the foundation of
artificial intelligence and machine learning, and are used to
develop intelligent systems that can perform tasks such as
image recognition, natural language processing, and decision-
making.
Data Science: Algorithms are used to analyze, process, and
extract insights from large amounts of data in fields such as
marketing, finance, and healthcare.
These are just a few examples of the many applications of
algorithms. The use of algorithms is continually expanding as
new technologies and fields emerge, making it a vital
component of modern society.
Algorithms can be simple and complex depending on what
you want to achieve.

96
It can be understood by taking the example of cooking a new
recipe. To cook a new recipe, one reads the instructions and
steps and executes them one by one, in the given sequence.
The result thus obtained is the new dish is cooked perfectly.
Every time you use your phone, computer, laptop, or calculator
you are using Algorithms. Similarly, algorithms help to do a
task in programming to get the expected output.
The Algorithm designed are language-independent, i.e. they are
just plain instructions that can be implemented in any
language, and yet the output will be the same, as expected.
What is the need for algorithms:
1.Algorithms are necessary for solving complex problems
efficiently and effectively.
2.They help to automate processes and make them more
reliable, faster, and easier to perform.
3.Algorithms also enable computers to perform tasks that
would be difficult or impossible for humans to do manually.
4.They are used in various fields such as mathematics,
computer science, engineering, finance, and many others to
optimize processes, analyze data, make predictions, and
provide solutions to problems.
What are the Characteristics of an Algorithm?

97
As one would not follow any written instructions to cook the
recipe, but only the standard one. Similarly, not all written
instructions for programming is an algorithms. In order for
some instructions to be an algorithm, it must have the
following characteristics:
• Clear and Unambiguous: The algorithm should be clear
and unambiguous. Each of its steps should be clear in
all aspects and must lead to only one meaning.
• Well-Defined Inputs: If an algorithm says to take
inputs, it should be well-defined inputs. It may or may
not take input.
• Well-Defined Outputs: The algorithm must clearly
define what output will be yielded and it should be well-
defined as well. It should produce at least 1 output.
• Finite-ness: The algorithm must be finite, i.e. it should
terminate after a finite time.
• Feasible: The algorithm must be simple, generic, and
practical, such that it can be executed with the available
resources. It must not contain some future technology
or anything.
• Language Independent: The Algorithm designed must
be language-independent, i.e. it must be just plain
instructions that can be implemented in any language,
and yet the output will be the same, as expected.
• Input: An algorithm has zero or more inputs. Each that
contains a fundamental operator must accept zero or
more inputs.
• Output: An algorithm produces at least one
output.Every instruction that contains a fundamental
operator must accept zero or more inputs.
• Definiteness: All instructions in an algorithm must be
unambiguous, precise, and easy to interpret. By
referring to any of the instructions in an algorithm one
can clearly understand what is to be done. Every
fundamental operator in instruction must be defined
without any ambiguity.
• Finiteness: An algorithm must terminate after a finite
number of steps in all test cases. Every instruction
which contains a fundamental operator must be
terminated within a finite amount of time. Infinite loops
or recursive functions without base conditions do not
possess finiteness.

98
• Effectiveness: An algorithm must be developed by
using very basic, simple, and feasible operations so that
one can trace it out by using just paper and pencil.
Properties of Algorithm:
• It should terminate after a finite time.
• It should produce at least one output.
• It should take zero or more input.
• It should be deterministic means giving the same
output for the same input case.
• Every step in the algorithm must be effective i.e. every
step should do some work.
Types of Algorithms:
There are several types of algorithms available. Some
important algorithms are:
1. Brute Force Algorithm: It is the simplest approach for a
problem. A brute force algorithm is the first approach that
comes to finding when we see a problem.
2. Recursive Algorithm: A recursive algorithm is based
on recursion. In this case, a problem is broken into several sub-
parts and called the same function again and again.
3. Backtracking Algorithm: The backtracking algorithm
basically builds the solution by searching among all possible
solutions. Using this algorithm, we keep on building the
solution following criteria. Whenever a solution fails we trace
back to the failure point and build on the next solution and
continue this process till we find the solution or all possible
solutions are looked after.
4. Searching Algorithm: Searching algorithms are the ones
that are used for searching elements or groups of elements
from a particular data structure. They can be of different types
based on their approach or the data structure in which the
element should be found.
5. Sorting Algorithm: Sorting is arranging a group of data in a
particular manner according to the requirement. The
algorithms which help in performing this function are called
sorting algorithms. Generally sorting algorithms are used to
sort groups of data in an increasing or decreasing manner.
6. Hashing Algorithm: Hashing algorithms work similarly to
the searching algorithm. But they contain an index with a key
ID. In hashing, a key is assigned to specific data.
7. Divide and Conquer Algorithm: This algorithm breaks a
problem into sub-problems, solves a single sub-problem and
merges the solutions together to get the final solution. It
consists of the following three steps:

99
• Divide
• Solve
• Combine
8. Greedy Algorithm: In this type of algorithm the solution is
built part by part. The solution of the next part is built based
on the immediate benefit of the next part. The one solution
giving the most benefit will be chosen as the solution for the
next part.
9. Dynamic Programming Algorithm: This algorithm uses the
concept of using the already found solution to avoid repetitive
calculation of the same part of the problem. It divides the
problem into smaller overlapping subproblems and solves
them.
10. Randomized Algorithm: In the randomized algorithm we
use a random number so it gives immediate benefit. The
random number helps in deciding the expected outcome.
To learn more about the types of algorithms refer to the article
about “Types of Algorithms“.
Advantages of Algorithms:
• It is easy to understand.
• An algorithm is a step-wise representation of a solution
to a given problem.
• In Algorithm the problem is broken down into smaller
pieces or steps hence, it is easier for the programmer
to convert it into an actual program.
Disadvantages of Algorithms:
• Writing an algorithm takes a long time so it is time-
consuming.
• Understanding complex logic through algorithms can
be very difficult.
• Branching and Looping statements are difficult to show
in Algorithms(imp)

Algorithm in C Language

Algorithm is a step-by-step procedure, which defines a set of


instructions to be executed in a certain order to get the desired
output. Algorithms are generally created independent of
underlying languages, i.e. an algorithm can be implemented in
more than one programming language.

From the data structure point of view, following are some


important categories of algorithms −

• Search − Algorithm to search an item in a data structure.

100
• Sort − Algorithm to sort items in a certain order.
• Insert − Algorithm to insert item in a data structure.
• Update − Algorithm to update an existing item in a data
structure.
• Delete − Algorithm to delete an existing item from a data
structure.

Characteristics of an Algorithm
Not all procedures can be called an algorithm. An algorithm
should have the following characteristics −

• Unambiguous − Algorithm should be clear and


unambiguous. Each of its steps (or phases), and their
inputs/outputs should be clear and must lead to only one
meaning.
• Input − An algorithm should have 0 or more well-defined
inputs.
• Output − An algorithm should have 1 or more well-defined
outputs, and should match the desired output.
• Finiteness − Algorithms must terminate after a finite
number of steps.
• Feasibility − Should be feasible with the available
resources.
• Independent − An algorithm should have step-by-step
directions, which should be independent of any
programming code.

How to Write an Algorithm?


There are no well-defined standards for writing algorithms.
Rather, it is problem and resource dependent. Algorithms are
never written to support a particular programming code.

As we know that all programming languages share basic code


constructs like loops (do, for, while), flow-control (if-else), etc.
These common constructs can be used to write an algorithm.

We write algorithms in a step-by-step manner, but it is not


always the case. Algorithm writing is a process and is executed
after the problem domain is well-defined. That is, we should
know the problem domain, for which we are designing a
solution.

Example
Let’s try to learn algorithm-writing by using an example.

101
Problem − Design an algorithm to add two numbers and display
the result.

Step 1 − START

Step 2 − declare three integers a, b & c

Step 3 − define values of a & b

Step 4 − add values of a & b

Step 5 − store output of step 4 to c

Step 6 − print c

Step 7 − STOP

Algorithms tell the programmers how to code the program.


Alternatively, the algorithm can be written as −

Step 1 − START ADD

Step 2 − get values of a & b

Step 3 − c ← a + b

Step 4 − display c

Step 5 − STOP

In design and analysis of algorithms, usually the second method


is used to describe an algorithm. It makes it easy for the analyst
to analyze the algorithm ignoring all unwanted definitions. He
can observe what operations are being used and how the
process is flowing.

Writing step numbers, is optional.

We design an algorithm to get a solution of a given problem. A


problem can be solved in more than one ways.

102
Hence, many solution algorithms can be derived for a given
problem. The next step is to analyze those proposed solution
algorithms and implement the best suitable solution.

Algorithm Analysis
Efficiency of an algorithm can be analyzed at two different
stages, before implementation and after implementation. They
are the following −

• A Priori Analysis − This is a theoretical analysis of an


algorithm. Efficiency of an algorithm is measured by
assuming that all other factors, for example, processor
speed, are constant and have no effect on the
implementation.
• A Posterior Analysis − This is an empirical analysis of an
algorithm. The selected algorithm is implemented using
programming language. This is then executed on target
computer machine. In this analysis, actual statistics like
running time and space required, are collected.

We shall learn about a priori algorithm analysis. Algorithm


analysis deals with the execution or running time of various
operations involved. The running time of an operation can be
defined as the number of computer instructions executed per
operation.

Algorithm Complexity
Suppose X is an algorithm and n is the size of input data, the
time and space used by the algorithm X are the two main factors,
which decide the efficiency of X.

103
• Time Factor − Time is measured by counting the number
of key operations such as comparisons in the sorting
algorithm.
• Space Factor − Space is measured by counting the
maximum memory space required by the algorithm.

The complexity of an algorithm f(n) gives the running time


and/or the storage space required by the algorithm in terms
of n as the size of input data.

Space Complexity
Space complexity of an algorithm represents the amount of
memory space required by the algorithm in its life cycle. The
space required by an algorithm is equal to the sum of the
following two components −

• A fixed part that is a space required to store certain data


and variables, that are independent of the size of the
problem. For example, simple variables and constants
used, program size, etc.
• A variable part is a space required by variables, whose size
depends on the size of the problem. For example, dynamic
memory allocation, recursion stack space, etc.

Space complexity S(P) of any algorithm P is S(P) = C + SP(I), where


C is the fixed part and S(I) is the variable part of the algorithm,
which depends on instance characteristic I. Following is a
simple example that tries to explain the concept −

Algorithm: SUM(A, B)

Step 1 – START

Step 2 – C ← A + B + 10

Step 3 – Stop

Here we have three variables A, B, and C and one constant.


Hence S(P) = 1 + 3. Now, space depends on data types of given
variables and constant types and it will be multiplied
accordingly.

Time Complexity
Time complexity of an algorithm represents the amount of time
required by the algorithm to run to completion. Time
requirements can be defined as a numerical function T(n), where

104
T(n) can be measured as the number of steps, provided each
step consumes constant time.

For example, addition of two n-bit integers takes n steps.


Consequently, the total computational time is T(n) = c ∗ n, where
c is the time taken for the addition of two bits. Here, we observe
that T(n) grows linearly as the input size increases.

Structure for arrays sparse matrics:-


A matrix is a two-dimensional data object made of m rows and
n columns, therefore having total m x n values. If most of the
elements of the matrix have 0 value, then it is called a sparse
matrix.
Why to use Sparse Matrix instead of simple matrix ?
• Storage: There are lesser non-zero elements than zeros
and thus lesser memory can be used to store only those
elements.
• Computing time: Computing time can be saved by
logically designing a data structure traversing only non-
zero elements..
Example:
00304
00570
00000
02600
Representing a sparse matrix by a 2D array leads to wastage of
lots of memory as zeroes in the matrix are of no use in most of
the cases. So, instead of storing zeroes with non-zero elements,
we only store non-zero elements. This means storing non-zero
elements with triples- (Row, Column, value).

Using Arrays:
2D array is used to represent a sparse matrix in which there are
three rows named as
• Row: Index of row, where non-zero element is located
• Column: Index of column, where non-zero element is
located
• Value: Value of the non zero element located at index –
(row,column)

105
Implementation:
• C++
• C
• Java
• Python3
• C#
• Javascript

// C++ program for Sparse Matrix Representation


// using Array
#include <iostream>
using namespace std;

int main()
{
// Assume 4x5 sparse matrix
int sparseMatrix[4][5] =
{
{0 , 0 , 3 , 0 , 4 },
{0 , 0 , 5 , 7 , 0 },
{0 , 0 , 0 , 0 , 0 },
{0 , 2 , 6 , 0 , 0 }
};

int size = 0;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 5; j++)
if (sparseMatrix[i][j] != 0)
size++;

// number of columns in compactMatrix (size) must be


// equal to number of non - zero elements in
// sparseMatrix
int compactMatrix[3][size];

106
// Making of new matrix
int k = 0;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 5; j++)
if (sparseMatrix[i][j] != 0)
{
compactMatrix[0][k] = i;
compactMatrix[1][k] = j;
compactMatrix[2][k] = sparseMatrix[i][j];
k++;
}

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


{
for (int j=0; j<size; j++)
cout <<" "<< compactMatrix[i][j];

cout <<"\n";
}
return 0;
}

// this code is contributed by shivanisinghss2110


Output
001133
242312
345726
Time Complexity: O(NM), where N is the number of rows in the
sparse matrix, and M is the number of columns in the sparse
matrix.
Auxiliary Space: O(NM), where N is the number of rows in the
sparse matrix, and M is the number of columns in the sparse
matrix.

STACK AND QUEUES:-

Stack: A stack is a linear data structure in which elements can


be inserted and deleted only from one side of the list, called
the top. A stack follows the LIFO (Last In First Out) principle,
i.e., the element inserted at the last is the first element to come
out. The insertion of an element into the stack is

107
called push operation, and the deletion of an element from the
stack is called pop operation. In stack, we always keep track of
the last element present in the list with a pointer called top.
The diagrammatic representation of the stack is given below:

Queue is a linear data structure in which elements can be


inserted only from one side of the list called rear, and the
elements can be deleted only from the other side called
the front. The queue data structure follows the FIFO (First In
First Out) principle, i.e. the element inserted at first in the list,
is the first element to be removed from the list. The insertion
of an element in a queue is called an enqueue operation and
the deletion of an element is called a dequeue operation. In
queue, we always maintain two pointers, one pointing to the
element which was inserted at the first and still present in the
list with the front pointer and the second pointer pointing to
the element inserted at the last with the rear pointer.

Difference between Stack and Queue Data Structures are as


follows:
Stacks Queues
A stack is a data structure A queue is a data structure that
that stores a collection of stores a collection of elements,
elements, with operations with operations to enqueue (add)
to push (add) and pop elements at the back of the
(remove) elements from queue, and dequeue (remove)
the top of the stack. elements from the front of the
queue.

108
Stacks are based on the Queues are based on the FIFO
LIFO principle, i.e., the principle, i.e., the element
element inserted at the inserted at the first, is the first
last, is the first element to element to come out of the list.
come out of the list.
Stacks are often used for Queues are often used for tasks
tasks that require that involve processing elements
backtracking, such as in a specific order, such as
parsing expressions or handling requests or scheduling
implementing undo tasks.
functionality.
Insertion and deletion in Insertion and deletion in queues
stacks takes place only takes place from the opposite
from one end of the list ends of the list. The insertion
called the top. takes place at the rear of the list
and the deletion takes place from
the front of the list.
Insert operation is called Insert operation is called
push operation. enqueue operation.
Stacks are implemented Queues are implemented using
using an array or linked list an array or linked list data
data structure. structure.
Delete operation is called Delete operation is called
pop operation. dequeue operation.
In stacks we maintain only In queues we maintain two
one pointer to access the pointers to access the list. The
list, called the top, which front pointer always points to the
always points to the last first element inserted in the list
element present in the list. and is still present, and the rear
pointer always points to the last
inserted element.
Stack is used in solving Queue is used in solving
problems works problems having sequential
on recursion. processing.
Stacks are often used for Queues are often used in
recursive algorithms or for multithreaded applications,
maintaining a history of where tasks are added to a queue
function calls. and executed by a pool of worker
threads.
Stack does not have any Queue is of three types – 1.
types. Circular Queue 2. Priority queue
3. double-ended queue.
Can be considered as a Can be considered as a horizontal
vertical collection visual. collection visual.

109
Examples of stack-based Examples of queue-based
languages include algorithms include Breadth-First
PostScript and Forth. Search (BFS) and printing a binary
tree level-by-level.
Applications of stack:
• Some CPUs have their entire assembly language based
on the concept of performing operations on registers
that are stored in a stack.
• Stack structure is used in the C++ run-time system.
• A Stack can be used for evaluating expressions consisting
of operands and operators.
• Stacks can be used for Backtracking, i.e., to check
parenthesis matching in an expression.
• It can also be used to convert one form of expression to
another form.
• It can be used for systematic Memory Management.

Applications of queue:
• Queue data structure is implemented in the hardware
microinstructions inside a CPU.
• Queue structure is used in most operating systems

Infix,prefix and postfix expression :-


For writing complex mathematical expressions, we generally
prefer parentheses to make them more readable. In computers,
expressions with various parentheses add unnecessary work
while solving. So, to minimize the computational works, various
notations have been made. Prefix and Postfix are one of them.
In this article, we’ll be learning about infix, postfix, and prefix
conversion in detail. You’ll find questions on infix, postfix, and
prefix conversion in the frequently asked interview questions of
almost every top tech-based company.
So, let’s get started!
Definition of Infix, Postfix, and Prefix
Infix: The typical mathematical form of expression that we
encounter generally is known as infix notation. In infix form, an
operator is written in between two operands.
For example:
An expression in the form of A * ( B + C ) / D is in infix form.
This expression can be simply decoded as: “Add B and C, then
multiply the result by A, and then divide it by D for the final
answer.”
Prefix: In prefix expression, an operator is written before its
operands. This notation is also known as “Polish notation”.

110
For example, The above expression can be written in the prefix
form as / * A + B C D. This type of expression cannot be simply
decoded as infix expressions.
Postfix: In postfix expression, an operator is written after its
operands. This notation is also known as “Reverse Polish
notation”.
For example, The above expression can be written in the postfix
form as A B C + * D /. This type of expression cannot be simply
decoded as infix expressions.
Refer to the table below to understand these expressions with
some examples:
Infix Prefix Postfix
A+B +AB AB+

A+B-C -+ABC AB+C-

(A+B)*C-D -*+ABCD AB+C*D-

Prefix and postfix notions are methods of writing mathematical


expressions without parentheses. Let’s see the infix, postfix and
prefix conversion.

Examples:

Infix Postfix Prefix

A*B+C/D AB*CD/+ +*AB/CD

A * (B + C) / D ABC+*D/ /*A+BCD

A * (B + C / D) ABCD/+* *A+B/CD

Circular Queue:-
A Circular Queue is an extended version of a normal
queue where the last element of the queue is connected to the
first element of the queue forming a circle.
The operations are performed based on FIFO (First In First Out)
principle. It is also called ‘Ring Buffer’.

111
Operations on Circular Queue:-
• Front: Get the front item from the queue.
• Rear: Get the last item from the queue.
• enQueue(value) This function is used to insert an
element into the circular queue. In a circular queue, the
new element is always inserted at the rear position.
• Check whether the queue is full – [i.e., the rear
end is in just before the front end in a circular
manner].
• If it is full then display Queue is full.
• If the queue is not full then, insert an
element at the end of the queue.
• deQueue() This function is used to delete an element
from the circular queue. In a circular queue, the
element is always deleted from the front position.
• Check whether the queue is Empty.
• If it is empty then display Queue is empty.
• If the queue is not empty, then get the
last element and remove it from the
queue.

Applications of Circular Queue:-


1. Memory Management: The unused memory locations
in the case of ordinary queues can be utilized in circular
queues.
2. Traffic system: In computer controlled traffic system,
circular queues are used to switch on the traffic lights
one by one repeatedly as per the time set.
3. CPU Scheduling: Operating systems often maintain a
queue of processes that are ready to execute or that are
waiting for a particular event to occur.

112
Advantages:-

Circular Queues offer a quick and clean way to store FIFO data
with a maximum size.
• Doesn’t use dynamic memory → No memory leaks
• Conserves memory as we only store up to our
capacity (opposed to a queue which could continue to
grow if input outpaces output.)
• Simple Implementation → easy to trust and test
• Never has to reorganize / copy data around
• All operations occur in constant time O(1)
Disadvantages:-

Circular Queues can only store the pre-determined maximum


number of elements.

• Have to know the max size beforehand

Deque or Double Ended Queue :-


It is a generalized version of Queue data structure that allows
insert and delete at both ends.
Operations on Deque: Below is a table showing some basic
operations along with their time complexity, performed on
deques.
Operation Description Time
Complexity
push_front() Inserts the element at the O(1)
beginning.
push_back() Adds element at the end. O(1)
pop_front() Removes the first element from O(1)
the deque.
pop_back() Removes the last element from O(1)
the deque.
front() Gets the front element from the O(1)
deque.
back() Gets the last element from the O(1)
deque.
empty() Checks whether the deque is O(1)
empty or not.

113
size() Determines the number of O(1)
elements in the deque.
Other operations performed on deques are explained as
follows:
clear(): Remove all the elements from the deque. It leaves the
deque with a size of 0.
erase(): Remove one or more elements from the deque. It takes
an iterator specifying the position of the first element to be
removed, and an optional second iterator specifying the
position of the last element to be removed.
swap(): Swap the contents of one deque with another deque.
emplace_front(): Insert a new element at the front of the deque.
It is similar to the insert operation, but it avoids the copy
constructor of the element being inserted.
emplace_back(): Insert a new element at the back of the deque.
It is similar to the insert operation, but it avoids the copy
constructor of the element being inserted.
resize(): Change the number of elements in the deque to a
specific number. If the new size is larger than the current size,
new elements are appended to the deque. If the new size is
smaller than the current size, elements are removed from the
deque.
assign(): Assign new values to the elements in the deque. It
replaces the current contents of the deque with new elements.
reverse(): Reverse the order of the elements in the deque.
sort(): Sort the elements in the deque in ascending order. It
uses the less-than operator to compare the elements.
Applications of Deque: Since Deque supports both stack and
queue operations, it can be used as both. The Deque data
structure supports clockwise and anticlockwise rotations in
O(1) time which can be useful in certain applications. Also, the
problems where elements need to be removed and or added to
both ends can be efficiently solved using Deque. For example
see the Maximum of all subarrays of size k problem., 0-1
BFS, and Find the first circular tour that visits all petrol pumps.
See the wiki page for another example of the A-Steal job
scheduling algorithm where Deque is used as deletions
operation is required at both ends.
Some Practical Applications of Deque:
• Applied as both stack and queue, as it supports both
operations.
• Storing a web browser’s history.
• Storing a software application’s list of undo operations.
• Job scheduling algorithm

114

You might also like