PPS Notes Unit-I (1) - Merged
PPS Notes Unit-I (1) - Merged
PPS Notes Unit-I (1) - Merged
COMPUTER SYSTEM:
A Computer is an electronic device which performs operations such as accepts the data, stores the data,
manipulates or process the data according to a pre-stored instructions and produces the desired result. All
these tasks are performed at high-speed and accuracy.
A Computer computes the data (input) supplied to it and generates information (output).
A Computer is an electronic device which takes the input, processes it, and gives the output according to the
user needs.
A computer is a system made of two major components: Hardware and software.
Hardware: Hardware of a computer system are the physical components which we can touch and feel.
Example: Keyboard and Mouse.
The hardware of a computer system can be classified as:
1. Input Devices (I/P)
2. Processing Devices (CPU)
3. Output Devices (O/P)
1. Input Devices: Input devices are used to enter the data into the computer system.
Example: Keyboard, Mouse, Scanner, Microphone, Camera…etc.
2. Output Devices: Output devices are used to take the information (output) from a computer system.
Example: Monitor (Display or Standard Output), Printer, Speakers…etc.
(If the output is shown on the monitor we call it as softcopy. If it is printed on a paper using the printer, we
call it as hardcopy)
3. Processing Unit (or) Central Processing Unit:
The CPU is responsible for executing instructions such as arithmetic calculations, comparison between
data, and movement of data inside the system.
The modern day computers can have one or more CPUs in it.
The CPU, internal to it will have three different parts: ALU, CU and MU.
o ALU (Arithmetic and Logic Unit): ALU will performs the Arithmetic and Logical Operations
such as +,-,*,/ (Arithmetic Operations) &&, || ( Logical Operations) inside a computer system.
o CU (Control Unit): Every Operation such as storing, computing and retrieving the data should
be governed by the control unit.
o MU (Memory Unit): The Memory unit is used for storing the data. The Memory unit is
classified into two types. They are:
a) Primary Memory
b) Secondary Memory
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
a) Primary Memory (Main Memory): The primary memory also known as main memory is a
place where the programs and data are stored temporarily during processing. The data in primary
memory are erased when the computer is turned off. The following are the two memory types, which
are treated as primary memory.
ROM (Read Only Memory): It represents Read Only Memory that stores data and
instructions even when the computer is turned off. The contents in the ROM can‘t be
modified once if they are written. It is used to store the BIOS information which is helpful in
loading the operating system into the RAM from HDD.
RAM (Random Access Memory): It represents Random Access Memory that stores data
and instructions when the computer is turned on. The contents in the RAM can be modified
any number of times by instructions. It is used to store the programs under execution. The
content in the RAM are volatile, that is when the computer turned off the content of RAM
will be lost.
b) Secondary Memory (Auxiliary Memory): The following are the different kinds of secondary
memories. They can also be called as auxiliary memory. The content of these devices will remain
permanent even when the computer is turned off. The programs and data remain in the secondary
storage, ready for the next time use.
Magnetic Storage: The Magnetic Storage devices store information that can be read, erased
and rewritten a number of times. Example: Floppy Disks, Hard Disks, Magnetic Tapes.
Optical Storage: The optical storage devices that use laser beams to read and write stored
data. Example: CD (Compact Disk), DVD (Digital Versatile Disk).
There are other forms of memory devices like: Cache Memory and CPU Registers.
Cache Memory: These are superfast memory locations and are directly accessible by the CPU. The
content are volatile again. They are maintained in very small amounts as they are very costly.
CPU Registers: There are internal memory location of the CPU. The data inside the CPU is stored
in these registers for processing.
Application Software:
The following figure shows the relationship between the system software and application software.
In this figure, each circle represents an interface point.
The inner core is the computer hardware. The outer most layer represents the user.
The user uses application software to work with the system. This application software interacts with
operating system, which is a part of system software layer.
The system software have the direct interaction with the hardware.
The opening at the bottom of the figure is the path followed by the user to interact directly with
operating system when necessary.
COMPUTER LANGUAGES
To write a program for a computer the computer language is used.
The computer languages have changed over the years from machine language to natural language.
The following summary shows, how computer languages have evolved from machine language to
natural language.
1940‘s -- Machine Languages
1950‘s -- Symbolic Languages
1960‘s -- High Level Languages
Machine Languages:
In the early days of computers, the only available programming language was machine language.
The problem with machine language is that, each computer will have its own machine language, which
made up of only 0’s and 1’s.
The following program will give an idea of how instructions can be written in machine language.
All instructions in machine language must be streams of 0’s and 1’s, because internal circuits of the
computer system are made of switches, transistors and other electronic devices.
These devices can be in any one of the two possible states: on or off.
The off state is represented by 0; the on state is represented by 1.
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
Symbolic Languages
In 1950s, Admiral Grace Hopper, a mathematician developed the concept of a special program that
convert programs into machine language.
During these days, programming languages simply mirrored machine languages using symbols, or
mnemonics, to represent the machine language instructions.
As these languages used special symbols, they were known as symbolic languages.
The computer does not understand any other languages except its own machine language. Hence there is
a need to translate symbolic languages into machine language.
A special program called an assembler is used, which translates symbolic languages into machine
languages.
As symbolic languages are assembled using an assembler into machine languages, they also called as
assembly languages.
High-Level Languages
Symbolic languages required the programmers to concentrate on the hardware of the computer that they
were using, as these languages are still dependent on the machine.
Writing program in symbolic languages is very difficult because each instruction has to be coded separately.
Because of these issues programmers thought that there is a requirement of sophisticated and efficient
programming technique.
This led to the development of high-level programming languages.
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
High-Level languages are machine independent (portable). They allow the programmers to concentrate
more on application rather than the computer hardware.
The programmers also free from remembering the symbols and mnemonics specific to the computer system.
However like symbolic languages, these languages also be converted to machine language before giving it
to the computer.
The process of converting high-level languages into machine languages is known as compilation.
The most widely used high-level language was FORTRAN created by John Backus and IBM team in 1957,
it is still in use in scientific and engineering applications.
COBOL was also another high-level language used, developed by Admiral Grace Hopper.
C is also a high-level language used for the development of System software and other application
programs. It was developed by Dennis Ritchie in 1972.
4. Executing programs:
Once the program has been linked it is ready for execution.
To execute a program the program has to be loaded into primary memory. The operating system
command ‘run’ can be used to achieve this job.
Getting the program into the main memory is the function of an operating system program known as
loader. It locates the executable program in secondary memory and loads it to main memory.
After loading everything into the memory, the program takes the control and starts the execution.
In today’s integrated development environments (IDEs) these steps are combined under simple
mouse clicks or pull-down menu bars or simple shortcut key combinations.
In typical program execution, the program takes input either from the user or from a file. After
processing the data, it prepares the output either to the user’s monitor or to a file.
Once the execution process finishes the operating system removes the program from main memory.
COMPUTING ENVIRONMENTS
In the early days of computing the only environment available was the mainframe computing environment,
where the mainframe computer is used to satisfy all operations given to it. No sharing of resources from
other computers.
Later with the advancement of minicomputers and personal computers, many computing environment came
into existence. These computing environments are:
1. Personal Computing Environment
2. Time-Sharing Environment
3. Client-Server Environment
4. Distributed Computing Environment
Personal Computing Environment:
In 1971, Marcian E. Hoff of Intel has combined all basic elements of the central processing unit onto a
single chip known as microprocessor.
This was the first computer on a single chip named Intel 4004. It was the grandfather to many of today’s
modern computing processors.
In personal computing environments, a personal computer (PC) will be used where all of the computer
hardware components are connected together inside a single computer.
This environment will have the whole computer of its own. The user can perform whichever operation he
want.
Atypical personal computer is shown in the following.
ALGORITHM:
An algorithm is a step by step process to solve any given computational problem.
That is an Algorithm refers to a set of rules/instructions that step-by-step define how a work is to be done to
get the expected results.
The Algorithm is language-independent, i.e. the plain instructions in an algorithm can be written in any
language to get the expected output.
Characteristics / Specifications of Algorithms:
Not all written instructions can be considered as an algorithm. In order to consider the written statements as an
algorithm it must have the following characteristics.
Input: An algorithm has zero or more inputs, taken from a specified set of objects.
Output: An algorithm has one or more outputs, which have a specified relation to the inputs.
Definiteness: Each step must be precisely defined; each instruction is clear and unambiguous.
Finiteness: The algorithm must always terminate after a finite number of steps.
Effectiveness: An algorithm must be basic and simple. And it has to give the expected solution to the
problem in a finite number of steps.
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
Example: To cook a new recipe, one reads the instructions/steps and execute them one by one, in the given
sequence. The result can be obtained as a new dish cooked perfectly. Similarly, algorithms help to do a task in
programming to get the expected output.
Example 2:
Problem − Design an algorithm to Calculate the Interest of a Bank Deposit.
Step 1: Start
Step 2: declare amount, year, rate and interest.
Step 3: input amount, year, and rate.
Step 4: interest=Amount*Years*Rate/100.
Step 5: print interest.
Step 6: Stop.
Example-3:
Problem − Design an algorithm to determine whether the Temperature is below or above the
freezing Point (32◦F).
Step 1: Start
Step 2: declare temperature.
Step 3: input temperature.
Step 4: if temperature < 32
print “below freezing point”
else
print “above freezing point”
Step 5: Stop
Example-5:
Problem − Design an algorithm to determine whether a student passed in the exam or not.
Step 1: Start
Step 2: Declare m1, m2, m3, m4, m5, m6 and avg.
Step 3: Read m1, m2, m5, m4, m5 and m6.
Step 4: avg=(m1+m2+m3+m4+m5+m6)/6"
Step 4: if avg < 60
print “FAIL”
else
print “PASS”
Step 5: Stop
Example-6:
Problem − Design an algorithm to find the given number is even or odd.
Step 1: Start
Step 2: Declare num, rem.
Step 3: Read num.
Step 5: if num%2==0
print “num is EVEN”
else
print “num is ODD”
Step 6: Stop
PSEUDO CODE:
Pseudocode is an informal way of programming description that does not require any strict programming
language syntax.
Pseudocode is a methodology that allows the programmer to represent the implementation of an algorithm.
Pseudo codes are used to represent algorithms so that they can be interpreted by programmers irrespective to
their programming background or knowledge.
Pseudo code (as the name suggest, is a false code) is also programming language independent.
Pseudo code has no syntax like any of the programming language, it can’t be compiled or interpreted by the
computer.
Advantages of pseudocode –
• Pseudocode can be understandable by the programmers of all programming languages.
• Pseudocode acts as a bridge between the program and the algorithm or flowchart.
Example:
C code: Pseudocode:
If(i<10) if i is less than 10
{ increment i value by 1
i++;
}
Example-1:
Problem − Design a pseudocode to add, subtract, multiply, divide and to find the reminder of two
numbers and display the result.
This program will allow the user to add two numbers.
Declare variables num1, num2 and sum.
Read values for num1 and num2.
Add num1 and num2 and assign the result to sum.
sum←num1+num2
print the value of sum on the output screen
Example 2:
Problem − Design a pseudocode to Calculate the Interest of a Bank Deposit.
This program will allow the user the user to calculate the interest for a bank deposit.
Declare variables amount, year, rate and interest.
Read values for amount, year, and rate.
Calculate the interest with formula "interest=Amount*Years*Rate/100.
print the value of interest on the output screen.
Example-3:
Problem − Design a pseudocode to determine whether the Temperature is below or above the freezing
Point (32◦F).
This program will allow the user to determine whether the temperature is below or above the freezing
point.
Declare variable temperature.
Read value for temperature.
if temperature value is lesser than 32, print a message “temperature is below freezing point”.
Otherwise print a message “temperature is above freezing point”.
Example-5:
Problem − Design a pseudocode to determine whether a student passed in the exam or not.
This program will allow the user to determine whether a student passed in the exam or not by considering
6 – different course marks.
Declare variables for courses M1, M2, M5, M4, M5, M6 and grade.
Read values for M1, M2, M5, M4, M5 and M6.
Calculate the average grade with formula "Grade=(M1+M2+M3+M4+M5+M6)/6"
if grade value is greater than 60, print a message PASS.
else print a message FAIL.
Example-6:
Problem − Design a pseudocode to find the given number is even or odd.
This program will allow the user to find the given number is even or odd.
Declare variable num, reminder.
Read value for num.
Calculate the reminder by using a formula reminder=num%2.
if reminder is equal to zero, print a message num is EVEN.
else print a message num is ODD
1. Auxiliary Symbols:
These symbols enhance the readability or functionality of the flowchart. They do not show any
instructions or commands.
These symbols are shown in the following figure: (a) Terminal (b) Flow Lines and (c) Connectors
(a) Terminal:
The Oval symbol is used as a terminal.
It is used to show the beginning and ending of an algorithm.
To show the beginning the START is used inside the oval, and to show the ending the
word STOP or RETURN is used inside the oval.
The basic rule of structured programming is every algorithm should have only one
entry point (START terminal) and one exit point (STOP/RETURN terminal).
(b) Flow Lines:
Flow lines are used to connect different symbols of a flowchart. They also shows the
order or sequence of the symbols.
Every symbol in a flowchart will have some entering and some exiting lines.
For example the START oval will have only one exiting line and the STOP oval will
have only one entering line.
(c) Connectors: A connector symbol, a circle with a number in it is used in two situations.
i. When the end of the page is reached but the flowchart is finished: Here a
connector is used at the bottom of the page to show that the flow continues at the
top of the next page. Refer the following figure (a).
2. Primary Symbol:
The primary symbols are used to show the instructions or actions needed to solve the problem.
These category of symbols used to show: (a) Sequence (b) Decision / Condition (Selection
Statements) and (c) Repetition (Looping Statement).
(a) Sequence
Sequence symbols are used to represent actions that must be performed in a linear order.
To this symbols the flow must enter at the top of the symbol, and flow exit at the bottom of the
symbol.
They do not allow any flow change.
There are four different types of sequence symbols:
i. Null statement
ii. Assignment statement
iii. Input / Output statement
iv. Module call statement
v. Compound statement
I. Null statement:
o A null statement is a sequence statement, as it cannot change the flow direction.
o There is no symbol defined to represent a null statement. It is simply a flow line.
V. Compound Statement:
o A broken-line rectangle is used for compound statement.
o All statements that makes the compound statement are encapsulated inside a broken-line
rectangle.
o In C-Programming a compound statement represents a block of code, which is enclosed in curly
brackets.
Example: The following algorithm reads an integer. If the integer’s value is greater than 10, subtract
10 and writes the result. It the value is lesser than 10, it does nothing.
o Although there are three statements in a for loop, but only two actions are performed in each
iteration.
o In the first iteration only initialization and condition are used. In rest of all iterations only
update and condition will be used.
Example: Design a flowchart to read 20 numbers and print the sum. Since the number of times is
known in advance, for loop is an excellent choice.
Example: Design a flowchart that reads numbers from the keyboard and print their total. As the
number of times is not known in advance a conditional loop is the best choice. To break the loop, or
to limit the number of times a negative input -1 can be read from the keyboard.
Example-1:
Problem – Draw a flowchart to add, subtract, multiply, divide and to find the reminder of two numbers
and display the result.
Example-3:
Problem − Draw a flowchart to determine whether the Temperature is below or above the freezing Point
(32◦F).
Example-5:
Problem – Draw a flowchart to determine whether a student passed in the exam or not.
COMMENTS
Comments are helpful in documenting the code.
Comments improves the readability and understanding of the code.
Comments are placed within the program, with actual programming code.
The compiler ignores these comments when it translates the program into executable code.
In C there are two different types of comments:
a. Block Comments
b. Line Comments
(a). Block Comments:
A block comment is used when he comment will span several lines.
A block comment uses an opening token ‘/*’ and a closing token ‘*/’, between opening and closing token
the comment which span more than one line is used.
No space is allowed between the token symbols, that is ‘/’ and ‘*’ should come together like ‘/*’ for
opening comment and ‘*/’ for closing comment.
Example:
/* This is a block comment
Which spans
More than one line */
Nesting of comment: Comments can be nested, one within another. Doing so does not give any specific meaning
but one has to know what happens if we nest the comments. In nesting of comments we have the following
possibilities.
(i) Nesting line comment within a line comment
(ii) Nesting line comment within a block comment
(iii) Nesting block comment within a line comment
(iv) Nesting block comment within a block comment
(i) Nesting line comment within a line comment: Nesting a line comment within a line comment does not raise
any error. The start token of the nested line comment will be ignored by the compiler. Hence will not generate
any error condition.
(ii) Nesting Line comment within a block comment: Nesting a line comment within a block comment will also
not generate any error. The start token of the nested line comment will be ignored by the compiler as part of
the comment. Hence will not generate any error condition.
(iii)Nesting of block comment within a line comment: Nesting of a block comment within a line comment will
generate error, only if the block comment will span more than one line.
IDENTIFIERS:
Identifiers are used to name data and other objects in the program. It is similar to nouns in natural
languages.
When objects are declared in computer program they will be stored at unique memory locations, these
memory locations will have unique addresses to represent them. If we don’t have symbolic names to these
memory locations, then there is need to know and use these addresses to access the memory locations.
Instead of doing the above, we simply give symbolic names (identifiers) to these memory locations, and the
compiler will keep track of where they are stored.
There are some rules while framing the identifier:
1. First character must be an alphabetic character or underscore.
2. Must consisits only of alphabetic characters, digits, or underscores.
3. First 63 characters of an identifier are significant.
4. Cannot be a keyword.
The forst character of the identifier cannot be underscore, because many objects in library files use
underscore as the first letter in their identifiers. If we do the same we may get duplicate names, which
becomes very confusing for the compiler.
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
C-language is a case sensitive language, that is uppercase and lowercase letters are differently treatted by
the compiler.
No space is allowed withing the identifier. Underscore and Capitalization can be used to separate the words.
KEYWORDS:
Keywords are also known as reserved words. They are syntactical tokens which have special meaning when
used in programming.
Keywords cannot be used as identifiers for variables, functions or named constants in programming.
In C-language there are 37 – keywords, they are listed in the following table:
auto extern short _Bool float signed
break for sizeof case goto static
char if struct _Complex _Imaginary switch
const inline typedef continue int union
default long unsigned do register void
double restrict volatile else return while
enum
The first three types are known as primitive types (or basic types) which are independently defined.
The last type is derived type which are derived from basic types.
1. Void Type:
o The keyword void is used to indicate void type.
o The void type has no values and no operations.
o The void type is used to specify that a function has either no parameters or no return values.
o Example: int main(void); - in this statement the function has no parameters.
o The void type is also used to define a pointer to generic type.
o Example: void* ptr; - in this statement ptr becomes a pointer to the generic type of data.
2. Integral type:
o In C-language there are three integral types namely: Boolean, character and integer.
o Integral types doesn’t hold fractional part they are whole numers.
(a) Boolean:
In C-language Boolean type is included in C99. It is named after the French mathamaticain and
phylosopher George Boole.
A boolean will have only two values: true and false.
Before C99 integers were used to represent the boolean values; a nonzero number (positive or
negetive) is used to represent true, and a zero is used to represent false.
The keyword bool is used refer boolean type.
A boolean type is stored in memory as 0 (false) or 1 (true).
(b) Character:
In computers a character is any value that can be represented in computer’s alphabet (character set).
In C-standard there are two character types: char and wchar_t.
Many computers will use 1-byte to store the char data types. A byte is 8-bits. With 8 bits, there are
256 different possible char values.
In English the letter a is different from x in its visual formation of the graphical associated with the
letter. But in computers the letter a is binary 0110 0001 and letter x is binary 0111 1000. The
decimal values of these two letters 97 for a and 120 for x.
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
In C99 standard To support non-English languages or languges that don’t use the Roman alphabet
wide charater type (wchar_t) is used.
char
wchar_t
(c) Integer:
An integer type is a number without a fraction part.
C supports four different sizes of integer data types: short int, int, long int and long long int.
A short int also referred as short, long int as long and long long int as long long.
These data types are organized from the smallest to the largest as shown in the following figure.
To know the size of any data type, C provides the sizeof operator, that gives the exact size in bytes.
sizeof(short) < sizeof(int) < sizeof(long) < sizeof(long long)
short int
int
long
long long
3. Floating-Point Types:
In C, there are three floating-point types: real, imaginary and complex.
Floating point types are always signed and there is no possibility for unsigned.
float
double
long double
Type summary: The following type summmerizes the standard data type.
A variable’s type can be any datatype, such as character, integral or real, but cannot be a void type.
To create a variable, first specify the type (datatype) and then the name (identifier).
Variable Creation:
Syntax:
float price;
C-allows multiple variables of same type to be defined at the same time in a single statement. It is
considered as poor programming style
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
Multiple Variable Creation in Single Statement:
Syntax:
float balance, price;
Variable Initialization:
The variables can be initialized at the same time when they are defined. That is in a single statement it is
possible to do variable declaration, definition and initialization.
To initialize a variable when it is defined, the identifier has to be followed by an assignment operator (=),
and the initilizer value.
Variable declaration, definition and initialization in single
statement:
Syntax:
float price = 3.759;
In multiple variable definitions when initializer is used with only one variable, the initialization will be
applied to that variable only, but not to all.
Multiple variable declaration, definition and initialization in
single statement:
Syntax:
float balance, price = 3.759;
To avoid the above confusion the variables has to be defined in separate lines.
CONSTANTS:
Constants are data values that cannot be changed during program execution.
Like variables, constatns will also have type.
In C there are different types of constants like: Boolean, character, integer, real, complex and string.
Constant Representation:
Boolean Constatnts:
A boolean data type can take only two values. The values are 1(true) and 0(false).
That is, there are only two possible symbols to represent a boolean data type: 1(true) and 0(false).
To use boolean type, requires the inclusion of standard boolean library file into the program stdbool.h.
Integer Constants:
Integer constants are simply coded as they are in real time. The value 15 is simply coded as 15.
By default all integer constants are signed inegers.
To override this default, that is to make the integer constant of different size: for Unsigned (u or U), for long
(l or L), for long long (ll or LL) can be used after the number.
These codes can be combined to get the required meaning.
There is no way to specify a short integer.
If no code is suffixed by default the type will be int.
Examples of Integer Constants
Representation Value Type
+123 123 int
-378 -378 int
-32,228L -32,228 long int
76542LU 76,542 unsigned long int
12789845LL 12,789,845 long long int
Real Constants:
Real constants will have integer part and fractional part seperated by a dot (.). Ex: 37.273
By default all real constants will be in double.
To override this default size: for float (f ot F) and for long double (l or L) can be used as suffix with the
value.
Complex Constants:
Complex constants are widely used in engineering and mathamatical applications.
Complex constants are coded as two parts, the real part and the imaginary part, seperated by a plus sign.
The real part is coded using the real part rules. The imaginary part is coded as real number multipled(*) with
imaginary constant i(√-1).
As with real constant, by default complex constant is double.
To override this for float (f or F) and for long double (l or L) can be used.
Examples of Complex Constants
Representation Value Type
12.3+14.4*i 12.3+14.4*(√-1) double complex
14F+16F*i 14F+16F*(√-1) float complex
1.4736L+4.56756L*i 1.4736L+4.56756L*(√-1) long double complex
String Constants:
A string constant is a sequence of zero or more characters enclosed in double quotes.
“” //An empty String
“h”
“Hello world\n”
“How are your”
“Good Morning!”
“” Empty String
Coding Constants:
General Syntax:
const type identifier = value;
Defining memory constants is similar to defining variable, prefixing const will make the content to be
fixed in the memory location, and cannot be changed.
The memory constants must be initialized where they are defined, otherwise they permanently hold a
garbage value.
For example:
const float PI = 3.141592;
const INTEREST_RATE 0.5
OPERATORS IN C-LANGUAGE:
Operators are the foundation for any programming language. The functionality of C programming
language is incomplete without the use of operators.
The operator can be defined as symbols that performs a specific mathematical or logical computations on
operands. In other words operator operates on the operands.
In C, Operators are broadly categorized into 3 – types: i) Unary Operators ii) Binary Operator and
iii)Ternary Operator
This broad categorization is done based on the number of operands the operator will use in exhibiting its
functionality.
i) Unary Operators: Operators of this type, operates or works with a single operand. Hence the
name unary operators. For example: (++, --).
ii) Binary Operators: Operators of this type, operates or works with a two operands. Hence the name
binary operators. For example: (+, -, *./).
iii) Ternary Operators: Operators of this type, operates or works with a three operands. Hence the
name ternary operators. For example: (?:).
Based on the above criterion in mind, Operators are categorized into the following categories:
a) Arithmetic Operators:
b) Relational Operators:
c) Logical Operators
d) Bitwise Operators
e) Assignment Operators
f) Increment and Decrement Operators
g) Conditional Operator
h) Other Operators
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
a) Arithmetic Operators:
Arithmetic operators are used to perform arithmetic/mathematical operations on operands.
b) Relational Operators:
Relational operators are used for comparison of two operand values. All of the relational operators are
binary operators. They need two operands to perform their functionality. They are as follows:
int main()
{
int a=10, b=4;
if (a > b)
printf("a is greater than b\n");
else printf("a is less than or equal to b\n");
if (a >= b)
printf("a is greater than or equal to b\n");
else printf("a is lesser than b\n");
if (a < b)
printf("a is less than b\n");
else printf("a is greater than or equal to b\n");
if (a <= b)
printf("a is lesser than or equal to b\n");
else printf("a is greater than b\n");
if (a == b)
printf("a is equal to b\n");
else printf("a and b are not equal\n");
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
if (a != b)
printf("a is not equal to b\n");
else printf("a is equal b\n");
return 0;
}
Output:
a is greater than b
a is greater than or equal to b
a is greater than or equal to b
a is greater than b
a and b are not equal
a is not equal to b
c) Logical Operators:
Logical operators are used to perform logical operations such as Logical AND, Logical OR and Logical
NOT. They are used to combine two or more conditions/constraints or to complement the evaluation of
the original condition in consideration. They are as follows:
if (a>b || c==d)
printf("a is greater than b OR c is equal to d\n");
else printf("Neither a is greater than b nor c is equal to d\n");
if (!a)
printf("a is zero\n");
else printf("a is not zero");
return 0;
}
Output:
AND condition not satisfied
a is greater than b OR c is equal to d
a is not zero
d) Bitwise Operator:
Bitwise operators work at bit level of the given operands. There are 6-different types of bitwise operators:
& (bitwise AND operator):
o This operator takes two numbers as operands and does AND on every bit of two numbers.
o The result of AND is 1 only if both bits are 1.
| (bitwise OR operator):
o This operator takes two numbers as operands and does OR on every bit of two numbers.
o The result of OR is 1 if any of the two bits is 1.
Examples:
a b a&b a|b a^b ~a
0 0 0 0 1 1
0 1 0 1 0 1
1 0 0 1 0 0
1 1 1 1 1 0
a = 5(00000101), b = 9(00001001)
a&b = 00000001
a|b = 00001101
a^b = 00001100
~a = 11111010
b<<1 = 00010010
b>>1 = 00000100
2. The left-shift and right-shift operators are equivalent to multiplication and division by 2 respectively.
For example: if x=18 then x<<1 = 36, x>>1 = 9
#include<stdio.h>
int main()
{
int x = 18;
printf ("x << 1 = %d\n", x << 1);
printf ("x >> 1 = %d\n", x >> 1);
return 0;
}
Output:
36 9
3. The & operator can be used to quickly check if a number is odd or even.
For example: The value of expression (x & 1) would be non-zero only if x is odd, otherwise the value
would be zero.
#include<stdio.h>
int main()
{
int x = 19;
(x & 1)? printf("Odd"): printf("Even");
return 0;
}
Output:
Odd
e) Assignment Operators:
The assignment operator (=) evaluates the operand on the right side of the operator (=) and places the
value in the variable on the left.
The value on the right side must be of the same data-type of variable on the left side otherwise the
compiler will raise an error.
Types of Assignment:
There are three different types of assignments possible using the same operator (=).
1. Simple assignment: This type of statement will have only one assignment operator in it. The right
side value or the result will be assigned to the left-side variable.
Example: a=10; //Here variable a will hold 10 after assignment.
2. Multiple assignment: This type of statement will have multiple assignment statements in it.
Example: a=b=c=10; // Here value 10 will be assigned to a, b, c variables
3. Compound assignment: It is a shorthand notation for a simple assignment. It requires the left
operator to be repeated as a part of the right expression. There are five compound assignment
operators listed in the following table.
Operator Example Equivalent Statement
+= c += 7 c=c+7
-= c -= 8 c=c–8
*= c *= 10 c = c * 10
/= c /= 5 c=c/5
%= c %= 5 c=c%5
Prefix: In this form, the operator is place before the variable, and the variable’s value will be
incremented by 1 before the expression evaluation. Hence the name prefix.
Syntax: a=++b; /*here first the ‘a’ value will be incremented by 1 and then will be
initialized to ‘b’ */
#include<stdio.h>
int main(void)
{
int a,b=7;
system("cls");
a=++b; //postfix increment
printf("\n%d %d", a, b);
a=--b; //postfix decrement
printf("\n%d %d", a, b);
return 0;
}
Output:
88
77
g) Conditional Operator:
Conditional operator also known as ternary operator.
It is the only operator in C, which takes three operands in its operation.
The (?:) token is used to form this operator.
h) Other Operators:
C supports the following set of special operators:
& (Address Operator) The address operator is used get the address of an operand.
It is a unary operator, it requires only on operand.
When used with the operand, it returns the address of that operand’s
memory location.
* (Indirection Operator) To access the value from the given address, the * operator is used.
Generally it deal with pointer, where to get the value from a pointer
this operator is used.
It is also a unary operator, requires only one operand to perform its
functionality.
, (Comma Operator) This operator does not show any operations on the operands, rather it
is used to separate the expressions which are appearing in the same
line.
Like regular use, the comma operator is used like a separator.
Example: int a,b,c;
j=(i=12,i+20);
sizeof() Operator This operator is used to know the memory size of the operand
supplied.
As it is a unary operator, it operates on single operand.
Syntax: sizeof(datatype/variable);
Example: sizeof(a);
sizeof(int);
. and (Member access The . (dot) and operators are used to access the members of a
Operators: structure (directly or indirectly).
Example: 2+3*4 = ?
In precedence table operator * is having higher precedence than operator +, hence the * will be
evaluated first and then +, so the value is 14 (see the following precedence table).
Associativity:
Associativity can be left-to-right or right-to-left.
Left-to-right associativity evaluates the expression by starting on the left and moving to the right.
Right-to-left associativity evaluates the expression by starting on the right and moving to the left.
Remember, associativity is used only when there are operators with same precedence level in occur in a
complex expression.
Associativity Rule
Example:
1. 3*8/4 is 6
2. 2+3%2*4 is 6
3. 3*8/4%4*5 is 10
I. Simple if – Statement:
In C, the simplest form of decision making is the if – statement.
If statement will have a condition helpful in making the decision.
If the condition is true then the statement-block will be executed.
If the condition is false it does not do anything (or the statements block is skipped). Simply the
simple form of if statement will not have anything to do in case of the false condition.
The condition is given in parentheses and must be evaluated as true (nonzero value) or false
(zero value).
If a compound statement need to be provided, it must be enclosed in opening and closing
braces.
Syntax: Simple if statement
if (condition)
{
statement-block;
}
Flow Chart: Example:
Example:
main()
{
int a=10,b=20;
if(a>b)
{
printf(“%d”,a);
}
printf(“%d”,b);
}
Output:
10
20
Whenever the specified condition becomes true, statement-block gets executed. If condition
becomes false it has nothing to do.
Whenever expression value is true (non – zero), statement1 will be executed. If the expression
value is false (zero), statement2 will be executed.
Compound statement:
One and only one statement is allowed in each part of if and else, use statement block
(compound statement) if more than one statement need to be specified.
Example: program for finding the biggest number in two.
#include<stdio.h>
int main(void)
{
int a,b;
clrscr();
printf(“Enter the two Numbers:”);
scanf(“%d %d”, &a,&b);
if(a>b)
printf(“%d is big”, a);
else
printf(“%d is big”, b);
getch();
return 0;
}
Output:
Enter the two Numbers:
10 20
20 is big
Using Nested if – else, two expressions are included. With two expressions it is possible to include three
statements that is three different paths for execution.
Example: Program to find the biggest number in three numbers.
#include<stdio.h>
int main(void)
{
int a,b,c;
clrscr();
printf("Enter a,b,c values:");
scanf("%d %d %d",&a,&b,&c);
if(a>b)
{
if(a>c)
printf("%d is big",a);
else
printf("%d is big",c);
}
else
{
if(b>c)
printf("%d is big",b);
else
printf("%d is big",c);
}
getch();
return 0;
}
Output:
Enter a,b,c values:2 7 29
29 is big
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
The Dangling else Problem:
The nested if – else statement has to be used with extra care, otherwise it may lead to dangling else
problem.
This problem arises when there is no matching else for every if in the statement.
In C, always an else part is paired with the most recent unpaired if.
Doing so may result that some of the if statements may left unpaired.
Syntax: Flowchart:
Consider the above example syntax, from the syntax it is clear that the programmer intended the else
statement to be paired with the first if, but the compiler pair it with the second if. This is known as
dangling else problem.
The solution to the dangling else problem can be obtained by simply taking a compound statement (a set
of curly braces to separate the true part for the first if statement) into consideration.
Syntax: Flowchart:
Consider the above figure; from this it is clear that when compound statement (curly braces) is used the
true part for the first if statement is separated, now the else will be paired with the first if and the
second if remains unpaired.
The conditions are evaluated from the top to down. As soon as a true condition is found the
statement associated with it is executed and the control is transferred to the statementx by skipping
the rest of the ladder. When all n conditions become false, final else containing default statement
that will be executed
Example:
#include<stdio.h>
int main(void)
{
float m1,m2,m3,m4;
float avg;
system("cls"); //clrscr();
printf("Enter marks for (m1,m2,m3,m4):\n");
scanf("%f %f %f %f",&m1,&m2,&m3,&m4);
avg=(m1+m2+m3+m4)/4;
if(avg>=75)
printf("\nDistinction");
else if(avg<75 && avg>=60)
printf("\nFirst Class");
else if(avg<60 && avg>=50)
printf("\nSecond Class");
else if(avg<50 && avg>=40)
printf("\nThird Class");
else
printf("\nFail");
Switch Statement:
The switch statement is a way to implement a multiway selection statement in C.
The switch statement is used only when the selection condition reduces to an integral expression.
If the selection condition is not an integral value, the else – if ladder is used.
Switch is selection statement in which decision for selection is made between many alternatives.
A switch statement allows a single variable to be compared with several possible case labels, which
are represented by constant values.
If the variable matches with one of the constants, then an execution jump is made to that point.
A case label cannot appear more than once.
When none of the case labels are matching with the conditional expression then a default case will be
evaluated.
Syntax: Flowchart:
To break every case, so as to avoid multiple case execution when matching case is found,
the break statement is used. Practically speaking every case should have a break
statement as the last statement to avoid the execution of multiple statements.
Break causes the program to jump out of the switch statement, that is go to the
closing braces (}) and continues the remaining code of the program.
Example:
#include<stdio.h>
int main(void)
{
char ch;
system("cls"); //clrscr();
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
printf("Enter your choice(R,B,G):\n");
scanf("%c",&ch);
switch(ch)
{
case 'R':printf("RED");
break;
case 'B':printf("BLUE");
break;
case 'G':printf("GREEN");
break;
default: printf("Invalid Option...!");
}
getch();
return 0;
}
Output:
Enter your choice(R,B,G):
B
BLUE
LOOPS IN C (REPETITION)
Loops are nothing but an approach to repeat set of statements for a specific number of times.
Every repetition is known as an iteration in the programming terminology.
The real power of computers is in their ability to repeat an operation or a series of operations many times.
This repetition, called looping, is one of the basic structured programming concepts.
Each loop must have an expression that determines the termination point for the loop. If there is no
termination point specified the loop will iterate for infinite number of times.
The basic loop concept is shown in the following figure, as there is no termination condition specified the
loop will iterate infinitely.
while loop:
The while loop is a pretest loop.
It uses an expression (termination condition) to control the loop.
As it is a pretest loop it tests the expression before every iteration of the loop.
Syntax: Flowchart:
do – while loop:
The do – while loop is a post-test loop.
Like while loop, do – while also uses an expression to control the loop.
It tests the condition after the execution of the body.
The body of the loop must contain one and only one statement at any time. To specify more than one
statement group them using a compound statement.
Unlike other looping statement a semicolon is required at the end of the do – while statement, and
also to the statements within the body.
Example: To print 1 to 10 natural numbers
#include<stdio.h>
int main()
{
int i;
system("cls"); //clrscr();
i=1;
do
{
printf("%d ",i);
i++;
}while(i<=10);
getch();
return 0;
}
Output:
1 2 3 4 5 6 7 8 9 10
In while loop if the condition becomes false in the first iteration, the body of the loop never gets executed.
But in do – while the body of the loop gets executed at least once, even if the condition fails in the first
iteration.
for loop:
Note that the semicolon is not required at the end of the for loop statement, but the statement
within the loop body do require semicolons at the end.
The following figure compares the while loop and for loop
Option 2:
int k = 1;
for (; k< = 10; k++);
{
printf(“%d”, k);
}
Here the initialization is done in the declaration statement itself, but still the semicolon
before the condition is necessary.
If we have to read, process and print 10 integers, then we need 10 integers in memory for the duration of
the program.
We can declare and define 10 variables with a different name.
To read these 10 variables from the keyboard we need 10 read statements, and also to print these 10 variables
onto the output screen we need 10 output (printf) statements. This is something redundancy in programming
code.
The approach may look simpler and acceptable to some extend for 10 variables, but if the variable count
increases rapidly, nowhere the above concept is acceptable.
To process large amount of data, C uses a powerful data structure called array.
An array is a collection of elements of the same data type.
Array elements can be initialized, accessed and manipulated using the indexing.
Example: score[10] Here score will contain 10-elements
Array index always start at ‘0’ and end at total-number of elements minus one.
In our example the index for score will start at 0 and end at 9.
Using Arrays in C
C provides two different types of arrays
One-Dimensional arrays: In One-dimensional arrays the data are organized linearly in only one direction.
Two-Dimensional arrays: In Two-Dimensional arrays the data are organized in rows and columns, like a
matrix.
ONE-DIMENSIONAL ARRAYS:
Array declaration and definition
Like every other object in C, an array must be declared, defined and initialized before it can be used in the
program.
Array declaration tells the compiler the name of the array.
Array definition specifies the size or number of elements in the array. In a fixed length array, the size of
the array is a constant and must have a value at the compile time.
Example: type arrayname[array_size];
The declaration and definition format for a variable length is same as like a fixed length array except the
size is a variable. The array size will be determined when the program is executed. Once the size is
determined it cannot be changed.
Initialization:
Array elements in a fixed-length array can be initialized when they are declared. For variable-length
arrays they cannot be initialized when they are defined.
To initialize the array elements with a set of values, they must be enclosed in braces and separated by
commas.
It is a compile error to specify more values than elements in the array.
The initialization can be done in the following ways:
(a) Basic initialization: int scores[5]={3,7,12,24,45};
(b) Initialization without size: int scores[]={3,7,12,24,45};
(c) Partial initialization: int scores[5]={3,7,0,0,0};
(d) Initialization to all zeros: int scores[5]={0};
The first example array the score array will have 5-elements and they contain specific set of values.
In the second example, when the array is completely initializing then the size attribute can be omitted.
In the third example, if the array is initialized with partial values rest of the elements will be
initialized to zero.
In the fourth example can be used to initialize all the elements to zeros.
Inputting values:
An array can be initialized from the keyboard. The values can be read from the keyboard and initialized to
array.
The most appropriate loop to use with arrays is the for loop.
for(i=0;i<9;i++)
scanf(“%d”,&scores[i]);
Assigning values:
Array elements can be assigned individually by using a set of values, with the help of assignment operator.
Example: scores[4]=10;
Assigning one array to another array is not possible even if they match fully in type and size. To do so we
have to copy all the elements individually from one array to another.
for(i=0;i<10;i++)
scores[i]=temp[i];
Printing values:
To print the contents of the array, a normal for loop can be used.
Example: for(i=0;i<10;i++)
printf(“%d “,scores[i]);
TWO-DIMENSIONAL ARRAYS
In One-dimensional arrays the data are organized linearly in only one direction.
Many applications require data to be stored in more than one dimension.
Matrices require an array that consists of rows and columns as shown in the following figure, which is
generally called as two-dimensional array.
In C-language a two dimensional array will be considered as an array of arrays. That is a two dimensional
array is an array of one-dimensional arrays.
Initialization:
The definition of a Two-Dimensional array only reserves the memory for the elements in the array.
No values will be stored in the locations. The locations will generally contain unpredictable values or
garbage values without initialization.
Initialization of array can be done when the array is defined.
The values for the array must be enclosed in braces.
Example: int scores[3][2]={2,3,5,4,6,9};
Nested braces must be used to show the exact number of rows and columns.
Example: int scores[3][2]={{2,3,5},{4,6,9}};
In a Two-Dimensional array, if the array is completely initialized with values, only the first dimension can
be omitted. The second dimension must need to be specified.
Example: int scores[][2]={{2,3,5},{4,6,9}};
The whole array can be initialized to zeros.
Example: int scores[5][4]={0};
Inputting Values:
Another way to initialize the values is, we can read them from the keyboard.
In Two-Dimensional array, it usually requires nested for loops.
The first loop, the outer loop controls the rows from zero to the maximum number and the inner loop
controls the columns from zero to the maximum number.
Example: for(i=0;i<2;i++)
for(j=0;j<2;j++)
scanf(“%d”,&scores[i][j]);
Outputting values:
The values inside a Two-Dimensional array can be printed using two nested loops.
The first loop, the outer loop controls the rows from zero to the maximum number and the inner loop
controls the columns from zero to the maximum number.
To print the matrix in a table format, a newline is printed at the end of each row.
Example: for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
printf(“ %d”,scores[i][j]);
printf(“\n”);
}
Accessing values:
Individual elements can be initialized using the assignment operator.
scores[2][0]=23;
scores[2][2]=scores[1][1]+12;
#include <stdio.h>
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
int main(void)
{
int a[2][2], b[2][2], c[2][2], i, j;
system("cls"); //clrscr();
printf("\nEnter values for matrix A(2X2):\n");
for(i=0;i<2;i++)
for(j=0;j<2;j++)
scanf("%d", &a[i][j]);
Variable-Length strings:
A much preferred solution is to create a structure that can expand and contract according to the size of the
value we want to store.
Example: To store a person name with only three characters the structure should contract and provide
three characters and to store a person name with 30-characters the structure should expand and provide
30-characers.
Here also there is a problem: as we are using a variable length structure in computers memory, there must
be a way to indicate the end of the string.
Two common techniques are used to indicate the end of the string.
o Length-Controlled Strings
o Delimited Strings
Length-Controlled Strings:
In this type of strings a count is used as the first character in the string that specifies the number of
characters in the string.
This count then be used by string manipulation functions to determine the length of the string.
Delimited Strings:
In this type of strings the end is specified by a special character known as delimiter, hence the name
delimited strings.
This concept is similar to using a full stop (.) at the end of a sentence in English. Where each sentence is
of variable length and a special symbol full stop is used to indicate the end of the sentence.
The disadvantage of using a delimiter is that it eliminates one character from being used for data in the
string.
The most common delimiter is a null character (\0).
All C strings are of variable length and delimited once.
As a string is stored in an array, the name of the string is a pointer to the beginning of the string.
There is a big difference between how a character is stored in memory and a one-character string is stored.
The character requires only one memory location, but the one-character string requires two memory
locations one for actual character and one for delimiter.
To store an empty string in memory also requires one memory location to store the delimiter.
String Constants:
A string literal or a string constant is a sequence of characters enclosed in double quotes.
When string constants are used in a program, C automatically creates an array of characters, initializes to a
null delimited string, and stores it.
Example: “C is a programming language”
“Hello World”
A string literal is stored in memory like any other object. It has an address, and can be referred by using a
pointer. Here the string literal as it is a sequence of characters, itself a pointer constant to the first element.
The string itself can be used to refer the individual characters by using index.
Example: “hello”[1] e
#include<stdio.h>
int main(void)
{
char name[30];
printf("Enter name: ");
gets(name); //Function to read string from user.
printf("Name: ");
puts(name); //Function to display string.
return 0;
}
C provides different predefined set of string functions which are helpful in manipulating the strings.
String Length
strlen () function:
This function counts and returns the number of characters in a string. It takes the form
Syntax: int n=strlen(str);
Example:
#include<stdio.h>
#include<string.h>
int main(void)
{
int len;
char str[]="hello";
len=strlen(str);
printf("%d",len);
getch();
return 0;
}
Output:
5
String Copy
The String copy functions strcpy(); copies the contents from one string including the null character to
another string.
There are two string copy functions:
I. Basic string copy strcpy();
II. String copy length controlled strncpy();
Example:
#include<stdio.h>
#include<string.h>
int main(void)
{
char fromstr[]="hello",tostr[10];
strcpy(tostr,fromstr);
puts(tostr);
puts(fromstr);
getch();
return 0;
}
Example:
#include<stdio.h>
#include<string.h>
int main(void)
{
char fromstr[]="hello",tostr[10];
strncpy(tostr,fromstr,2);
puts(tostr);
puts(fromstr);
getch();
return 0;
}
Output:
he
hello
Sring Compare
C has two string compare functions:
I. Basic string compare strcmp();
II. String compare length controlled strncmp();
Example:
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[ ] = "Hyderabad" ;
char str2[ ] = "Hydarabad" ;
int i, j, k;
i = strncmp ( str1, str2, 3) ;
j = strncmp ( str1, str2, 4) ;
k = strncmp ( str1, str2, 10) ;
printf ( "\n%d %d %d", i, j, k ) ;
}
Output
0 4 4
String Concatenation
The string concatenation function appends one string to the end of another string.
The size of the destination string should be large enough to hold the resulting string. If it is not the data at
the end of the destination string will be destroyed.
C has two string concatenation functions:
I. Basic string concatenation strcat();
II. String concatenation length controlled strncat();
Example:
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[ ] = "Hyderabad" ;
char str2[ ] = "ISL" ;
strcat ( str1, str2);
printf ( "%s", str1);
getch();
return 0;
}
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
Output
HyderabadISL
Example:
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[ ] = "Hyderabad" ;
char str2[ ] = "ISL" ;
strncat ( str1, str2, 2) ;
printf ( "%s", str1 ) ;
getch();
return 0;
}
Output
HyderabadIS
String reverse
strrev() function:
The function strrev is used to reverse the contents of the given string.
The function strrev(); takes the string and reverses it, and places the reversed string in the given string
only.
Syntax: strrev(string);
Example:
#include<stdio.h>
#include<string.h>
int main(void)
{
toupper() function takes the character value as parameter, and converts it into the uppercase character.
If the converted character is already in upper case, it remains as it is.
Syntax: tolower(char);
Example:
#include<stdio.h>
#include<string.h>
int main(void)
{
char ch = 'i';
printf("%c",toupper(ch));
getch();
return 0;
}
Output:
I
tolower() function:
tolower() function takes the character value as parameter, and converts it into the lowercase character.
If the converted character is already in lower case, it remains as it is.
Sybtax: tolower(char);
Example:
#include<stdio.h>
#include<string.h>
int main(void)
{
char ch = 'I';
printf("%c",tolower(ch));
getch();
return 0;
}
Output:
i
toascii() function takes the character value as parameter, and converts it into the equivalent ASCII value.
Syntax: toascii(char);
Example:
#include<stdio.h>
#include<string.h>
int main(void)
{
char ch = 'A';
printf("%d",toascii(ch));
getch();
return 0;
}
Output:
65
There are different sorting mechanisms: Selection sort, Bubble sort, Merge sort, Heap sort … etc.
SEARCHING
There are two basic searching techniques that can be applied to an array of elements.
The Linear/Sequential search is used whenever the list is not ordered, small in size and not searched too
often.
The Binary search is used, if the list is ordered, large in size and searched too often.
SELECTION SORT:
In the selection sort, the list is divided into two sub-lists, sorted and unsorted, which are divided by an
imaginary wall.
The smallest element from the unsorted sub-list is found and swapped with the element at the beginning of
the unsorted sub-list.
After each selection and swapping, the imaginary wall between the two sub-lists moves one element ahead,
increasing the number of sorted elements and decreasing the number of unsorted elements.
Each time an element is moved from the unsorted sub-list to the sorted sub-list, we call it a sort pass is
completed.
To sort a list of n-elements, n-1 sort passes are needed.
// C program for implementation of selection sort
#include <stdio.h>
void swap(int*,int*);
void selectionSort(int[],int);
void printArray(int[],int);
Output:
Sorted array:
11 12 22 25 64
BUBBLE SORT:
In the bubble sort, the list is divided into two sub-lists, sorted and unsorted.
The smallest element is bubbled from unsorted sub-list and moved to the sorted sub-list.
After moving the smallest element to the sorted sub-list, the imaginary wall moves one element ahead,
increasing the number of sorted elements and decreasing the number of unsorted elements.
Moving one element each time from unsorted sub-list to the sorted sub-list completes one sort pass.
Given a list of n-elements, the bubble sort takes n-1 sort passes to sort the data.
Remember the bubble sort concept starts from the end of the list.
// C program for implementation of Bubble sort
#include <stdio.h>
void swap(int*, int*);
void bubbleSort(int[],int);
void printArray(int[],int);
int main()
{
int list[] = {64, 34, 25, 12, 22, 11, 90};
int size = sizeof(list)/sizeof(list[0]);
bubbleSort(list, size);
printf("Sorted array: \n");
printArray(list, size);
return 0;
}
LINEAR/SEQUENTIAL SEARCH
In sequential search, the searching for the target will start from the beginning of the list, and will continue
until the target is found or until the end of the list is reached (no target found case).
Example:
The following figure lists the steps to find 62. The process will first compare the value with data at index 0,
then 1, 2, and 3 before finding the element at 5th location (index 4).
If the target value is not in the list, then the comparison operation will reach the end of the list, making sure
that the target is not in the list. The figure also lists the steps for finding the value 72, which is not there in
the list.
// C-Program for Linear Search.
#include<stdio.h>
int seqSearch(int[],int,int);
int main(void)
{
int list[20], target, index, i, size;
system("cls"); //clrscr();
printf("Enter the size of the list:");
scanf("%d", &size);
printf("Enter any %d elements:\n", size);
for (i = 0; i < size; i++)
scanf("%d", &list[i]);
if (index==-1)
printf("%d isn't present in the list.\n", target);
else
printf("%d is present at index %d in the list",target, index);
getch();
return 0;
}
BINARY SEARCH
How it works:
The binary search starts by comparing the data in the element in the middle of the list. This determines if
the target is in the first half or second half of the list.
If the target is in the first half, no need to search the second half and if the target is in the second half, then
no need to search the first half.
Either way half of the list will be eliminated from consideration.
The same process will be repeated until the target is found or it’ll be confirmed that the target is not in the
list.
The two important cases in binary searching process are:
o The target found case.
o The target not found case.
To find the middle of the list, we need three variables, one to identify the beginning of the list (first), one to
identify the middle of the list (mid), and one to identify the end of the list (last).
Target Found:
The following figure shows finding 22 in a sorted list. In our case first will be 0 and last will be 11 and mid
can be calculated as follows.
mid = (first + last) / 2;
Since the index mid is an integer, the result of will be an integral value: mid = ( 0 + 11 ) / 2 = 11 / 2 = 5
At index location 5, the target is greater than the list value ( 22 > 21 ). Therefore the list location from 0
through 5 can be eliminated.
Now in the step the first will be made as: first = mid + 1 i.e. first = 5 + 1 = 6. And further calculates the mid
by using same formulae: mid = (first + mid)/2 i.e. mid = ( 6 + 11 ) / 2 = 17 / 2 = 8.
Again the target will be tested with value at mid, this time the target is less than the list value ( 22 < 62 ).
This eliminates locations 8 through 11.
This time last will be adjusted as: last = mid – 1 i.e. last = 8 – 1 = 7 and mid = ( first + last ) / 2 = ( 6 + 7 ) /
2 = 6.
Now at mid location the value matches with the target. This will stop the search.
The target not found in the binary search is something when we searched all the possibilities and didn’t
find the target in the list.
This is done in the binary search when first becomes greater than last.
Thus only two conditions terminate the binary search algorithm: Either the target is found or first
becomes larger than last.
//Binary Search algorithm
#include <stdio.h>
int binSearch(int[],int,int);
int main(void)
{
int i, index, size, target, list[20];
system("cls"); //clrscr();
printf("Enter size of the list:");
scanf("%d",&size);
printf("Enter any %d elements:\n", size);
for(i = 0; i < size; i++)
scanf("%d", &list[i]);
printf("Enter target value:\n");
scanf("%d", &target);
index=binSearch(list,target,size);
if(index==-1)
printf("%d isn't found in the list",target);
else
printf("%d is fount at %d in the list",target,index);
getch();
return 0;
}
FUNCTIONS:
The programs we have presented so far have been very simple. They solved problems that could be
understood without too much effort.
As the program size grows and it is common practice to divide the complex program into smaller
elementary parts.
The planning for large programs is simpler. First we must understand the problem as a whole; then break it
into simpler and smaller understandable parts. We call each of these parts of a program a module and
subdividing a problem into manageable parts top-down design.
The technique used to pass data to a function is known as parameter passing.
Functions in C:
In C, the idea of top-down design is done using functions. A C program is made of one or more functions,
but one and only one of which must be named main.
The execution of the program always starts and ends with main, but it can call other functions to do some
of the job.
A function in main including main is an independent module that will be called to do a specific task. A
called function receives control from calling function.
When the called function completes its task, it returns control back to the calling function. It may or may
not return a value to the caller.
The function main is called by the operating system; main in turn calls other functions. When main is
complete, control return to the operating system.
In general, the purpose of a function is to receive zero or more pieces of data, operate on them, and return
at most one piece of data.
Like every other object in C, functions must be declared, defined and called when needed.
The function declaration needs to done before the function call, mentions the name of the function, the
return type and type and order of the formal parameters. The declaration uses only the header of the
function and ended with a semicolon.
The function definition can be coded after the function call contains the code needed to complete the task.
The function call comes within a function which calls it to get the portion of the job to be done.
A function name is used three times: for declaration, in a call and for definition.
Example programs:
void greetings()
{
printf("Hello World\n");
}
Output:
Hello World
The classification of the basic function designs is done by their return values and their parameter list.
Functions either return a value or don’t. Functions that don’t return a value are known as void functions.
Based on requirement parameter list is also optional. Either they can have parameters or don’t.
Combining the return values and parameter lists functions can be classified into four basic designs:
1. void functions without parameters
2. void functions with parameters
3. non void functions without parameters
4. non void functions with parameters
void add(void)
{
int a=10,b=20,sum;
sum=a+b;
printf("Sum of %d,%d is:%d",a,b,sum);
}
Output:
Sum of 10,20 is:30
This type of functions returns a value but don’t have any parameters.
The most common use of this design reads data from the keyboard or file and returns to the calling
function.
As this function returns a specific type of value, the function call must be initialized with variable of that
specific type.
int add()
{
int a=10,b=20,sum;
sum=a+b;
return sum;
}
Output:
Sum of a,b is:30
//Programs for getValue() function
#include <stdio.h>
int getValue(void);
void main(void)
{
int val1,val2;
val1=getValue();
val2=getValue();
printf("Val1:%d, val2:%d",val1,val2);
}
int getValue(void)
{
int val;
printf("Enter Value:");
scanf("%d",&val);
return val;
}
Output:
Enter Value:24
Enter Value:36
Val1:24, val2:36
o Like every other object in C, functions must be declared, defined and initialized (calling of the function).
o The functions defined by the user who is writing the program, but not by the developers of the language are
known as user defined functions.
o To use functions in a C-Program one has to do, the declaration, definition and initialization of the function.
o The function declaration has to be done before function call, which will give the complete picture of the
function.
o And definition will succeed function call, which actually contains the statements (body) of the function.
Function Declaration:
o Function declaration consists of only a function header. It contains no code (body of the function).
o Function declaration consists of three parts: the return type, the function name and the formal parameter
list.
o Function declaration will be terminated by a semicolon.
o The return type is the type of value the function is going to return after performing its job. If there is no
return type the type will be void type.
o In declaration the parameter list will indicate only the valid type and order of the parameters; the variable
identifier can be omitted here in this case.
o Generally the declarations are placed in the global declaration area of the program. That is before the main
function.
Function call:
Function Definition:
function header
A function header consists of three parts: the return type, the function name, and the formal parameter list.
A semicolon is not required at the end of the function definition header.
The return-type should come before the function name; return-type specifies the type of value a function
will return. If the function has nothing to return, the return type will be void.
The formal parameter list must match with the type and order of the actual parameters. Here while
specifying the formal parameters the variable identifier is must, which will hold the values passed by actual
parameters.
function body
The function body contains the local declarations and the function statements.
The body starts with local definitions that specify the variables needed by the function. After local
definition, the function statements, terminating with a return statement.
If a functions return type is void, it can be written without a return statement.
In the definition of a function, the parameters are contained in the formal parameter list.
This list declares and defines the variables that will contain the data received by the function.
If the function has no parameters; if it is not receive any data from the calling function, then the parameter
list can be void.
Local Variables:
A local variable is a variable that is defined inside a function body and used without having any role in the
communication between functions.
int getvalue()
{
int temp;
printf("Enter value:");
scanf("%d",&temp);
return temp;
}
Inter function communication is a concept through which calling function and called function will
communicate with each other, and exchange the data.
The data flow between the called and calling function can be divided into three strategies:
I. Downward flow
II. Upward flow
III. Bi-directional flow
I. Downward flow:
In downward communication, the calling function sends data to the called function.
No data flows in the opposite directions.
The called function may change the values passed, but the original values in the calling function remains
untouched.
The pass by value or call by value mechanism is a perfect solution for downward flow.
A variable is declared and defined in the called function for each value to be received from the calling
function.
Downward communication is one-way communication. The calling function can send data to the called
function, but the called function cannot send any data to the calling function.
//downward communication
#include<stdio.h>
void downFun(int,int);
void main(void)
{
int a=5;
downFun(a,15);
printf("Value of a is:%d",a);
}
Upward communication occurs when the called function sends data back to the calling function without
receiving any data from it.
C provides only one way for upward flow, the return statement.
Using return statement only one piece of data item can be returned.
To send multiple values back to the calling function, we have to use references of variables. References are
memory locations which carries the data from called function to the calling function.
//upward communication
#include<stdio.h>
void upFun(int*,int*);
void main(void)
{
int a,b;
upFun(&a,&b);
printf("Value of a, b are:%d,%d",a,b);
}
Bi-directional communication occurs when the calling function sends data down to the called function.
After processing the called function sends data up to the calling.
The strategy described for upward communication can also be used for bi-direction communication, but
with a little modification.
The only change is that the indirect reference must be used in both sides of the assignment statement.
With this change the variable in the called function first is accessed for retrieving data using address
variable in the right hand side.
The same parameter is used again to store a value in the left-hand side.
Note: both upward and bidirectional communications are examples for pass by reference or call by
reference mechanisms.
//Bi-directional communication:
#include<stdio.h>
void biFun(int*,int*);
void main(void)
{
int a=2,b=3;
biFun(&a,&b);
printf("Value of a, b are:%d,%d",a,b);
}
void biFun(int* aptr,int* bptr)
{
*aptr = *aptr+24;
*bptr = *bptr+32;
}
Value of a,b are: 26, 35
C provides a rich collection of standard functions whose definitions have been written and are ready to be
used in our programs.
To use these functions, we must include their function declarations into our program.
The function declarations are generally found in header files.
Instead of adding each declaration separately, a simple statement with header file can be included on top of
the program.
Math functions
The real functions are fabs, fabsf and fabsl. For fabs the parameter is a double, and it returns a double. For
fabsf the parameter is a float and returns a float. For fabsl the parameter is a long double and returns a long
double.
General Syntax:
double fabs(double);
float fabsf(float);
long double fabsl(long double);
// Absolute value functions
#include<stdio.h>
#include<math.h>
void main(void)
{
float val=-2.674;
float res;
res = fabsf(val);
printf("Absolute value of %f is %f", val, res);
}
Output:
Absolute value of -2.674000 is 2.674000
Ceiling Functions
// Ceiling Functions
#include<stdio.h>
#include<math.h>
void main(void)
{
float val = 2.674;
float res;
res = ceilf(val);
printf("Ceiling value of %f is %f", val, res);
val = -2.674;
res = ceilf(val);
printf("\nCeiling value of %f is %f", val, res);
}
Output:
Ceiling value of 2.674000 is 3.000000
Ceiling value of -2.674000 is -2.000000
Floor Functions
A floor is the largest integral value that is equal to or less than a number.
Example: Floor of 3.99999 is 3.0.
On number series, this function moves the number left towards an integral value.
Truncate Functions
The truncate functions return the integral value in the direction of 0.
They are same as floor functions for positive numbers and same as ceiling function for negative numbers.
Their function declarations are:
double trunc (double);
float truncf (float);
long double truncl (long double);
Round Functions
The round functions return the nearest integral value.
Their function declarations are:
double round (double);
float roundf(float);
long double roundl(long double);
Power Functions:
The power (pow) function return the value of the x raised to the power of y.
An error occurs if the base (x) is negative and the exponent (y) is not an interger, or if the base is zero and
the exponent is not positive.
Individual data values of arrays can be passed using their index along with array name.
As long as the type is matching, the called function is unaware whether the value is coming from an array
or a normal variable.
Passing Addresses
The address of the elements of the array can also be passed to the function.
The individual element addresses can be passed just like any other variable address.
To pass an array element’s address, the address operator can be prefixed to the element’s indexed
reference.
Example: The address of 4th element in the array can be passed in following way: &arr[3];
Passing an address of an array element requires two changes in the called function.
Output:
Parameter received from calling function: 6
Array element after function call: 36
In C, the name of an array holds the address of the first element in the array.
Using array name and index values the complete array elements can be accessed.
Passing the array name instead of a single element, allows the called function to refer to the same array
back in the calling function.
//Passing whole array to called function
#include<stdio.h>
void arrAccess(int[]);
void main(void)
{
int a[5]={2,4,3,6,9},i;
arrAccess(a);
printf("\nAfter function call Elements in Array:");
for(i=0;i<5;i++)
printf("%d ", a[i]);
}
RECURSION
Programmers use two approaches for writing repetitive algorithms: One approach uses loops and the other
uses recursion.
Recursion is a repetitive process in which a function calls itself.
Some older languages do not support recursion. One major language that does not support recursion is
COBOL.
To study the concept of recursion let us consider the example of finding factorial of a given number.
In our study we’ll see both iterative definition and recursive definition for finding the factorial.
Iterative Definition
The factorial of a number is the product of the integral values from 1 to the given number.
The iterative definition can be shown as:
An iterative function can be defined which will take only the iteration counter to calculate the factorial but
not the function call.
Example: factorial (4) = 4 * 3 * 2 * 1 = 24
Recursive Definition
A function is defined recursively whenever the function itself appears within the definition itself.
The recursive definition of factorial function can be shown as:
The decomposition of factorial (3), using the above formula is shown in the following formula.
Observe it carefully; the recursive solution for a problem involves a two-way journey: the decomposition
will be from top to bottom, and then we solve it from bottom to the top.
Every recursive call must either solve part of the problem or reduce the size of the problem.
The recursive calculation looks more difficult when using pen and paper, but it is often much easier and
more elegant solution when a computer is used.
Every recursive solution to the problem will have a base-case and general-case. A base-case will provide
the solution to the problem and all other cases will be known as general-cases.
In the factorial example the base-case is factorial of (0) and all other cases are general-cases.
Fibonacci Numbers
void fibonacci(int n)
{
int i, term1 = 0, term2 =1, nextTerm;
for (i = 1; i <= n; ++i)
{
printf("%d, ", term1);
nextTerm = term1 + term2;
term1 = term2;
term2 = nextTerm;
}
}
Output:
Enter the number of terms: 6
0, 1, 1, 2, 3, 5,
Recursive solution to factorial problem
int fibonacci(int n)
{
if(n == 0 || n == 1)
return n;
return (fibonacci(n - 1) + fibonacci(n - 2));
}
Output:
Enter the nuumber of terms:6
Fibonacci series terms are:
0, 1, 1, 2, 3, 5,
The HCF (Highest Common Factor) or GCD (Greatest Common Divisor) of two integers is the largest
integer that can exactly divide both numbers (without a remainder).
Each element in a structure is called a field. A field is the smallest element of named data that has meaning.
It has many of the characteristics of the variables. It has a type, an identifier and it also exists in the
memory. It can be initialized a value, and later can be used for manipulations. The only difference between
the variable and a structure field is that, structure field is a part of the structure.
The difference between an array and a structure is that, all elements in an array must be of same type, but
the elements in a structure can be of same or different types.
A structure is a convenient way in which data are grouped into one single name. It provides flexibility and
an increased control over accessing the data when it needed. Using structures data can be accessed as a
single grouped object or individual elements can be accessed.
1. Tagged Structures:
It is a more powerful way of declaring a structure. By using the keyword typedef the structure will be declared.
Syntax: Example:
typedef struct typedef struct
{ {
Filed list; char name[20];
}TYPE; char ID[10];
int marks;
}STUDENT;
The type-defined structure differs from the tagged declarations in two ways:
First, the keyword, type-def, is added in the beginning of the declaration.
Second, an identifier is required at the end of the block. The identifier will be the structure
type name.
After a structure has been declared, a variable of structure type can created using it.
The structure type can be declared in the global area of the program, to make it visible to all functions.
The structure variables are declared in the local declarations.
Initialization
The rules for structure initialization are similar to the rules for array initialization.
The initializing values are enclosed in braces and separated by commas.
They must match the corresponding types in the structure definition.
Examples:
Accessing Structures:
The elements in a structure can be accessed individually or the complete structure can assigned as a whole.
Structure fields can be accessed and manipulated using operators just like any other normal variables.
To refer to a field in a structure the structure and the field both has to be referred.
C uses a hierarchical naming convention that first uses the structure variable identifier and then the field
identifier.
The structure variable identifier is separated from the field identifier by a dot.
The dot is known as the direct selection operator.
Example1: Example2:
aStudent.ID SAMPLE sam1={2,5,3.2,’A’};
aStudent.name scanf(“%d %d %f %c”, &sam1.x, &sam1.y,
aStudent.marks &sam1.t, &sam1.u);
prinf(“%d %d %f %c”, sam1.x, sam1.y,
sam1.t, sam1.u);
void main(void)
{
//declaring, defining and initializing the structure variable sam1
SAMPLE sam1 = {5,4,3.2,'A'};
SAMPLE sam2;
printf("sam1 contents:\n");
printf("%d %d %f %c", sam1.x,sam1.y,sam1.t,sam1.u);
printf("\nEnter contents for sam2:\n");
scanf("%d %d %f %c",&sam2.x,&sam2.y,&sam2.t,&sam2.u);
//Modifying sam1
sam1.x=45;
sam1.y=32;
sam1.t=5.4;
sam1.u='d';
printf("\nsam1 contents after modification:");
printf("%d %d %f %c", sam1.x,sam1.y,sam1.t,sam1.u);
printf("\nsam2 contents after modification:");
printf("%d %d %f %c", sam2.x,sam2.y,sam2.t,sam2.u);
}
Output:
sam1 contents:
5 4 3.200000 A
Enter contents for sam2:
3 5 2.45 s
Only one operation is allowed on the structure that is the assignment of a structure to another structure.
A structure can only be copied to another structure of the same type using the assignment operator.
When one structure needs to be copied to another structure, instead of assigning the individual members to
another structure’s members, the whole structure can be initialized to another structure.
void main(void)
{
//declaring, defining and initializing the structure variable sam1
SAMPLE sam1 = {5,4,3.2,'A'};
SAMPLE sam2;
sam2 = sam1;
printf("sam1 contents:\n");
printf("%d %d %f %c", sam1.x,sam1.y,sam1.t,sam1.u);
printf("\nsam2 contents:\n");
printf("%d %d %f %c", sam2.x,sam2.y,sam2.t,sam2.u);
}
Output:
sam1 contents:
5 4 3.200000 A
sam2 contents:
5 4 3.200000 A
Pointer to structure:
The parenthesis in the above example are absolutely required, without the parenthesis the compiler will
consider *ptr.x as *(ptr.x). C applies the dot (.) operator first and then the asterisk operator next.
The reason the parenthesis are needed is that the precedence of the direct selection operator (.) is higher
than the indirection operator (*).
Here *ptr.x will be interpreted as *(ptr.x) which is wrong. *(ptr.x) means a completely different undefined
structure called ptr that contains a member x, which must be a pointer. Since this is not true, a compile time
error will be generated.
To avoid the above confusion (to eliminate the problem with pointers to structures) a special operator
known as indirect selection operator is used.
The symbol used for indirect selection operator is an arrow formed by minus sign and the grater than
symbol (->).
The indirection operator is placed between the pointer identifier of structure and the member to be
referenced.
void main(void)
{
//declaring, defining and initializing the structure variable sam1
SAMPLE sam1 = {5,4,3.2,'A'};
SAMPLE* strPtr;
strPtr = &sam1;
printf("Accessing sam1 contents through structure variable and direct selection operator (dot(.)):\n");
printf("%d %d %f %c", sam1.x,sam1.y,sam1.t,sam1.u);
printf("\nAccessing sam1 contents through pointer to structure and direct selection operator (dot(.)):\n");
printf("%d %d %f %c", (*strPtr).x,(*strPtr).y,(*strPtr).t,(*strPtr).u);
printf("\nAccessing sam1 contents through pointer to structure and indirect selection operator (->):\n");
printf("%d %d %f %c", strPtr->x,strPtr->y,strPtr->t,strPtr->u);
}
Output:
Accessing sam1 contents through structure variable and direct selection operator (dot(.)):
5 4 3.200000 A
Accessing sam1 contents through pointer to structure and direct selection operator (dot(.)):
5 4 3.200000 A
Accessing sam1 contents through pointer to structure and indirect selection operator (->):
5 4 3.200000 A
COMPLEX STRUCTURES
Structures within structures (nested structure), arrays within structure, and arrays of structures are some of
the complex forms of structures.
i. Nested Structures
ii. Structures containing Arrays
iii. Structures containing pointers
iv. Array of structures
i. Nested Structures:
Example:
//type declarations
typedef struct
{
int month;
int day;
int year;
}DATE;
typedef struct
// A more complex form {
typedef struct int hour;
{ int min;
STAMP startTime; int sec;
STAMP endTime; }TIME;
}JOB;
typedef struct
//variable declaration {
JOB job; DATE date;
TIME time;
}STAMP;
//variable declarations
STAMP stamp;
The most important point to remember when nesting structures is, they must be declared from inside
out. That is they must be declared from lowest level to the highest level. When nesting a structure into
the other structure the inner structure must be declared first before its inclusion.
To access fields of nested structures the direct referencing operator dot(.) is used from highest level to
inner component level.
stamp stamp
stamp.date stamp.time
stamp.date.month stamp.time.hour
stamp.date.day stamp.time.min
stamp.date.year stamp.time.sec
job.startTime.time.hour
job.endTime.time.hour
To initialize a Nested Structure simply pass the values using sets to the outermost structure variable using
assignment operator.
The outermost structure will have the instances of inner structure and hence initializes the values
accordingly.
typedef struct
{
int hour;
int min;
int sec;
}TIME;
typedef struct
{
DATE date;
TIME time;
}TIMESTAMP;
void main(void)
{
TIMESTAMP tstamp = {{05, 10, 2019}, {23, 45, 01}};
printf("Event Date (mm:dd:yyyy): %d / %d / %d", tstamp.date.month, tstamp.date.day, tstamp.date.Year);
printf("\nEvent Time (hh:mm:ss): %d : %d : %d", tstamp.time.hour, tstamp.time.min, tstamp.time.sec);
}
Output:
Event Date (mm:dd:yyyy): 5 / 10 / 2019
Event Time (hh:mm:ss): 23 : 45 : 1
To define arrays within structures just defined in their regular approach within the structure.
Referencing arrays within a structure is same like referencing other elements from the structure.
First we need to qualify the element with structure name and then with index or pointer the array can be
accessed from the structure.
Initializing Arrays within a structure
Since array is a separate member and it will have other members as part of it, hence the value for an array
within a structure must be separated using a set of braces.
Example:
void main(void)
{
STUDENT student = {"John", {18, 17, 15}};
student.final = student.midterm[0]+student.midterm[1]+student.midterm[2];
printf("Student Name: %s",student.name);
printf("\nStudent midterm Marks: %d %d %d", student.midterm[0], student.midterm[1], student.midterm[2]);
printf("\nStudent Final Marks: %d", student.final);
}
Output:
Student Name: John
Student midterm Marks: 18 17 15
Student Final Marks: 50
Point of Consideration:
A pointer can be used to refer directly the array elements within a structure.
Consider the above example to store the starting location of midterm array a pointer pScore can be used.
Later using this pScore one can access the complete array midterm without depending on the structure.
Example:
int* pScore = student.midterm;
int total = *pScore + *(pScore+1) + *(pScore+2);
typedef struct
{
DATE date;
}STAMP;
//variable declarations
STAMP tstamp;
//Initialization
stamp.date.month = may;
typedef struct
{
DATE date;
}TIMESTAMP;
void main(void)
{
TIMESTAMP tStamp = {"May", 9, 2019};
printf("Event DATE: %dth %s - %d", tStamp.date.day, tStamp.date.month, tStamp.date.year);
}
Output:
Event DATE: 9th May - 2019
void main(void)
{
STUDENT std[5];
int i;
// storing information
for(i=0; i<5; i++)
{
std[i].rollno = i+1;
printf("\n");
}
printf("Displaying Information:\n\n");
// displaying information
for(i=0; i<5; i++)
{
printf("\nRoll number: %d\n",std[i].rollno);
printf("Name: ");
puts(std[i].name);
printf("Marks: %d %d %d",std[i].midmarks[0], std[i].midmarks[1], std[i].midmarks[2]);
printf("\n");
}
}
Output:
Enter information of students:
Displaying Information:
Roll number: 1
Name: John
Marks: 12 13 15
Roll number: 2
Name: Asif
Marks: 15 17 19
UNIONS
typedef union
{
char chAry[2];
int num;
}SHAREDATA;
Referencing Unions
When a union is being referenced through a pointer, the indirect selection operator ( ) can be used.
SHAREDATA* ptrShareData;
ptrShareDatanum;
ptrShareDatachAry[0];
ptrShareDatachAry[1];
Initializing a Union:
Only the first type declared in the union can be initialized when the union variable is defined. The other
types can be initialized by assigning values or reading values into the union.
When initializing a union, the value must be enclosed in a set of braces, even if there is only one value.
//Demonstration of Unions
#include<stdio.h>
typedef union
{
int num;
char chAry[2];
}SHAREDATA;
void main(void)
{
SHAREDATA shareData;
shareData.num = 16706;
printf("Integer Value: %d", shareData.num);
shareData.chAry[0] = 'X';
shareData.chAry[1] = 'Y';
printf("\nValues from character array: %c %c",shareData.chAry[0], shareData.chAry[1]);
printf("\nInteger Value: %d", shareData.num);
}
Output:
Integer Value: 16706
Values from character array: X Y
Integer Value: 22872
DIFFERENCE BETWEEN UNION AND STRUCTURE
POINTERS
Introduction:
A pointer is a constant or variable that contains an address that can be used to access data.
Pointers are built on the basis of pointer constants.
Pointer constant:
A pointer constant is an address value that specifically represents a memory location in the computers main
memory.
Like every other constant in computer world a character constant cannot be changed.
Every time a program runs all variables in the program will get different addresses, this is because in a
computer modern operating systems can put a program in memory wherever it feels convenient.
Pointer constants are drawn from the set of addresses of a computer. They exist during the run time of a
computer. We cannot change them but we can only use them.
Being existed in the computer a pointer constant can be retrieved and saved inside a variable.
The address operator (&) extracts the address of a variable. Syntax: &variable_name
To print the address of a variable the conversion code %p can be used.
MD AFZAL Mob: 8179700193
Asst. Professor mdafzal.mbnr@gmail.com
//Printing the address of variables
#include<stdio.h>
int main(void)
{
char a, b;
system(“cls”); //clrscr();
printf(“%p %p”, &a, &b);
getch();
return 0;
}
Output:
142300
142301
Pointer Variables:
A pointer constant can be saved in a pointer variable, and later can be used to access the value.
The type of a pointer must be specific to the type of the variable to which it is going to point. That is an
integer type of variables address can be saved into an integer type of pointer.
To store the address of a variable we need a special type of variable that is Pointer variable.
A single variables address can be saved into multiple pointers, so that we’ll have more number of pointers
pointing to the same location, and it is possible in C.
If a Pointer variable not pointing to anywhere, that is if we want to make sure that a pointer is not pointing
to any address, C provides a special null pointer (NULL) in the standard Input/Output stdio.h header file
for this purpose.
The indirection operator (*) can be used to dereference the pointer’s address.
The indirection operator is a unary operator whose operand must be a pointer value. The result is, a pointed
variables value that can be used for inspection or manipulation.
To access the variable a through pointer p, simply code *p.
To add 1 to the variable a’s content any of the following ways can be used
a++ a=a+1 *p=*p+1 (*p)++
The indirection and address operators are the inverse of each other, and when combined in an expression
they cancel each other. *&x SAME x
To declare a pointer variable the asterisk symbol (*) can be used along with type specification.
The following figure shows the declaration and definition of different pointer variables and their
corresponding data variable declarations.
Declaration Vs Redirection:
The asterisk operator can be used in two different contexts: for declaration and for redirection.
When asterisk is used for declaration, it is associated with a type.
Example: int* ptr; will declare an integer pointer.
When asterisk is used for redirection, it is associated with a pointer variable to get the data value of the
variable whose address is stored in that pointer.
Example: sum = *aptr + *bptr;
Like every other object in C, pointers must be initialized, before they can be used in the program.
Like variables, without initialization pointers will also have an unknown garbage value in them.
When program starts all uninitialized pointers will hold some unknown addresses which are pointing to
some unknown values.
Pointers to Pointers
In C, it is possible to use pointers that points to other pointers. That is, we can have a pointer pointing to a
pointer to an integer.
The following figure demonstrates this two level indirection:
Each level of pointer indirection requires a separate indirection operator when it is dereferenced.
#include<stdio.h>
int main(void)
{
int a;
int* p;
int** q;
int*** r;
system(“cls”); //clrscr();
p = &a;
q = &p;
r = &q;
printf("Enter a value:");
scanf("%d",&a);
printf("a's value is:%d",a);
printf("\nEnter a value:");
scanf("%d",p);
printf("a's value: %d %d", a, *p);
printf("\nEnter a value:");
scanf("%d",*q);
printf("a's value: %d %d %d", a, *p, **q);
printf("\nEnter a value:");
scanf("%d",**r);
printf("a's value: %d %d %d %d", a, *p, **q, ***r);
getch();
return 0;
}
Output:
Enter a value:4
a's value is:4
Enter a value:5
a's value: 5 5
Enter a value:6
a's value: 6 6 6
Enter a value:7
a's value: 7 7 7 7
A pointer to void is a generic type that is not associated with a reference type, that is it is not the address of
a character, an integer, a floating point or any other type.
It is compatible for assignment purpose only with all other types.
The name of an array is a pointer constant to the first element in the array. As it is a pointer constant its
value cannot be changed, that is it cannot be used as an lvalue.
The name of an array and the first element address both will represent the same memory location in
computer memory.
When the array name is dereferenced it is like dereferencing the first element of the array; that is it gives
the value of the first element array[0].
Remember, when array name is dereferenced, it refers only to the first element, not the whole array.
Besides indexing, programmers use another powerful method of moving through an array: pointer
arithmetic.
Pointer arithmetic offers a set of arithmetic operators for manipulating the addresses in pointer.
This technique is used to move back and forth through an array from element to element.
Having an array a, then ‘a’ is a constant pointing to the first element and a+1 is a constant pointing to the
second element.
If a pointer ptr is pointing to the second element of the array, then p-1 is a pointer pointing to the previous
(first) element and p+1 is a pointer to the next (third) element.
Given an array a, a+2 is the address two elements away from a, and a+3 is the address three elements away
from a. So the generalized notation will be as follows:
Given pointer ptr, ptr±n is a pointer to the value n elements away from ptr.
Indirection operator can be applied on pointer arithmetic to access the value from the location where the
pointer is pointing after pointer arithmetic.
Self-Referential Structures:
Self-Referential structures holds one or more pointers which point to the same structure type of structure,
as their member.
In simple words, structures pointing to the same type of structures are self-referential structure.
A self-Referential structure is essentially a structure definition which includes at least one member that is a
pointer to the structure of its own type.
See the following declaration of a tagged structure:
struct NODE
{
int data;
struct NODE* link;
};
The above illustrated structure declaration describes one NODE that comprises of two logical segments.
One of them stores data and the other one is a pointer indicating where the next component can be found. .
Several such inter-connected nodes create a chain of structures known as linked list.
The above declaration of structure can be used to create a chain of nodes, where each node is going to hold
some data and a link to another node.
Several of such nodes can be created and connected to form a data-structure known as linked list.
The above NODE is having only one data element and a link to the one other NODE of the same type. As
the NODE is having only a single linking pointer between the NODEs, we can also call the data structure
as single linked list.
The following program demonstrate the concept of single linked list:
struct NODE {
int data;
struct NODE* link;
};
#include <stdio.h>
struct NODE {
int data;
struct NODE* link;
};
int main(void)
{
struct NODE node1, node2, node3; // Node1
system("cls"); //clrscr();
// Initialization node1
node1.link = NULL;
node1.data = 10;
// Initialization node2
node2.link = NULL;
node2.data = 20;
// Initialization node3
node3.link = NULL;
node3.data = 30;
Self-referential structures are very useful in applications that involve linked data structures, such as linked
lists.
Unlike a static data structure such as array where the number of elements that can be inserted in the array is
limited by the size of the array, a self-referential structure can dynamically be expanded or contracted.
Operations like insertion or deletion of nodes in a self- referential structure involve simple and straight
forward alteration of pointers.
Memory Usage:
Memory allocated to a program is divided into program memory and data memory.
Program memory consists of memory used for main and all called functions.
Data memory consists of permanent definitions of global and local data and constants, dynamic data
memory.
main() function must be in memory all the time. Each called function must be in memory only when it is
called and becomes active.
If a function called more than once, the copies of the local variables of this function will be maintained
inside stack memory.
In addition to the stack memory, a separate memory area known as heap is also available. Heap memory is
unused memory allocated to the program and available to be assigned during execution. It is the memory
pool from which the memory is allocated when requested by the memory allocation functions.
Static memory allocation requires that the declaration and definition of memory be fully specified in the
source program.
The number of bytes reserved cannot be changed during run time of the program.
So far we used this technique for reserving memory for variables, arrays and pointers.
Dynamic memory allocation uses predefined functions to allocate and release memory for data while the
program is running.
Unlike static memory allocations, dynamic memory allocations have no identifier associated with it. It can
be accessed only through an address. That is to access data in dynamic memory we need a pointer.
The malloc() function allocates a block of memory that contains the number of bytes specified in its
parameter.
void main(void)
{
int* ptr;
int n, i, sum = 0;
void main(void)
{
int* ptr;
int n, i, sum = 0;
The realloc() function is advised to be used with much care. As a minor issue in the usage will lead to the
crash of the program.
Given a pointer to a previously allocated block of memory, realloc changes the size of the block by
deleting or extending the memory at the end of the block.
If the memory cannot be extended because of other allocations, realloc allocates a completely new block,
copies the existing memory locations to the new allocations, and deletes the old locations.
Syntax: void* realloc(void* ptr, int newSize);
void main(void)
{
int* ptr;
int n, i, sum = 0;
free(ptr);
}
Output:
Enter the number of elements you need from heap:2
Memory successfully allocated using calloc.
Enter 2 elements into the heap:4
2
The elements in heap are: 4, 2,
Enter the new size of heap:4
Memory successfully allocated using realloc.
Enter 4 elements into the heap:2
3
4
5
The elements in heap are: 2, 3, 4, 5,
Releasing Memory (free())
When memory locations allocated by malloc, calloc or realloc are no longer needed, they should be freed
using the free() function.
It is an error to free memory with a null pointer, a pointer to other than the first element of an allocated
block, a pointer that is different type than the pointer that allocated the memory.
It is also an error to refer to memory after it has been released.
Syntax: void free(void* ptr);
A file is an external collection of related data treated as a single unit. The primary purpose of a file is to
keep a record of data.
As the contents of primary memory are not permanent, and they will be lost when the computer is shut
down, we need files to store the data permanently.
Sometimes the collection of data will become too large to be maintained in main memory; in this case files
can be used to store the data in secondary memory.
Files are stored permanently in auxiliary or secondary memory, the most common secondary storage
devices are hard disk, CD, DVD and tape.
When the computer reads, the data move from the external device to memory and when it writes the data
move from memory to the external device.
This data movement uses a special work area known as a buffer. A buffer is a temporary storage area that
holds data when it is in transfer to or from the memory. The buffer acts like a synchronizer between the
physical devices and memory.
When a file is processed for data input, the data is read from the file up to the end of file (EOF). End file is
the terminator of the file which indicates the completion of data processing in the file.
The EOF will be automatically read and supplied to the program and it is the responsibility of the
programmer to keep track of it.
When a program is terminated, the entire data is lost. Storing in a file will preserve your data even if the
program terminates.
If you have to enter a large number of data, it will take a lot of time to enter them all. If you have a file
containing all the data, you can easily access the contents of the file using few commands in C.
You can easily move your data from one computer to another without any changes.
Types of Files
There are two types of files:
1. Text files
2. Binary files
1. Text files
Text files are the normal .txt files that you can easily create using Notepad or any simple text editors.
Generally text files consists of sequence of characters divided into lines with each line terminated by a
newline (\n).
When you open those files, you'll see all the contents within the file as plain text. You can easily edit or
delete the contents.
They take minimum effort to maintain, are easily readable, and provide least security and takes bigger
storage space.
2. Binary files
In C, you can perform four major operations on the file, either text or binary:
When working with files, you need to declare a pointer of type file. This declaration is needed for
communication between the file and program.
Syntax: FILE *fptr;
Here FILE is a predefined structure definition in stdio.h library file.
Note the * asterisk after the file type (FILE). It indicates that fptr is a pointer variable that contains the
address of the stream of file.
Opening a file is performed using the library function in the "stdio.h" header file: fopen().
The syntax for opening a file in standard I/O is: fptr = fopen("file_to_open","mode")
For Example: fopen("E:\\cprogram\\newprogram.txt","w");
Let's suppose the file newprogram.txt doesn't exist in the location E:\cprogram. The first function creates a
new file named newprogram.txt and opens it for writing as per the mode 'w'.
The writing mode allows you to create and edit (overwrite) the contents of the file.
fgetc() & fputc functions: Reading and Writing characters to a text file
Character input/output functions read/write one character at a time from/to a text stream.
These functions are divided into two general groups:
1. Input/output functions used only with terminal devices.
2. Input/output functions used with both terminal devices and text files.
When the file is no longer needed it should be closed to free the system resources.
Closing a file is performed using library function fclose().
Syntax: fclose(fptr); //fptr is the file pointer associated with file to be closed.
void main(void)
{
int num;
FILE *fptr;
fptr = fopen("C:\\program.txt","w");
if(fptr == NULL)
{
printf("No such file exitst…!");
exit(1);
}
fprintf(fptr,"%d",num);
fclose(fptr);
}
Output:
This program takes a number from user and stores in the file program.txt.
After you compile and run this program, you can see a text file program.txt created in C drive of your
computer. When you open the file, you can see the integer you entered.
void main(void)
{
int num;
FILE *fptr;
fscanf(fptr,"%d", &num);
If you have many records inside a file and need to access a record at a specific position, you need to loop
through all the records before it to get the record.
This will waste a lot of memory and operation time. An easier way to get to the required data can be
achieved using fseek().
As the name suggests, fseek() seeks the cursor to the given record in the file.
Syntax: void fseek(FILE * stream, long int offset, int whence)
o The first parameter stream is the pointer to the file. The second parameter is the position of the
record to be found, and the third parameter specifies the location where the offset starts.
Whence Meaning
SEEK_CUR Starts the offset from the current location of the cursor in the file.
void main(void)
{
FILE *fp;
fp = fopen("test.txt", "r");
ftell() in C is used to find out the position of file pointer in the file with respect to starting of the file.
Syntax of ftell() is: long ftell(FILE *pointer).
Consider below C program.
When the fscanf statement is executed word “Someone” is stored in string and the pointer is moved beyond
“Someone”. Therefore ftell(fp) returns 7 as length of “someone” is 6.
#include<stdio.h>
void main(void)
{
/* Opening file in read mode */
FILE *fp = fopen("test.txt","r");
The rewind function sets the file position indicator (file marker) to the beginning of the file irrespective of
its current location.
General Syntax: void rewind(FILE *fp);
It is equivalent to: void fseek(stream, 0L, SEEK_SET);
#include <stdio.h>
int main () {
char str[] = "ISL Engineering College.";
FILE *fp;
int ch;
}
fclose(fp);
return(0);
}
Output: file.txt
This is ISL Engineering College. This is ISL Engineering College.
This is ISL Engineering College.