Programming Languages

Crescent Institute of Technology and Management
Kalingarajapuram, Kanjampuram Post
Diploma in Software Engineering
Syllabus
PAPER-11 PROGRAMMIMG LANGUAGE
UNIT-1 DATA STRUCTURE & ALGORITHMS
Data Structure Overview –Arrays- Stacks and Queues- Application of Stacks and
Queues – Sparse Matrix-String and Character Manipulations-Linked Lists-Singly
Linked List-Doubly Lined List – Tree Structures - Graphs – Sorting – Searching Strategies.
UNIT-11 LINUX
History of Linux-Requirements-Installing Linux-Linux and Interest Networking
protocols in Linux- creating Network interfaces and Configuration- Using PPP in
Linux-Configuring DHCP-IP Masquerading- Security- Using K Development
Environment (KDE)
UNIT-111 PRINCIPLES OF OOPS & PROGRAMMING IN C++
Software Evaluation –benefits of OOPs – Objects- Classes-DataAbstraction-Data
Encapsulation-Inheritance-Polymorphism-Binding-Application of OOPs.
Data Types-Operations-Control Statements-Arrays-Structures-Unions-Pointers-Bit
Fields-User Defined Functions-Call by value-Call by reference-Default Functions-0
Functions over Loading – Friend Function- Virtual Function- Library Function.
UNIT – 1V PROGRAMMING BASED ON OOPS
Classes and Objects-Contructors-Destructors – Inheritance-interfaces Operators
Over Loading-Type Conversions – Derived Classes – Virtual Functions and runtime
Polymorphism and polymorphism based Programming.
UNIT-V CONSOLE I/O OPERATIONS
C++ Streams- Stream Classes – formatted I/O Operatons-Unformatted I/O
Operations – Manipulators- Introduction to Files – Opening and Closing filesReading, Writing a Character from a File – Structure File Operations- Classes and
Files Operations-Random ACCESS File Programming- Command Line ArgumentsError Handling.
Unit 1
Text Introduction to Data Structures By Adam drozdex-Vikas
Publishing.
Ref: Fundamentals of Data Structures By Ellis Horowitz Sartraj
Sahni
Unit2
Ref: Limux Complete by Grant Taylor- BPB
Unit3,4, &5 Text: Object Oriented Programming with C++, E.
Balagurusamy – Tata Mc Hill
Ref: Programming with C++, Ravichandran.
UNIT-1
1.0 Tree Data Structures
3 Tree Ttt0. Tre30. Treee
30Tree represents the nodes connected by edges. We will discuss binary
tree or binary search tree specifically.
Binary Tree is a special data structure used for data storage purposes. A
binary tree has a special condition that each node can have a maximum
of two children. A binary tree has the benefits of both an ordered array
and a linked list as search is as quick as in a sorted array and insertion or
deletion operation are as fast as in linked list.
.Tree30.Tree
Important Terms
Following are the important terms with respect to tree.
· Path − Path refers to the sequence of nodes along the edges of a tree.
· Root – The node at the top of the tree is called root. There is only one
root per tree and one path from the root node to any node.
· Parent − Any node except the root node has one edge upward to a
node called parent.
· Child – The node below a given node connected by its edge
downward is called its child node.
· Leaf – The node which does not have any child node is called the leaf
node.
· Subtree − Subtree represents the descendants of a node.
· Visiting − Visiting refers to checking the value of a node when control
is on the node.
· Traversing − Traversing means passing through nodes in a specific
order.
· Levels − Level of a node represents the generation of a node. If the
root node isat level 0, then its next child node is at level 1, its grandchild
is at level 2, and soon.
· Keys − Key represents a value of a node based on which a search
operation is tobe carried out for a node.
1.1 Binary Search Tree Representation
Binary Search tree exhibits a special behavior. A node's left child must
have a value less than its parent's value and the node's right child must
have a value greater than its parent value.
We're going to implement tree using node object and connecting them
through references
Tree Node
The code to write a tree node would be similar to what is given below. It
has a data part and references to its left and right child nodes.
struct node {
int data;
struct node *leftChild;
struct node *rightChild;
};
In a tree, all nodes share common construct.
1.2 BST Basic Operations
The basic operations that can be performed on a binary search tree data
structure, are the following –
· Insert − Inserts an element in a tree/create a tree.
· Search − Searches an element in a tree.
· Pre-order Traversal − Traverses a tree in a pre-order manner.
· In-order Traversal − Traverses a tree in an in-order manner.
· Post-order Traversal − Traverses a tree in a post-order manner.
Insert Operation
The very first insertion creates the tree. Afterwards, whenever an element
is to be inserted, first locate its proper location. Start searching from the
root node, then if the data is less than the key value, search for the empty
location in the left subtree and insertthe data. Otherwise, search for the
empty location in the right subtree and insert the data.
Algorithm
.
If root is NULL
then create root node
return
If root exists then
compare the data with node.data
while until insertion position is located
If data is greater than node.data
goto right subtree
else
goto left subtree
endwhile
insert data
end If
Implementation
The implementation of insert function should look like this –
void insert(int data) {
struct node *tempNode = (struct node*) malloc(sizeof(struct
node));
struct node *current;
struct node *parent;
tempNode->data = data;
tempNode->leftChild = NULL;
tempNode->rightChild = NULL;
//if tree is empty, create root node
if(root == NULL) {
root = tempNode;
}else {
current = root;
parent = NULL;
while(1) {
parent = current
//go to left of the tree
if(data < parent->data) {
current = current->leftChild;
//insert to the left
if(current == NULL) {
parent->leftChild = tempNode;
return;
}
}
//go to right of the tree
else {
current = current->rightChild;
//go to right of the tree
else {
current = current->rightChild;
//insert to the right
if(current == NULL) {
parent->rightChild = tempNode;
return;
}
}
}
}
2.0 Tree Traversal
T Tree Traversal
Traversal is a process to visit all the nodes of a tree and may print their
values too.
Because, all nodes are connected via edges (links) we always start from
the root (head) node. That is, we cannot randomly access a node in a tree.
There are three ways which we use to traverse a tree –
· In-order Traversal
· Pre-order Traversal
· Post-order Traversal
Generally, we traverse a tree to search or locate a given item or key in the
tree or to print all the values it contains.Tree Traversalre
In-order Traversalre
In this traversal method, the left sub tree is visited first, then the root and
later the right sub-tree. We should always remember that every node may
represent a sub tree itself. If a binary tree is traversed in-order, the output
will produce sorted key values in an ascending order
We start from A, and following in-order traversal, we move to its left sub
tree B. B is also traversed in-order. The process goes on until all the nodes
are visited. The output of in order traversal of this tree will be –
D → B → E → A→ F → C → GTrave
Algorithm
Until all nodes are traversed –
Step 1 − Recursively traverse left sub tree
Step 2 − Visit root node
Step 3 − Recursively traverse right sub tree.
Pre-order TraversalTr
avIn this traversal method, the root node is visited first, then the left
subtree and finally the right subtree.
We start from A, and following pre-order traversal, we first visit A itself
and then move toits left subtree B. B is also traversed pre-order. The
process goes on until all the nodes are visited. The output of pre-order
traversal of this tree will be –
A → B → D → E → C → F → Gersa
Algorithmal
Until all nodes are traversed –
Step 1 − Visit root node.
Step 2 − Recursively traverse left subtree.
Step 3 − Recursively traverse right subtree. Tree Travers
Post-order Traversal
In this traversal method, the root node is visited last, hence the name. First
we traverse the left subtree, then the right subtree and finally the root
node.
We start from A, and following pre-order traversal, we first visit the left
subtree B. B isalso traversed post-order. The process goes on until all the
nodes are visited. The outputof post-order traversal of this tree will be –
D→E→B→F→G→C→A
Algorithm
Until all nodes are traversed –
Step 1 − Recursively traverse left subtree.
Step 2 − Recursively traverse right subtree
.
Step 3 − Visit root node.
3.0 Binary Search Tree
A Binary Search Tree (BST) is a tree in which all the nodes follow the
below-mentioned properties –
· The left sub-tree of a node has a key less than or equal to its parent
node's key.
· The right sub-tree of a node has a key greater than or equal to its parent
node's key.
Thus, BST divides all its sub-trees into two segments; the left sub-tree and
the right subtree and can be defined as−
left_subtree (keys) ≤ node (key) ≤ right_subtree (keys)
Representation
BST is a collection of nodes arranged in a way where they maintain BST
properties. Eachnode has a key and an associated value. While searching,
the desired key is compared tothe keys in BST and if found, the associated
value is retrieved.
Following is a pictorial representation of BST −
We observe that the root node key (27) has all less-valued keys on the left
sub-tree and the higher valued keys on the right sub-tree.
Basic Operations
S
Following are the basic operations of a tree –
· Search − Searches an element in a tree.
· Insert − Inserts an element in a tree.
· Pre-order Traversal − Traverses a tree in a pre-order manner.
· In-order Traversal − Traverses a tree in an in-order manner.
• Post-order Traversal − Traverses a tree in a post-order mannerear
Nodec
Define a node having some data, references to its left and right child
nodes.
struct node {
int data;
struct node *leftChild;
struct node *rightChild;
};
AVL TREE
What if the input to binary search tree comes in a sorted (ascending or
descending) manner? It will then look like this –
It is observed that BST's worst-case performance is closest to linear search
algorithms,that is Ο(n). In real-time data, we cannot predict data pattern
and their frequencies. So,a need arises to balance out the existing BST.
Named after their inventor Adelson, Velski &Landis, AVL trees are
height balancing binary search tree. AVL tree checks the height of the left
and the right sub-trees and assures that the difference is not more than 1.
This difference is called the Balance Factor.
Here we see that the first tree is balanced and the next two trees are not
balanced –
In the second tree, the left sub tree of C has height 2 and the right sub tree
has height 0, so the difference is 2. In the third tree, the right sub tree of
A has height 2 and the left is missing, so it is 0, and the difference is 2
again. AVL tree permits difference (balance factor) to be only 1.
Balance Factor = height(left-sutree) − height(right-sutree)
If the difference in the height of left and right sub-trees is more than 1, the
tree is balanced using some rotation techniques.
AVL Rotations
To balance itself, an AVL tree may perform the following four kinds of
rotations –
· Left rotation
· Right rotation
· Left-Right rotation
· Right-Left rotation
The first two rotations are single rotations and the next two rotations are
double rotations. To have an unbalanced tree, we at least need a tree of
height 2. With this simple tree, let's understand them one by one.
Left Rotation
If a tree becomes unbalanced, when a node is inserted into the right sub
tree of the right sub tree, then we perform a single left rotation –
Tree
In our example, node A has become unbalanced as a node is inserted in
the right subtree of A's right subtree. We perform the left rotation by
making A the left-subtree of B.
Right Rotation
AVL tree may become unbalanced, if a node is inserted in the left sub tree
of the left sub tree. The tree then needs a right rotation.
As depicted, the unbalanced node becomes the right child of its left child
by performing a right rotation.
Left-Right Rotation
Double rotations are slightly complex version of already explained
versions of rotations. To understand them better, we should take note of
each action performed while rotation. Let's first check how to perform
Left-Right rotation. A left-right rotation is a combination of left rotation
followed by right rotation.
STATE
ACTION
A node has been inserted into the right sub
tree of the left sub tree. This makes C an
unbalanced node. These scenarios cause
AVL tree to perform left-right rotation.
We first perform the left rotation on the left
subtree of C.
This makes A, the left subtree of B.
Node C is still unbalanced, however now, it
is because of the left-sub tree of the left-sub
tree.
We shall now right-rotate the tree, making B
the new root node of this sub tree. C now
becomes the right sub tree of its own left sub
tree.
The tree is now balanced.
\
Right-Left Rotation
The second type of double rotation is Right-Left Rotation. It is a
combination of right rotation followed by left rotation.
S
STATE
ACTI
ACTION
A node has been inserted into the left
sub tree of the right sub tree. This makes
A, an unbalanced node with balance
Factor 2.
First, we perform the right rotation
along C node, making C the right
subtree of its own left subtree B. Now,
B becomes the right subtree of A.
Node A is still unbalanced because of
the right subtree of its right subtree and
requires a left rotation.
A left rotation is performed by making
B the new root node of the sub tree. A
becomes the left sub tree of its right sub
tree B.
The tree is now balanced.
SPSPANNING TREE
A spanning tree is a subset of Graph G, which has all the vertices covered
with minimum possible number of edges. Hence, a spanning tree does not
have cycles and it cannot be disconnected.
By this definition, we can draw a conclusion that every connected and
undirected Graph G has at least one spanning tree. A disconnected graph
does not have any spanning tree, as
it cannot be spanned to all its vertices.
We found three spanning trees off one complete graph. A complete
undirected graph can have maximum nn-2 number of spanning trees,
where n is the number of nodes. In the
above addressed example, n is 3, hence 33−2 = 3 spanning trees are
possible.
General Properties of Spanning Tree
We now understand that one graph can have more than one spanning tree.
Following are
a few properties of the spanning tree connected to graph G –
· A connected graph G can have more than one spanning tree.
· All possible spanning trees of graph G, have the same number of
edges and vertices
· The spanning tree does not have any cycle (loops).
· Removing one edge from the spanning tree will make the graph
disconnected, i.e. the spanning tree is minimally connected.
· Adding one edge to the spanning tree will create a circuit or loop, i.e.
the spanning tree is maximally acyclic.
Mathematical Properties of Spanning Tree
· Spanning tree has n-1 edges, where n is the number of nodes
(vertices).
· From a complete graph, by removing maximum e-n+1 edges, we can
construct a spanning tree.
· A complete graph can have maximum nn-2 number of spanning trees.
Thus, we can conclude that spanning trees are a subset of connected Graph
G and disconnected graphs do not have spanning tree.
Application of Spanning Tree
Spanning tree is basically used to find a minimum path to connect all
nodes in a graph.
Common application of spanning trees are –
· Civil Network Planning
·Computer Network Routing Protocol
·Cluster Analysis
Let us understand this through a small example. Consider, city network as
a huge graphand now plans to deploy telephone lines
in such a way that in minimum lines we canconnect to all city nodes. This
is where the spanning tree comes into picture.
Minimum of Spanning Tree (MST)
In a weighted graph, a minimum spanning tree is a spanning tree that has
minimum weight than all other spanning trees of the same graph. In realworld situations, this weight can be measured as distance, congestion,
traffic load or any arbitrary value denoted to the edges.
Minimum Spanning-Tree Algorithm
We shall learn about two most important spanning tree algorithms here –
· Kruskal's Algorithm
· Prim's Algorithm
Both are greedy algorithms.
Kruskal's Spanning Tree Algorithm
Kruskal's algorithm to find the minimum cost spanning tree uses the
greedy approach. This algorithm treats the graph as a forest and every
node it has as an individual tree. A tree connects to another only and only
if, it has the least cost among all available options and does not violate
MST properties.
To understand Kruskal's algorithm let us consider the following example
–
Step 1 - Remove all loops and parallel edges
Remove all loops and parallel edges from the given graph.
In case of parallel edges, keep the one which has the least cost associated
and remove all others.
Step 2 - Arrange all edges in their increasing order of weight
The next step is to create a set of edges and weight, and arrange them in
an ascending order of weightage (cost).
Step 3 - Add the edge which has the least weightage
Now we start adding edges to the graph beginning from the one which has
the least weight.Throughout, we shall keep checking that the spanning
properties remain intact. In case,by adding one edge, the spanning tree
property does not hold then we shall consider not to include the edge in
the graph.
The least cost is 2 and edges involved are B,D and D,T. We add them.
Adding them does not violate spanning tree properties, so we continue to
our next edge selection. Next cost is 3, and associated edges are A,C and
C,D. We add them again −
Next cost in the table is 4, and we observe that adding it will create a
circuit in the graph.
We ignore it. In the process we shall ignore/avoid all edges that create a
circuit.
We observe that edges with cost 5 and 6 also create circuits. We ignore
them and move on.
Now we are left with only one node to be added. Between the two least
cost edges available 7 and 8, we shall add the edge with cost 7.
By adding edge S,A we have included all the nodes of the graph and we
now have minimum cost spanning tree.
Describe about data manipulation
Searching Techniques
Linear Search
Linear search is a very simple search algorithm. In this type of search, a
sequential search is made over all items one by one. Every item is checked
and if a match is found then thatParticular item is returned, otherwise the
search continues till the end of the data collection.
Algorithm
Linear Search ( Array A, Value x)
Step 1: Set i to 1
Step 2: if i > n then go to step 7
Step 3: if A[i] = x then go to step 6
Step 4: Set i to i + 1
Step 5: Go to Step 2
Step 6: Print Element x Found at index i and go to step 8
Step 7: Print element not found
Step 8: Exit
Pseudocode
procedure linear_search (list, value)
for each item in the list
if match item == value
return the item's location
end if
end for
end procedure
Linear Search Program in C
Here we present the implementation of linear search in C programming
language. The output of the program is given after the code.
Linear Search Program
#include <stdio.h>
#define MAX 20
// array of items on which linear search will be conducted.
int intArray[MAX] = {1,2,3,4,6,7,9,11,12,14,15,16,17,19,33,34,43,45,55,66};
void printline(int count){
int i;
for(i = 0;i <count-1;i++){
printf("=");
}
printf("=\n");
}
// this method makes a linear search.
int find(int data){
int comparisons = 0;
int index = -1;
int i;
// navigate through all items
for(i = 0;i<MAX;i++){
// count the comparisons made
comparisons++;
// if data found, break the loop
if(data == intArray[i]){
index = i;
break;
}
}
printf("Total comparisons made: %d", comparisons);
return index;
}
void display(){
int i;
printf("[");
// navigate through all items
for(i = 0;i<MAX;i++){
printf("%d ",intArray[i]);
}
printf("]\n");
}
main(){
printf("Input Array: ");
display();
printline(50);
//find location of 1
int location = find(55);
// if element was found
if(location != -1)
printf("\nElement found at location: %d" ,(location+1));
else
printf("Element not found.");
}
If we compile and run the above program, it will produce the following
result –
Input Array: [1 2 3 4 6 7 9 11 12 14 15 16 17 19 33 34 43 45 55 66 ]
==================================================
Total comparisons made: 19
Element found at location: 19
Binary Search
Binary search is a fast search algorithm with run-time complexity of (log
n). This search Algorithm works on the principle of divide and onquer.
For this algorithm to work properly,the data collection should be in the
sorted form.
Binary search looks for a particular item by comparing the middle most
item of the Collection. If a match occurs, then the index of item isreturned.
If the middle item is greater than the item, then the item is searched in the
sub-array to the right of the middleitem. Otherwise, the item is searched
for in the sub-array to the left of the middle item. This process continues
on the sub-array as well until the size of the sub array reduces tozero.
How Binary Search Works?
For a binary search to work, it is mandatory for the target array to be
sorted. We shall learn the process of binary search with a pictorial
example. The following is our sorted array and let us assume that we need
to search the location of value 31 using binary search.
First, we shall determine half of the array by using this formula –
mid = low + (high - low) / 2
Here it is, 0 + (9 - 0 ) / 2 = 4 (integer value of 4.5). So, 4 is the mid of
the array.
Now we compare the value stored at location 4, with the value being
searched, i.e. 31.We find that the value at location 4 is 27, which is not a
match. As the value is greaterthan 27 and we have a sorted array, so we
also know that the target value must be in theupper portion of the array.
We change our low to mid + 1 and find the new mid value again.
low = mid + 1
mid = low + (high - low) / 2
Our new mid is 7 now. We compare the value stored at location 7 with
our target value31.
The value stored at location 7 is not a match, rather it is less than what we
are lookingfor. So, the value must be in the lower part from this location.
Hence, we calculate the mid again. This time it is 5.
We compare the value stored at location 5 with our target value. We find
that it is a match.
We conclude that the target value 31 is stored at location 5.
Pseudocode
The pseudocode of binary search algorithms should look like this −
Procedure binary_search
A ← sorted array
n ← size of array
x ← value ot be searched
Set lowerBound = 1
Set upperBound = n
while x not found
if upperBound < lowerBound
EXIT: x does not exists.
set midPoint = lowerBound + ( upperBound - lowerBound ) / 2
if A[midPoint] < x
set lowerBound = midPoint + 1
if A[midPoint] > x
set upperBound = midPoint – 1
if A[midPoint] = x
EXIT: x found at location midpoint
end while
end procedure
Binary Search Program in C
Binary search is a fast search algorithm with run-time complexity of Ο(log
n). This search algorithm works on the principle of divide and conquer.
For this algorithm to work properly, the data collection should be in a
sorted form.
Implementation in C
#include <stdio.h>
#define MAX 20
// array of items on which linear search will be conducted.
int intArray[MAX] =
{1,2,3,4,6,7,9,11,12,14,15,16,17,19,33,34,43,45,55,66};
void printline(int count){
int i;
for(i = 0;i <count-1;i++){
printf("=");
}
rintf("=\n");
}
int find(int data){
int lowerBound = 0;
int upperBound = MAX -1;
int midPoint = -1;
int comparisons = 0;
int index = -1;
while(lowerBound <= upperBound){
printf("Comparison %d\n" , (comparisons +1) ) ;
printf("lowerBound : %d, intArray[%d] = %d\n",
lowerBound,lowerBound,intArray[lowerBound]);
printf("upperBound : %d, intArray[%d] = %d\n",
upperBound,upperBound,intArray[upperBound]);
comparisons++;
// compute the mid point
// midPoint = (lowerBound + upperBound) / 2;
midPoint = lowerBound + (upperBound - lowerBound) / 2;
// data found
if(intArray[midPoint] == data){
index = midPoint;
break;
}else {
// if data is larger
if(intArray[midPoint] < data){
// data is in upper half
lowerBound = midPoint + 1;
}
// data is smaller
else{
// data is in lower half
upperBound = midPoint -1;
}
}
}
printf("Total comparisons made: %d" , comparisons);
return index;
}
void display(){
int i;
printf("[");
// navigate through all items
for(i = 0;i<MAX;i++){
printf("%d ",intArray[i]);
}
printf("]\n");
}
m
ain(){
printf("Input Array: ");
display();
printline(50);
//find location of 1
int location = find(55);
// if element was found
if(location != -1)
printf("\nElement found at location: %d" ,(location+1));
else
printf("\nElement not found.");
}
If we compile and run the above program, it will produce the following
result –
Input Array: [1 2 3 4 6 7 9 11 12 14 15 16 17 19 33 34 43 45 55 66 ]
Comparison 1
lowerBound : 0, intArray[0] = 1
upperBound : 19, intArray[19] = 66
Comparison 2
lowerBound : 10, intArray[10] = 15
upperBound : 19, intArray[19] = 66
Comparison 3
lowerBound : 15, intArray[15] = 34
upperBound : 19, intArray[19] = 66
Comparison 4
lowerBound : 18, intArray[18] = 55
upperBound : 19, intArray[19] = 66
Total comparisons made: 4
Element found at location: 19
Interpolation Search
Interpolation search is an improved variant of binary search. This search
algorithm works on the probing position of the required value. For this
algorithm to work properly, the datacollection should be in a sorted form
and equally distributed.
Binary search has a huge advantage of time complexity over linear search.
Linear search has worst-case complexity of Ο(n) whereas binary search
has Ο(log n).
There are cases where the location of target data may be known in
advance. For example,in case of a telephone directory, if we want to
search the telephone number of Morphius.Here, linear search and even
binary search will seem slow as we can directly jump tomemory space
where the names start from 'M' are store
Positioning in Binary Search
In binary search, if the desired data is not found then the rest of the list is
divided in two parts, lower and higher. The search is carried out in either
of them.
Position Probing in Interpolation Search
Interpolation search finds a particular item by computing the probe
position. Initially, the probe position is the position of the middle most
item of the collection.
If a match occurs, then the index of the item is returned. To split the list
into two parts, we use the following method –
mid = Lo + ((Hi - Lo) / (A[Hi] - A[Lo])) * (X - A[Lo])
where –
A = list
Lo = Lowest index of the list
Hi = Highest index of the list
A[n] = Value stored at index n in the list
If the middle item is greater than the item, then the probe position is again
calculated in the sub-array to the right of the middle item. Otherwise, the
item is searched in the subarray
to the left of the middle item. This process continues on the sub-array as
well until the size of subarray reduces to zero.
Runtime complexity of interpolation search algorithm is Ο(log (log n)) as
compared to Ο(log n) of BST in favorable situations.
Algorithm
As it is an improvisation of the existing BST algorithm, we are mentioning
the steps to search the 'target' data value index, using position probing –
Step 1 − Start searching data from middle of the list.
Step 2 − If it is a match, return the index of the item, and exit.
Step 3 − If it is not a match, probe position.
Step 4 − Divide the list using probing formula and find the new middle.
Step 5 − If data is greater than middle, search in higher sub-list.
Step 6 − If data is smaller than middle, search in lower sub-list.
Step 7 − Repeat until match.
Pseudocode
A → Array list
N → Size of A
X → Target Value
Procedure Interpolation_Search()
Set Lo → 0
Set Mid → -1
Set Hi → N-1
While X does not match
if Lo equals to Hi OR A[Lo] equals to A[Hi]
EXIT: Failure, Target not found
end if
Set Mid = Lo + ((Hi - Lo) / (A[Hi] - A[Lo])) * (X - A[Lo])
if A[Mid] = X
EXIT: Success, Target found at Mid
Else
if A[Mid] < X
Set Lo to Mid+1
else if A[Mid] > X
Set Hi to Mid-1
end if
end if
End While
End Procedure
Interpolation Search Program in C
Interpolation search is an improved variant of binary search. This search
algorithm works on the probing position of the required value. For this
algorithm to work properly, the data collection should be in sorted and
equally distributed form.
It's runtime complexity is log2(log2 n).
Implementation in C
#include<stdio.h>
#define MAX 10
// array of items on which linear search will be conducted.
int list[MAX] = { 10, 14, 19, 26, 27, 31, 33, 35, 42, 44 };
int find(int data) {
int lo = 0;
int hi = MAX - 1;
int mid = -1;
int comparisons = 1;
int index = -1;
while(lo <= hi) {
printf("\nComparison %d \n" , comparisons ) ;
printf("lo : %d, list[%d] = %d\n", lo, lo, list[lo]);
printf("hi : %d, list[%d] = %d\n", hi, hi, list[hi]);
comparisons++;
// probe the mid point
mid = lo + (((double)(hi - lo) / (list[hi] - list[lo])) * (data - list[lo]));
printf("mid = %d\n",mid);
// data found
if(list[mid] == data) {
index = mid;
break;
}else {
if(list[mid] < data) {
// if data is larger, data is in upper half
lo = mid + 1;
}else {
// if data is smaller, data is in lower half
hi = mid - 1;
}
}
}
printf("\nTotal comparisons made: %d", --comparisons);
return index;
}
int main() {
//find location of 33
int location = find(33);
// if element was found
if(location != -1)
printf("\nElement found at location: %d" ,(location+1));
else
printf("Element not found.");
return 0;
}
If we compile and run the above program, it will produce the following
result −
Searching 33
Comparison 1
lo : 0, list[0] = 10
hi : 9, list[9] = 44
mid = 6
Total comparisons made: 1
Element found at location: 7
Describe about data manipulation Sorting
Techniques.
Sorting Algorithm
Sorting refers to arranging data in a particular format. Sorting algorithm
specifies the way to arrange data in a particular order. Most common
orders are in numerical or lexicographical order.
The importance of sorting lies in the fact that data searching can be
optimized to a very high level, if data is stored in a sorted manner. Sorting
is also used to represent data in more readable formats. Following are
some of the examples of sorting in real-life
Scenarios:
· Telephone Directory – The telephone directory stores the telephone
numbers ofpeople sorted by their names, so that the names can be
searched easily.
· Dictionary – The dictionary stores words in an alphabetical order so
thatsearching of any word becomes easy.
In-place Sorting and Not-in-place Sorting
Sorting algorithms may require some extra space for comparison and
temporary storage of few data elements. These algorithms do not require
any extra space and sorting is said to happen in-place, or for example,
within the array itself. This is called in-place sorting. Bubble sort is an
example of in-place sorting.
However, in some sorting algorithms, the program requires space which
is more than orequal to the elements being sorted. Sorting which uses
equal or more space is called notin-place sorting. Merge-sort is an
example of not-in-place sorting
Stable and Not Stable Sorting
If a sorting algorithm, after sorting the contents, does not change the
sequence of similarcontent in which they appear, it is called stable
sorting.
If a sorting algorithm, after sorting the contents, changes the sequence of
similar contentin which they appear, it is called unstable sorting.
Stability of an algorithm matters when we wish to maintain the sequence
of originalelements, like in a tuple for example.
Adaptive and Non-Adaptive Sorting Algorithm
A sorting algorithm is said to be adaptive, if it takes advantage of already
'sorted' elements in the list that is to be sorted. That is, while sorting if the
source list has some element already sorted, adaptive algorithms will take
this into account and will try not to re-order them.
A non-adaptive algorithm is one which does not take into account the
elements which are already sorted. They try to force every single element
to be re-ordered to confirm their sortedness.
Important Terms
Some terms are generally coined while discussing sorting techniques, here
is a brief introduction to them –
Increasing Order
A sequence of values is said to be in increasing order, if the successive
element is greater than the previous one. For example, 1, 3, 4, 6, 8, 9 are
in increasing order, as every next
element is greater than the previous element.
Decreasing Order
A sequence of values is said to be in decreasing order, if the successive
element is less than the current one. For example, 9, 8, 6, 4, 3, 1 are in
decreasing order, as every next element is less than the previous element.
Non-Increasing Order
A sequence of values is said to be in non-increasing order, if the
successive element is less than or equal to its previous element in the
sequence. This order occurs when the sequence contains duplicate values.
For example, 9, 8, 6, 3, 3, 1 are in non-increasing order, as every next
element is less than or equal to (in case of 3) but not greater than any
previous element.
Non-Decreasing Order
A sequence of values is said to be in non-decreasing order, if the
successive element isgreater than or equal to its previous element in the
sequence. This order occurs when thesequence contains duplicate values.
For example, 1, 3, 3, 6, 8, 9 are in non-decreasingorder, as every next
element is greater than or equal to (in case of 3) but not less thanthe
previous one.
Bubble Sort Algorithm
Bubble sort is a simple sorting algorithm. This sorting algorithm is
comparison-based algorithm in which each pair of adjacent elements is
compared and the elements are swapped if they are not in order. This
algorithm is not suitable for large data sets as its average and worst case
complexity are of O(n2) where n is the number of items.
How Bubble Sort Works?
We take an unsorted array for our example. Bubble sort takes Ο(n2) time
so we're keepingit short and precise.
Bubble sort starts with very first two elements, comparing them to check
which one isgreater.
In this case, value 33 is greater than 14, so it is already in sorted locations.
Next, wecompare 33 with 27.
We find that 27 is smaller than 33 and these two values must be swapped.
The new array should look like this –
Next we compare 33 and 35. We find that both are in already sorted
positions.
Then we move to the next two values, 35 and 10.
We know then that 10 is smaller 35. Hence they are not sorted.
We swap these values. We find that we have reached the end of the array.
After oneiteration, the array should look like this –
To be precise, we are now showing how an array should look like after
each iteration. After the second iteration, it should look like this –
Notice that after each iteration, at least one value moves at the end.
And when there's no swap required, bubble sorts learns that an array is
completely sorted.
Now we should look into some practical aspects of bubble sort.
Algorithm
We assume list is an array of n elements. We further assume that swap
function swaps the values of the given array elements.
begin Bubble Sort(list)
for all elements of list
if list[i] > list[i+1]
swap(list[i], list[i+1])
end if
end for
return list
end Bubble Sort
Pseudocode
We observe in algorithm that Bubble Sort compares each pair of array
element unless the whole array is completely sorted in an ascending order.
This may cause a few complexity issues like what if the array needs no
more swapping as all the elements are already ascending.
To ease-out the issue, we use one flag variable swapped which will help
us see if any swap has happened or not. If no swap has occurred, i.e. the
array requires no more processing to be sorted, it will come out of the
loop.
Pseudocode of Bubble Sort algorithm can be written as follows –
procedure bubbleSort( list : array of items )
loop = list.count;
for i = 0 to loop-1 do:
swapped = false
for j = 0 to loop-1 do:
/* compare the adjacent elements */
if list[j] > list[j+1] then
/* swap them */
swap( list[j], list[j+1] )
swapped = true
end if
end for
/*if no number was swapped that means
array is sorted now, break the loop.*/
if(not swapped) then
break
end if
end for
end procedure return list
Implementation
One more issue we did not address in our original algorithm and its
improvised pseudocode, is that, after every iteration the highest values
settles down at the end of the array. Hence, the next iteration need not
include already sorted elements. For thispurpose, in our implementation,
we restrict the inner loop to avoid already sorted values.
To know about bubble sort implementation in C programming language,
please click here.
Bubble Sort Program in C
We shall see the implementation of bubble sort in C programming
language here.
Implementation in C
#include <stdio.h>
#include <stdbool.h>
#define MAX 10
int list[MAX] = {1,8,4,6,0,3,5,2,7,9};
void display(){
int i;
printf("[");
// navigate through all items
for(i = 0; i < MAX; i++){
printf("%d ",list[i]);
}
printf("]\n");
}
void bubbleSort() {
int temp;
int i,j;
bool swapped = false;
// loop through all numbers
for(i = 0; i < MAX-1; i++) {
swapped = false;
// loop through numbers falling ahead
for(j = 0; j < MAX-1-i; j++) {
printf(" Items compared: [ %d, %d ] ", list[j],list[j+1]);
// check if next number is lesser than current no
// swap the numbers.
// (Bubble up the highest number)
if(list[j] > list[j+1]) {
temp = list[j];
list[j] = list[j+1];
list[j+1] = temp;
swapped = true;
printf(" => swapped [%d, %d]\n",list[j],list[j+1]);
}else {
printf(" => not swapped\n");
}
}
// if no number was swapped that means
// array is sorted now, break the loop.
if(!swapped) {
break;
}
printf("Iteration %d#: ",(i+1));
display();
}
}
main(){
printf("Input Array: ");
display();
printf("\n");
bubbleSort();
printf("\nOutput Array: ");
display();
}
If we compile and run the above program, it will produce the following
result –
Input Array: [1 8 4 6 0 3 5 2 7 9 ]
Items compared: [ 1, 8 ] => not swapped
Input Array: [1 8 4 6 0 3 5 2 7 9 ]
Items compared: [ 1, 8 ] => not swapped
Items compared: [ 8, 4 ] => swapped [4, 8]
Items compared: [ 8, 6 ] => swapped [6, 8]
Items compared: [ 8, 0 ] => swapped [0, 8]
Items compared: [ 8, 3 ] => swapped [3, 8]
Items compared: [ 8, 5 ] => swapped [5, 8]
Items compared: [ 8, 2 ] => swapped [2, 8]
Items compared: [ 8, 7 ] => swapped [7, 8]
Items compared: [ 8, 9 ] => not swapped
Iteration 1#: [1 4 6 0 3 5 2 7 8 9 ]
Items compared: [ 1, 4 ] => not swapped
Items compared: [ 4, 6 ] => not swapped
Items compared: [ 6, 0 ] => swapped [0, 6]
Items compared: [ 6, 3 ] => swapped [3, 6]
Items compared: [ 6, 5 ] => swapped [5, 6]
Items compared: [ 6, 2 ] => swapped [2, 6]
Items compared: [ 6, 7 ] => not swapped
Items compared: [ 7, 8 ] => not swapped
Iteration 2#: [1 4 0 3 5 2 6 7 8 9 ]
Items compared: [ 1, 4 ] => not swapped
Items compared: [ 4, 0 ] => swapped [0, 4]
Items compared: [ 4, 3 ] => swapped [3, 4]
Items compared: [ 4, 5 ] => not swapped
Items compared: [ 5, 2 ] => swapped [2, 5]
Items compared: [ 5, 6 ] => not swapped
Items compared: [ 6, 7 ] => not swapped
Iteration 3#: [1 0 3 4 2 5 6 7 8 9 ]
Items compared: [ 1, 0 ] => swapped [0, 1]
Items compared: [ 1, 3 ] => not swapped
Items compared: [ 3, 4 ] => not swapped
Items compared: [ 4, 2 ] => swapped [2, 4]
Items compared: [ 4, 5 ] => not swapped
Items compared: [ 5, 6 ] => not swapped
Items compared: [ 4, 3 ] => swapped [3, 4]
Items compared: [ 4, 5 ] => not swapped
Items compared: [ 5, 2 ] => swapped [2, 5]
Items compared: [ 5, 6 ] => not swapped
Items compared: [ 6, 7 ] => not swapped
Iteration 3#: [1 0 3 4 2 5 6 7 8 9 ]
Items compared: [ 4, 3 ] => swapped [3, 4]
Items compared: [ 4, 5 ] => not swapped
Items compared: [ 5, 2 ] => swapped [2, 5]
Items compared: [ 5, 6 ] => not swapped
Items compared: [ 6, 7 ] => not swapped
Iteration 3#: [1 0 3 4 2 5 6 7 8 9 ]
Items compared: [ 1, 0 ] => swapped [0, 1]
Items compared: [ 1, 3 ] => not swapped
Items compared: [ 3, 4 ] => not swapped
Items compared: [ 4, 2 ] => swapped [2, 4]
Items compared: [ 4, 5 ] => not swapped
Items compared: [ 5, 6 ] => not swapped
Iteration 4#: [0 1 3 2 4 5 6 7 8 9 ]
Items compared: [ 0, 1 ] => not swapped
Items compared: [ 1, 3 ] => not swapped
Items compared: [ 3, 2 ] => swapped [2, 3]
Items compared: [ 3, 4 ] => not swapped
Items compared: [ 4, 5 ] => not swapped
Iteration 5#: [0 1 2 3 4 5 6 7 8 9 ]
Items compared: [ 0, 1 ] => not swapped
Items compared: [ 1, 2 ] => not swapped
Items compared: [ 2, 3 ] => not swapped
Items compared: [ 3, 4 ] => not swapped
Insertion Sort
This is an in-place comparison-based sorting algorithm. Here, a sub-list is
maintained which is always sorted. For example, the lower part of an array
is maintained to be sorted. An element which is to be 'insert'ed in this
sorted sub-list, has to find its appropriate place and then it has to be
inserted there. Hence the name, insertion sort.
The array is searched sequentially and unsorted items are moved and
inserted into the sorted sub-list (in the same array). This algorithm is not
suitable for large data sets as its average and worst case complexity are of
Ο(n2), where n is the number of items.
How Insertion Sort Works?
We take an unsorted array for our example.
Insertion sort compares the first two elements.
It finds that both 14 and 33 are already in ascending order. For now, 14 is
in sorted sublist.
Insertion sort moves ahead and compares 33 with 27.
And finds that 33 is not in the correct position.
It swaps 33 with 27. It also checks with all the elements of sorted sub-list.
Here we see that the sorted sub-list has only one element 14, and 27 is
greater than 14. Hence, the sorted sub-list remains sorted after swapping.
By now we have 14 and 27 in the sorted sub-list. Next, it compares 33
with 10.
These values are not in a sorted order.
So we swap them.
However, swapping makes 27 and 10 unsorted.
Hence, we swap them too.
Again we find 14 and 10 in an unsorted order.
We swap them again. By the end of third iteration, we have a sorted sublist of 4 items.
This process goes on until all the unsorted values are covered in a sorted
sub-list. Now weshall see some programming aspects of insertion sort.
Algorithm
Now we have a bigger picture of how this sorting technique works, so we
can derive simple steps by which we can achieve insertion sort.
Step 1 − If it is the first element, it is already sorted. return 1;
Step 2 − Pick next element
Step 3 − Compare with all elements in the sorted sub-list
Step 4 − Shift all the elements in the sorted sub-list that is greater than the
value to be sorted
Step 5 − Insert the value
Step 6 − Repeat until list is sorted
Pseudocode
procedure insertionSort( A : array of items )
int holePosition
int valueToInsert
for i = 1 to length(A) inclusive do:
/* select value to be inserted */
valueToInsert = A[i]
holePosition = i
/*locate hole position for the element to be inserted */
while holePosition > 0 and A[holePosition-1] > valueToInsert do:
A[holePosition] = A[holePosition-1]
holePosition = holePosition -1
end while
/* insert the number at hole position */
A[holePosition] = valueToInsert
end for
end procedure
Insertion Sort Program in C
This is an in-place comparison-based sorting algorithm. Here, a sub-list is
maintained which is always sorted. For example, the lower part of an array
is maintained to be sorted. An element which is to be 'inserted in this
sorted sub-list, has to find its appropriate place and then it is to be inserted
there. Hence the name insertion sort.
Implementation in C
#include <stdio.h>
#include <stdbool.h>
#define MAX 7
int intArray[MAX] = {4,6,3,2,1,9,7};
void printline(int count){
int i;
for(i = 0;i <count-1;i++){
printf("=");
}
printf("=\n");
}
void display(){
int i;
printf("[");
// navigate through all items
for(i = 0;i<MAX;i++){
printf("%d ",intArray[i]);
}
printf("]\n");
}
void insertionSort(){
int valueToInsert;
int holePosition;
int i;
// loop through all numbers
for(i = 1; i < MAX; i++){
// select a value to be inserted.
valueToInsert = intArray[i];
// select the hole position where number is to be inserted
holePosition = i;
// check if previous no. is larger than value to be inserted
while (holePosition > 0 && intArray[holePosition-1] > valueToInsert){
intArray[holePosition] = intArray[holePosition-1];
holePosition--;
printf(" item moved : %d\n" , intArray[holePosition]);
}
if(holePosition != i){
printf(" item inserted : %d, at position : %d\n" ,
valueToInsert,holePosition);
// insert the number at hole position
intArray[holePosition] = valueToInsert;
}
printf("Iteration %d#:",i);
display();
}
}
main(){
printf("Input Array: ");
display();
printline(50);
insertionSort();
printf("Output Array: ");
display();
printline(50);
}
If we compile and run the above program, it will produce the following
result –
Input Array: [4, 6, 3, 2, 1, 9, 7]
==================================================
iteration 1#: [4, 6, 3, 2, 1, 9, 7]
item moved :6
item moved :4
item inserted :3, at position :0
iteration 2#: [3, 4, 6, 2, 1, 9, 7]
item moved :6
item moved :4
item moved :3
item inserted :2, at position :0
iteration 3#: [2, 3, 4, 6, 1, 9, 7]
item moved :6
item moved :4
item moved :3
item moved :2
item inserted :1, at position :0
iteration 4#: [1, 2, 3, 4, 6, 9, 7]
iteration 5#: [1, 2, 3, 4, 6, 9, 7]
item moved :9
item moved :6
item inserted :7, at position :4
iteration 6#: [1, 2, 3, 4, 7, 6, 9]
Output Array: [1, 2, 3, 4, 7, 6, 9]
==================================================
Selection Sort
Selection sort is a simple sorting algorithm. This sorting algorithm is an
in-place comparison-based algorithm in which the list is divided into two
parts, the sorted part at the left end and the unsorted part at the right end.
Initially, the sorted part is empty and the unsorted part is the entire list.
The smallest element is selected from the unsorted array and swapped
with the leftmost element, and that element becomes a part of the sorted
array. This process continues moving unsorted array boundary by one
element to the right.
This algorithm is not suitable for large data sets as its average and worst
case complexities are of O(n2), where n is the number of items.
How Selection Sort Works?
Consider the following depicted array as an example
For the first position in the sorted list, the whole list is scanned
sequentially. The firstposition where 14 is stored presently, we search the
whole list and find that 10 is thelowest value.
So we replace 14 with 10. After one iteration 10, which happens to be the
minimum valuein the list, appears in the first position of the sorted list.
For the second position, where 33 is residing, we start scanning the rest
of the list in alinear manner.
We find that 14 is the second lowest value in the list and it should appear
at the secondplace. We swap these values.
After two iterations, two least values are positioned at the beginning in a
sorted manner.
The same process is applied to the rest of the items in the array.
Following is a pictorial depiction of the entire sorting process –
Algorithm
Step 1 − Set MIN to location 0
Step 2 − Search the minimum element in the list
Step 3 − Swap with value at location MIN
Step 4 − Increment MIN to point to next element
Step 5 − Repeat until list is sorted
Pseudocode
procedure selection sort
list : array of items
n : size of list
for i = 1 to n – 1
/* set current element as minimum*/
min = i
/* check the element to be minimum */
for j = i+1 to n
if list[j] < list[min] then
min = j;
end if
end for
/* swap the minimum element with the current element*/
if indexMin != i then
swap list[min] and list[i]
end if
end for
end procedure
Selection Sort Program in C
Selection sort is a simple sorting algorithm. This sorting algorithm is an
in-place comparison-based algorithm in which the list is divided into two
parts, the sorted part at the left end and the unsorted part at the right end.
Initially, the sorted part is empty and the unsorted part is the entire list.
Implementation in C
#include <stdio.h>
#include <stdbool.h>
#define MAX 7
int intArray[MAX] = {4,6,3,2,1,9,7};
void printline(int count){
int i;
for(i = 0;i <count-1;i++){
printf("=");
}
printf("=\n");
}
void display(){
int i;
printf("[");
// navigate through all items
for(i = 0;i<MAX;i++){
printf("%d ", intArray[i]);
}
If we compile and run the above program, it will produce the following
result −
Input Array: [4, 6, 3, 2, 1, 9, 7]
==================================================
Items swapped: [ 4, 1 ]
iteration 1#: [1, 6, 3, 2, 4, 9, 7]
Items swapped: [ 6, 2 ]
iteration 2#: [1, 2, 3, 6, 4, 9, 7]
iteration 3#: [1, 2, 3, 6, 4, 9, 7]
Items swapped: [ 6, 4 ]
iteration 4#: [1, 2, 3, 4, 6, 9, 7]
iteration 5#: [1, 2, 3, 4, 6, 9, 7]
Items swapped: [ 9, 7 ]
iteration 6#: [1, 2, 3, 4, 6, 7, 9]
Output Array: [1, 2, 3, 4, 6, 7, 9]
==================================================
Merge Sort Algorithm
Merge sort is a sorting technique based on divide and conquer technique.
With worst-case time complexity being Ο(n log n), it is one of the most
respected algorithms.
Merge sort first divides the array into equal halves and then combines
them in a sorted manner.
How Merge Sort Works?
To understand merge sort, we take an unsorted array as the following –
We know that merge sort first divides the whole array iteratively into
equal halves unlessthe atomic values are achieved. We see here that an
array of 8 items is divided into twoarrays of size 4.
This does not change the sequence of appearance of items in the original.
Now we dividethese two arrays into halves.
We further divide these arrays and we achieve atomic value which can no
more be divided.
Now, we combine them in exactly the same manner as they were broken
down. Pleasenote the color codes given to these lists.
We first compare the element for each list and then combine them into
another list in asorted manner. We see that 14 and 33 are in sorted
positions. We compare 27 and 10 andin the target list of 2 values we put
10 first, followed by 27. We change the order of 19and 35 whereas 42 and
44 are placed sequentially.
In the next iteration of the combining phase, we compare lists of two data
values, andmerge them into a list of found data values placing all in a
sorted order.
After the final merging, the list should look like this –
Algorithm
Merge sort keeps on dividing the list into equal halves until it can no more
be divided. Bydefinition, if it is only one element in the list, it is sorted.
Then, merge sort combines thesmaller sorted lists keeping the new list
sorted too.
Step 1 − if it is only one element in the list it is already sorted, return.
Step 2 − divide the list recursively into two halves until it can no more be
divided.
Step 3 − merge the smaller lists into new list in sorted order.
Pseudocode
We shall now see the pseudocodes for merge sort functions. As our
algorithms point outtwo main functions − divide & merge.
Merge sort works with recursion and we shall see ourimplementation in
the same way.
procedure mergesort( var a as array )
if ( n == 1 ) return a
var l1 as array = a[0] ... a[n/2]
var l2 as array = a[n/2+1] ... a[n]
l1 = mergesort( l1 )
l2 = mergesort( l2 )
return merge( l1, l2 )
end procedure
procedure merge( var a as array, var b as array )
var c as array
while ( a and b have elements )
if ( a[0] > b[0] )
add b[0] to the end of c
remove b[0] from b
else
add a[0] to the end of c
remove a[0] from a
end if
end while
while ( a has elements )
add a[0] to the end of c
remove a[0] from a
end while
while ( b has elements )
add b[0] to the end of c
remove b[0] from b
end while
return c
end procedure
Shell Sort
Shell sort is a highly efficient sorting algorithm and is based on insertion
sort algorithm. This algorithm avoids large shifts as in case of insertion
sort, if the smaller value is to the far right and has to be moved to the far
left
.
This algorithm uses insertion sort on a widely spread elements, first to sort
them and then sorts the less widely spaced elements. This spacing is
termed as interval. This interval is calculated based on Knuth's formula
as –
h=h*3+1
where −
h is interval with initial value 1
This algorithm is quite efficient for medium-sized data sets as its average
and worst casecomplexity are of O(n), where n is the number of items.
How Shell Sort Works?
Let us consider the following example to have an idea of how shell sort
works. We take the same array we have used in our previous examples.
For our example and ease of understanding, we take the interval of 4.
Make a virtual sub-list of all values located at the interval of 4 positions.
Here these values are {35, 14}, {33, 19}, {42, 27} and {10,14}
We compare values in each sub-list and swap them (if necessary) in the
original array.After this step, the new array should look like this –
Then, we take interval of 2 and this gap generates two sub-lists - {14, 27,
35, 42}, {19,10, 33, 44}
We compare and swap the values, if required, in the original array. After
this step, thearray should look like this –
Finally, we sort the rest of the array using interval of value 1. Shell sort
uses insertion sortto sort the array.
Following is the step-by-step depiction –
Algorithm
Following is the algorithm for shell sort.
Step 1 − Initialize the value of h
Step 2 − Divide the list into smaller sub-list of equal interval h
Step 3 − Sort these sub-lists using insertion sort
Step 3 − Repeat until complete list is sorted
Quick sort
Quick sort is a highly efficient sorting algorithm and is based on
partitioning of array of data into smaller arrays. A large array is
partitioned into two arrays one of which holds values smaller than the
specified value, say pivot, based on which the partition is made and
another array holds values greater than the pivot value.
Quick sort partitions an array and then calls itself recursively twice to sort
the two resulting subarrays. This algorithm is quite efficient for largesized data sets as its average and worst case complexity are of O(nlogn),
where n is the number of items.
Partition in Quick Sort
Following animated representation explains how to find the pivot value in
an array.
The pivot value divides the list into two parts. And recursively, we find
the pivot for eachsub-lists until all lists contains only one element.
Quick Sort Pivot Algorithm
Based on our understanding of partitioning in quick sort, we will now try
to write analgorithm for it, which is as follows.
Step 1 − Choose the highest index value has pivot
Step 2 − Take two variables to point left and right of the list excluding pivot
Step 3 − left points to the low index
Step 4 − right points to the high
Step 5 − while value at left is less than pivot move right
Step 6 − while value at right is greater than pivot move left
Step 7 − if both step 5 and step 6 does not match swap left and right
Step 8 − if left ≥ right, the point where they met is new pivot
Quick Sort Pivot Pseudocode
The pseudocode for the above algorithm can be derived as –
function partitionFunc(left, right, pivot)
leftPointer = left -1
rightPointer = right
while True do
while A[++leftPointer] < pivot do
//do-nothing
end while
while rightPointer > 0 && A[--rightPointer] > pivot do
//do-nothing
end while
if leftPointer >= rightPointer
break
else
swap leftPointer,rightPointer
end if
end while
swap leftPointer,right
return leftPointer
end function
Quick Sort Algorithm
Using pivot algorithm recursively, we end up with smaller possible
partitions. Each partition is then processed for quick sort. We define
recursive algorithm for quicksort as follows –
Step 1 − Make the right-most index value pivot
Step 2 − partition the array using pivot value
Step 3 − quicksort left partition recursively
Step 4 − quicksort right partition recursively
Explain about data structure overview?
Data Structure is a systematic way to organize data in order to use it
efficiently. Following terms are the foundation terms of a data structure.
• Interface − Each data structure has an interface. Interface
represents the set of operations that a data structure supports. An
interface only provides the list of supported operations, type of
parameters they can accept and return type of these operations.
• Implementation − Implementation provides the internal
representation of a data structure. Implementation also provides the
definition of the algorithms used in the operations of the data
structure.
Characteristics of a Data Structure
• Correctness − Data structure implementation should implement its
interface correctly.
• Time Complexity − Running time or the execution time of
operations of data structure must be as small as possible.
• Space Complexity − Memory usage of a data structure operation
should be as little as possible.
Need for Data Structure
As applications are getting complex and data rich, there are three
common problems that applications face now-a-days.
• Data Search − Consider an inventory of 1 million(106) items of a
store. If the application is to search an item, it has to search an item
in 1 million(106) items every time slowing down the search. As data
grows, search will become slower.
• Processor Speed − Processor speed although being very high, falls
limited if the data grows to billion records.
• Multiple Requests − As thousands of users can search data
simultaneously on a web server, even the fast server fails while
searching the data.
Execution Time Cases
There are three cases which are usually used to compare various data
structure's execution time in a relative manner.
• Worst Case − This is the scenario where a particular data structure
operation takes maximum time it can take. If an operation's worst
case time is ƒ(n) then this operation will not take more than ƒ(n)
time, where ƒ(n) represents function of n.
• Average Case − This is the scenario depicting the average execution
time of an operation of a data structure. If an operation takes ƒ(n)
time in execution, thenm operations will take mƒ(n) time.
• Best Case − This is the scenario depicting the least possible
execution time of an operation of a data structure. If an operation
takes ƒ(n) time in execution, then the actual operation may take time
as the random number which would be maximum as ƒ(n).
2) Explain about Array representation?
Array is a container which can hold a fix number of items and these items
should be of the same type. Most of the data structures make use of arrays
to implement their algorithms.
Following are the important terms to understand the concept of Array.
• Element − Each item stored in an array is called an element.
• Index − Each location of an element in an array has a numerical
index, which is used to identify the element.
Array Representation
Arrays can be declared in various ways in different languages. For
illustration, let's take array declaration.
Arrays can be declared in various ways in different languages. For
illustration, let's take C array declaration.
As per the above illustration, following are the important points to be
considered.
Index starts with 0.
• Array length is 8 which means it can store 8 elements.
• Each element can be accessed via its index. For example, we can
fetch an elementat index 6 as 9
Insertion Operation
Insert operation is to insert one or more data elements into an array. Based
on the requirement, a new element can be added at the beginning, end, or
any given index of array. Here, we see a practical implementation of
insertion operation, where we add data at the end of the array −
Algorithm
Let Array be a linear unordered array of MAX elements.
Example
Let LA be a Linear Array (unordered) with N elements and K is a
positive integer suchthat K<=N. Following is the algorithm where ITEM
is inserted into the Kth position of LA –
1. Start
2. Set J=N
3. Set N = N+1
4. Repeat steps 5 and 6 while J >= K
5. Set LA[J+1] = LA[J]
6. Set J = J-1
7. Set LA[K] = ITEM
8. Stop
Array Insertions
In the previous section, we have learnt how the insertion operation
works. It is not alwaysnecessary that an element is inserted at the end of
an array. Following can be a situationwith array insertion −
• Insertion at the beginning of an array
• Insertion at the given index of an array
• Insertion after the given index of an array
• Insertion before the given index of an array
Insertion at the Beginning of an Array
When the insertion happens at the beginning, it causes all the
existing data items to shift one step downward. Here, we design and
implement an algorithm to insert an element at the beginning of an array.
Algorithm
We assume A is an array with N elements. The maximum numbers
of elements it can store is defined by MAX. We shall first check if an
array has any empty space to store any element and then we proceed with
the insertion process
begin
IF N = MAX, return
ELSE
N=N+1
For All Elements in A
Move to next adjacent location
A[FIRST] = New_Element
end
Insertion at the Given Index of an Array
In this scenario, we are given the exact location (index) of an array
where a new data element (value) needs to be inserted. First we shall
check if the array is full, if it is not, then we shall move all data elements
from that location one step downward. This will make room for a new
data element.
Algorithm
We assume A is an array with N elements. The maximum numbers of
elements it can store is defined by MAX.
begin
IF N = MAX, return
ELSE
N=N+1
SEEK Location index
For All Elements from A[index] to A[N]Move to next
adjacent location
A[index] = New_Element
end
Insertion After the Given Index of an Array
In this scenario we are given a location (index) of an array after
which a new data element (value) has to be inserted. Only the seek process
varies, the rest of the activities are the same as in the previous example.
Algorithm
We assume A is an array with N elements. The maximum numbers of
elements it can store is defined by MAX.
begin
IF N = MAX, return
ELSE
N=N+1
SEEK Location index
For All Elements from A[index + 1] to A[N]
Move to next adjacent location
A[index + 1] = New_Element
end
Insertion Before the Given Index of an Array
In this scenario we are given a location (index) of an array before
which a new data element (value) has to be inserted. This time we seek
till index-1, i.e., one locationahead of the given index. Rest of the
activities are the same as in the previous example.
Algorithm
We assume A is an array with N elements. The maximum
numbers of elements it can store is defined by MAX.
begin
IF N = MAX, return
ELSE
N=N+1
SEEK Location index
For All Elements from A[index - 1] to A[N]
Move to next adjacent location
A[index - 1] = New_Element
end
Describe stacks and queues?
Stack:
A stack is an Abstract Data Type (ADT), commonly used in most
programming languages. It is named stack as it behaves like a real-world
stack, for example – a deck of cards or a pile of plates, etc
A real-world stack allows operations at one end only. For example, we
can place or remove a card or plate from the top of the stack only.
Likewise, Stack ADT allows all data operations at one end only. At any
given time, we can only access the top element of a stack.
This feature makes it LIFO data structure. LIFO stands for Last-in-firstout. Here, the element which is placed (inserted or added) last, is accessed
first. In stack terminology, insertion operation is called PUSH operation
and removal operation is called POP operation.
Stack Representation
The following diagram depicts a stack and its operations
A stack can be implemented by means of Array, Structure, Pointer, and
Linked List. Stack can either be a fixed size one or it may have a sense of
dynamic resizing. Here, we aregoing to implement stack using arrays,
which makes it a fixed size stack implementation.
Basic Operations
Stack operations may involve initializing the stack, using it and then deinitializing it. Apartfrom these basic stuffs, a stack is used for the
following two primary operations −
• push() − Pushing (storing) an element on the stack.
• pop() − Removing (accessing) an element from the stack.
When data is PUSHed onto stack.To use a stack efficiently, we need to
check the status of stack as well.
For the samepurpose, the following functionality is added to stacks −
• peek() − get the top data element of the stack, without removing
it.
• isFull() − check if stack is full.
• isEmpty() − check if stack is empty.
At all times, we maintain a pointer to the last PUSHed data on the stack.
As this pointer always represents the top of the stack, hence named top.
The top pointer provides top value of the stack without actually removing
it.First we should learn about procedures to support stack functions.
peek()
Algorithm of peek() function –
begin procedure peek
return stack[top]
end procedure
isfull()
Algorithm of isfull() functionbegin procedure isfull
if top equals to MAXSIZE
return true
else
return false
endif
end procedure
isempty()
Algorithm of isempty() function –
begin procedure isempty
if top less than 1
return true
else
return false
endif
end procedure
Push Operation
The process of putting a new data element onto stack is known as a Push
Operation. Pushoperation involves a series of steps −
• Step 1 − Checks if the stack is full.
• Step 2 − If the stack is full, produces an error and exit.
• Step 3 − If the stack is not full, increments top to point next
empty space.
• Step 4 − Adds data element to the stack location, where top is
pointing.
• Step 5 − Returns success.
Algorithm for PUSH Operation
A simple algorithm for Push operation can be derived as follows
begin procedure push: stack, data
if stack is full
return null
endif
top ← top + 1
stack[top] ← data
end procedure
Pop Operation
Accessing the content while removing it from the stack, is known as a Pop
Operation. In an array implementation of pop() operation, the data
element is not actually removed,instead top is decremented to a lower
position in the stack to point to the next value. But in linked-list
implementation, pop() actually removes data element and deallocates
memory space.
A Pop operation may involve the following steps −
• Step 1 − Checks if the stack is empty.
• Step 2 − If the stack is empty, produces an error and exit
• Step 3 − If the stack is not empty, accesses the data element at
which top is
pointing.
• Step 4 − Decreases the value of top by 1.
• Step 5 − Returns success
Algorithm for Pop Operation
A simple algorithm for Pop operation can be derived as follows
begin procedure pop: stack
if stack is empty
return null
endif
data ← stack[top]
top ← top - 1
return data
end procedure
Queue
Queue is an abstract data structure, somewhat similar to Stacks. Unlike
stacks, a queue is open at both its ends. One end is always used to insert
data (enqueue) and the other is used to remove data (dequeue). Queue
follows First-In-First-Out methodology, i.e., the data item stored first will
be accessed first.real-world example of queue can be a single-lane oneway road, where the vehicle enters first, exits first. More real-world
examples can be seen as queues at the ticket windows and bus-stops.
Queue Representation
As we now understand that in queue, we access both ends for different
reasons. The following diagram given below tries to explain queue
representation as data structure
As in stacks, a queue can also be implemented using Arrays, Linked-lists,
Pointers and Structures. For the sake of simplicity, we shall implement
queues using one-dimensional array.
Basic Operations
Queue operations may involve initializing or defining the queue, utilizing
it, and thencompletely erasing it from the memory. Here we shall try to
understand the basicoperations associated with queues −
• enqueue() − add (store) an item to the queue.
• dequeue() − remove (access) an item from the queue.
Few more functions are required to make the above-mentioned queue
operation efficient.
These are −
• peek() − Gets the element at the front of the queue without
removing it.
• isfull() − Checks if the queue is full.
• isempty() − Checks if the queue is empty.
In queue, we always dequeue (or access) data, pointed by front pointer
and while enqueing (or storing) data in the queue we take help of rear
pointer.
Let's first learn about supportive functions of a queue −
peek()
This function helps to see the data at the front of the queue. The
algorithm of peek() function is as follows
begin procedure peek
return queue[front]
end procedure
isfull()
As we are using single dimension array to implement queue, we just check
for the rear pointer to reach at MAXSIZE to determine that the queue is
full. In case we maintain the queue in a circular linked-list, the algorithm
will differ. Algorithm of isfull() function –
begin procedure isfull
if rear equals to MAXSIZE
return true
else
isempty()
Algorithm of isempty() function –
begin procedure isempty
if front is less than MIN OR front is greater than rear
return true
else
return false
endif
end procedure
If the value of front is less than MIN or 0, it tells that the queue is not
yet initialized, hence empty.
Here's the C programming code –
bool isempty() {
if(front < 0 || front > rear)return true;
else
return false;
}
Enqueue Operation
Queues maintain two data pointers, front and rear. Therefore, its
operations arecomparatively difficult to implement than that of stacks.
The following steps should be taken to enqueue (insert) data into a queue
−
• Step 1 − Check if the queue is full.
• Step 2 − If the queue is full, produce overflow error and exit.
• Step 3 − If the queue is not full, increment rear pointer to point the
next empty space.
• Step 4 − Add data element to the queue location, where the rear is
pointing.
• Step 5 − Return success.
Sometimes, we also check to see if a queue is initialized or not, to
handle any unforeseen situations
procedure enqueue(data)
if queue is full
return overflow
endif
rear ← rear + 1
queue[rear] ← data
return true
end procedure
Dequeue Operation
Accessing data from the queue is a process of two tasks − access the data
where front ispointing and remove the data after access. The following
steps are taken toperform dequeue operation −
• Step 1 − Check if the queue is empty.
• Step 2 − If the queue is empty, produce underflow error and exit.
• Step 3 − If the queue is not empty, access the data where front is
pointing.
• Step 4 − Increment front pointer to point to the next available data
element.
• Step 5 − Return success
Algorithm for dequeue Operation
procedure dequeue
if queue is empty
return underflow
end if
data = queue[front]
front ← front + 1
return true
end procedure
4)Give a application of stack and queue ?
Application of Stacks
Call stack in run time systems
ü When a function (method, procedure) is called, the work area (local
variables, copies of parameters, return location in code) for the
new function is pushed on to the stack. When the function returns
the stack is popped.
ü The order we need the data back is ‘LIFO’.This explains why
calling a recursive procedure with a depth of N requires O(N) space.
Stack ADT
ü A list for which Insert and Delete are allowed only at one
end of the list (the top)
ü The implementation defines which end is the "top"
LIFO – Last in, First out
ü Push: Insert element at top
ü Pop: Remove and return top element (aka TopAndPop)
ü • IsEmpty: test for emptyne
The reverse Polish (postfix) notation:
ab+cd+*
Linked List Implementation
ü Stack of blobs
Array Implementation
ü Stack of blobs
Two Basic Implementations of Stacks
• Linked List
ü Push is InsertFront
ü Pop is DeleteFront (Top is “access” the
element at the top of the stack)
ü IsEmpty is test for null (or null after the
header if there’s one)
• Array
ü The k items in the stack are the first k items in the array
Linked Lists vs Array
• Linked list implementation
flexible – size of stack can be anything
constant time per operation
Call to memory allocator can be costly
• Array Implementation
ü Memory preallocated
ü Constant time per operation.
ü Not all allocated memory is used
ü Overflow possible - Resizing can be used but
ü some ops will be more than constant time.
Detail about Linked List and single linked list ?
Linked Lists
Linked lists can be thought of from a high level perspective as being
a series of nodes. Each node has at least a single pointer to the next node,
and in the last node's case a null pointer representing that there are no
more nodes in the linked list.
In DSA our implementations of linked lists always maintain head
and tail pointers so that insertion at either the head or tail of the list is a
constant time operation. Random insertion is excluded from this and will
be a linear operation. As such, linked lists in DSA have the following
characteristics:
1. Insertion is O(1)
2. Deletion is O(n)
3. Searching is O(n)
Out of the three operations the one that stands out is that of insertion.
In DSA we chose to always maintain pointers (or more aptly references)
to the node(s) at the head and tail of the linked list and so performing a
traditional insertion to either the front or back of the linked list is an O(1)
operation. An exception to this rule is performing an insertion before a
node that is neither the head nor tail in a singly linked list. When the node
we are inserting before is somewhere in the middle of the linked list
(known as random insertion) the complexity is O(n). In order to add
before the designated node we need to traverse the linked list to ¯nd that
node's current predecessor. This traversal yields an O(n) run time.
This data structure is trivial, but linked lists have a few key points which
at times make them very attractive:
1. the list is dynamically resized, thus it incurs no copy penalty like an
array or vector would eventually incur; and
2. insertion is O(1).
Singly Linked List
Singly linked lists are one of the most primitive data structures you
will ¯nd. Each node that makes up a singly linked list consists of a value,
and a reference to the next node (if any) in the list.
Linked list
Insertion
In general when people talk about insertion with respect to linked
lists of any form they implicitly refer to the adding of a node to the tail of
the list. When you use an API like that of DSA and you see a general
purpose method that adds a node to the list, you can assume that you are
adding the node to the tail of the list not the head.
Adding a node to a singly linked list has only two cases:
1. head= ; in which case the node we are adding is now both the head
and
tailof the list; or
2. we simply need to append our node onto the end of the list updating
the
tailreference appropriately.
1) algorithm Add(value)
2) Pre: value is the value to add to the list
3) Post: value has been placed at the tail of the list
4) n à node(value)
5) ifhead = ;
6) head à n
7) tail à n
8) else
9) tail.Nextà n
10) tail à n
11) end if
12) end Add
Deletion
Deleting a node from a linked list is straightforward but there are a few
cases
we need to account for:
1. the list is empty; or
2. the node to remove is the only node in the linked list; or
3. we are removing the head node; or
4. we are removing the tail node; or
5. the node to remove is somewhere in between the head and tail; or
6. the item to remove doesn't exist in the linked list
The algorithm whose cases we have described will remove a node from
any- where within a list irrespective of whether the node is the head etc.
If you know that items will only ever be removed from the head or tail of
the list then you can create much more concise algorithms. In the case of
always removing from the front of the linked list deletion becomes an
O(1) operation.
1) algorithm Remove(head, value)
2) Pre: head is the head node in the list
3) valueis the value to remove from the list
4) Post: value is removed from the list, true; otherwise false
5) ifhead = ;
6) // case 1
7) return false
8) end if
9) n à head
10) ifn.Value = value
11) ifhead = tail
12) // case 2
13) head à ;
14) tail à ;
15) else
16) // case 3
17) head à head.Next
18) end if
19) return true
20) end if
21) whilen.Next 6= ; and n.Next.Value 6= value
22) n à n.Next
23) end while
24) ifn.Next 6= ;
25) ifn.Next = tail
26) // case 4
27) tail à n
28) end if
29) // this is only case 5 if the conditional on line 25 was false
30) n.Nextà n.Next.N
31) return true
32) end if
33) // case 6
34) return false
35) end Remove
Traversing the list
Traversing a singly linked list is the same as that of traversing a
doubly linked list .The two cases are as follows:
1. node= Exhausted all nodes in the linked list; or
2. node.Next.
The algorithm described is a very simple one that makes use of a simple
while loop to check the ¯rst case.
1) algorithm Traverse(head)
2) Pre: head is the head node in the list
3) Post: the items in the list have been traversed
4) n à head
5) while n 6= 0
6) yieldn.Value
7) n à n.Next
8) end while
9) end Traverse
Traversing the list in reverse order
Traversing a singly linked list in a forward manner (i.e. left to right)
is simple as demonstrated in x2.1.4. However, what if we wanted to
traverse the nodes in the linked list in reverse order for some reason? The
algorithm to perform such a traversal is very simple, and just like
demonstrated .Acquire a reference to the predecessor of a node, even
though the fundamental characteristics of the nodes that make up a singly
linked list make this an expensive operation. For each node, ¯nding its
predecessor is an O(n) operation, so over the course of traversing the
whole list backwards the cost becomes O(n2).
Depicts the following algorithm being applied to a linked list with
the integers 5, 10, 1, and 40.
1) algorithm ReverseTraversal(head, tail)
2) Pre: head and tail belong to the same list
3) Post: the items in the list have been traversed in reverse order
4) iftail 6= ;
5) curr à tail
6) whilecurr 6= head
7) prev à head
8) whileprev.Next 6= curr
9) prev à prev.Next
10) end while
11) yieldcurr.Value
12) curr à prev
13) end while
14) yieldcurr.Value
15) end if
16) end ReverseTraversal
This algorithm is only of real interest when we are using singly linked
lists, as you will soon see that doubly linked lists (de¯ned in x2.2) make
reverse list traversal simple and efficient.
Describe Doubly linked list ?
Doubly Linked List
Doubly linked lists are very similar to singly linked lists. The only
difference is that each node has a reference to both the next and previous
nodes in the list.
Reverse traveral of a singly linked list
Doubly linked list node
The following algorithms for the doubly linked list are exactly the same
as those listed previously for the singly linked list:
1. Searching
2. Traversal
Insertion
The only major di®erence between the algorithm is that we need to
remember to bind the previous pointer of n to the previous tail node if n
was not the ¯rst node to be inserted into the list.
1) algorithm Add(value)
2) Pre: value is the value to add to the list
3) Post: value has been placed at the tail of the list
4) n à node(value)
5) ifhead = ;
6) head à n
7) tail à n
8) else
9) n.Previousà tail
10) tail.Nextà n
11) tail à n
12) end if
13) end Add
Doubly linked list populated with integers
Deletion
Binding an additional reference to the correct value.
1) algorithm Remove(head, value)
2) Pre: head is the head node in the list
3) valueis the value to remove from the list
4) Post: value is removed from the list, true; otherwise false
5) ifhead = ;
6) return false
7) end if
8) ifvalue = head.Value
9) ifhead = tail
10) head à ;
11) tail à ;
12) else
13) head à head.Next
14) head.Previousà ;
15) end if
16) return true
17) end if
18) n à head.Next
19) whilen 6= ; and value 6= n.Value
20) n à n.Next
21) end while
22) ifn = tail
23) tail à tail.Previous
24) tail.Nextà ;
25) return true
26) else if n 6= ;
27) n.Previous.Nextà n.Next
28) n.Next.Previousà n.Previous
29) return true
30) end if
31) return false
32) end Remove
Reverse Traversal
Singly linked lists have a forward only design, which is why the reverse
traversal algorithm required some creative invention. Doubly linked lists
make reverse traversal as simple as forward traversal except that we start
at the tail node and update the pointers in the opposite direction.
shows the reverse traversal algorithm in action.
Doubly linked list reverse traversal
1) algorithm ReverseTraversal(tail)
2) Pre: tail is the tail node of the list to traverse
3) Post: the list has been traversed in reverse order
4) n à tail
5) whilen 6= ;
6) yieldn.Value
7) n à n.Previous
8) end while
9) end ReverseTraversal.
Graph
A graph is a pictorial representation of a set of objects where some pairs
of objects are connected by links. The interconnected objects are
represented by points termed as vertices, and the links that connect the
vertices are called edges.
Formally, a graph is a pair of sets (V, E), where V is the set of vertices
and E is the set of edges, connecting the pairs of vertices. Take a look at
the following graph.
In the above graph,
V = {a, b, c, d, e}
E = {ab, ac, bd, cd, de}
Graph Data Structure
Mathematical graphs can be represented in data structure. We can
represent a graph using an array of vertices and a two-dimensional array
of edges. Before we proceed further, let's familiarize ourselves with some
important terms –
• Vertex − Each node of the graph is represented as a vertex. In the
following example, the labeled circle represents vertices. Thus, A
to G are vertices. We can represent them using an array as shown
in the following image. Here A can be identified by index 0. B can
be identified using index 1 and so on.
• Edge − Edge represents a path between two vertices or a line
between two vertices. In the following example, the lines from A to
B, B to C, and so on represents edges. We can use a twodimensional array to represent an array as shown in the following
image. Here AB can be represented as 1 at row 0, column 1, BC as
1 at row 1, column 2 and so on, keeping other combinations as 0.
• Adjacency − Two node or vertices are adjacent if they are
connected to each other through an edge. In the following example,
B is adjacent to A, C is adjacent to B, and so on.
• Path − Path represents a sequence of edges between the two
vertices. In the following example, ABCD represents a path from A
to D.
Basic Operations
Following are basic primary operations of a Graph which are following.
• Add Vertex − Adds a vertex to the graph.
• Add Edge − Adds an edge between the two vertices of the graph.
• Display Vertex − Displays a vertex of the graph
Depth First Search (DFS)
Depth First Search (DFS) algorithm traverses a graph in a depth ward
motion and uses a stack to remember to get the next vertex to start a
search, when a dead end occurs in any iteration.
As in the example given above, DFS algorithm traverses from A to B to
C to D first then to E, then to F and lastly to G. It employs the following
rules.
• Rule 1 − Visit the adjacent unvisited vertex. Mark it as visited.
Display it. Push it in a stack.
• Rule 2 − If no adjacent vertex is found, pop up a vertex from the
stack. (It will pop up all the vertices from the stack, which do not
have adjacent vertices.)
• Rule 3 − Repeat Rule 1 and Rule 2 until the stack is empty.
SL.NO
Traversal
Description
1
Initialize the stack.
2.
Mark S as visited and
put it onto the stack.
Explore any unvisited
adjacent node from S.
3
Mark A as visited
and put it onto the
stack. Explore any
unvisited adjacent
node from A.
Both S and D are
adjacent to A but we
are concerned for
unvisited nodes only.
Visit D and mark it
as visited and put
onto the stack.
4
5
Have B and C nodes,
which are adjacent to
D and both are
unvisited.
However, we shall
again choose in an
alphabetical order
We choose B, mark it
as visited and put
onto the stack.
Here B does not have
any 5unvisited
adjacent node.
6
So,we pop B from
the stack
We check the stack
top for return to the
previous node and
check if it has any
unvisited nodes.
Here,We find D to be
on the top of the
stack.
Unvisitedadjacent
only node is from D
is C now.
7
So we visit C, mark
it as visited and put it
onto the stack
Breadth First Search (BFS)
Breadth First Search (BFS) algorithm traverses a graph in a breadth
ward motion and uses a queue to remember to get the next vertex to start
a search, when a dead end occurs in any iteration.
BFS
As in the example given above, BFS algorithm traverses from A to B to
E to F first then to C and G lastly to D. It employs the following rules.
• Rule 1 − Visit the adjacent unvisited vertex. Mark it as visited.
Display it. Insertit in a queue.
• Rule 2 − If no adjacent vertex is found, remove the first vertex
from the queue.
• Rule 3 − Repeat Rule 1 and Rule 2 until the queue is empty
SL.NO
1
2
3
4
Traversal
Description
Initialize the queue
We start from visiting S
(starting node), and mark
it
as visited.
We then see an unvisited
adjacent node from S. In
this example, we have
three
nodes
but
alphabetically we choose A,
mark it as visited
and enqueue it.
Next, the unvisited
adjacent
node from S is B. We mark
it
as visited and enqueue it
5
Next, the unvisited
adjacent
node from S is C. We mark
it as visited and enqueue
it.
6
Now, S is left with no
unvisited adjacent nodes.
So, we dequeue and find A
7
From A we have D as
unvisited adjacent node.
We
mark it as visited and
enqueue it.
At this stage, we are left with no unmarked (unvisited) nodes. But as per
the algorithm we keep on dequeuing in order to get all unvisited nodes.
When the queue gets emptied, the program is over.
Explain about string and characters?
Strings
Strings have their own chapter in this text purely because string operations
and transformations are incredibly frequent within programs. The
algorithmspresented are based on problems the authors have come across
previously, orwere formulated to satisfy curiosity.
Reversing the order of words in a sentence
De¯ning algorithms for primitive string operations is simple, e.g.
extracting a sub-string of a string, however some algorithms that require
more inventiveness can be a little more tricky.
The algorithm presented here does not simply reverse the characters in a
string, rather it reverses the order of words within a string. This algorithm
works on the principal that words are all delimited by white space, and
using a few markers to de¯ne where words start and end we can easily
reverse them.
1) algorithm ReverseWords(value)
2) Pre: value 6= ;, sb is a string bu®er
3) Post: the words in value have been reversed
4) last à value.Length ¡ 1
5) start à last
6) while last ¸ 0
7) // skip whitespace
8) while start ¸ 0 and value[start] = whitespace
9) start à start ¡ 1
10) end while
11) last à start
12) // march down to the index before the beginning of the word
13) while start ¸ 0 and start 6= whitespace
14) start à start ¡ 1
15) end while
16) // append chars from start + 1 to length + 1 to string bu®er sb
17) for i à start + 1 to last
18) sb.Append(value[i])
19) end for
20) // if this isn't the last word in the string add some whitespace after
the word in the bu®er
21) if start >0
22) sb.Append(` ')
23) end if
24) last à start ¡ 1
25) start à last
26) end while
27) // check if we have added one too many whitespace to sb
28) if sb[sb.Length ¡1] = whitespace
29) // cut the whitespace
30) sb.Length à sb.Length ¡1
31) end if
32) return sb
33) end ReverseWords
Detecting a palindrome
Although not a frequent algorithm that will be applied in real-life
scenarios detecting a palindrome is a fun, and as it turns out pretty trivial
algorithm to design.
The algorithm that we present has a O(n) run time complexity. Our
algorithm uses two pointers at opposite ends of string we are checking is
a palindrome or not. These pointers march in towards each other always
checking that each character they point to is the same with respect to
value. shows the IsPalindrome algorithm in operation on the string . If
you remove all punctuation, and white space from the aforementioned
string you will ¯nd that it is a valid palindrome.
left and right pointers marching in towards one another
1) algorithm IsPalindrome(value)
2) Pre: value 6= ;
3) Post: value is determined to be a palindrome or not
4) word à value.Strip().ToUpperCase()
5) left à 0
6) right à word.Length ¡1
7) while word[left] = word[right] and left < right
8) left à left + 1
9) right à right ¡ 1
10) end while
11) return word[left] = word[right]
12) end IsPalindrome
In the IsPalindrome algorithm we call a method by the name of
Strip. This algorithm discards punctuation in the string, including white
space. As a result word contains a heavily compacted representation of
the original string, each character of which is in its uppercase
representation. Palindromes discard white space, punctuation, and case
making these changes allows us to design a simple algorithm while
making our algorithm fairly robust with respect to the palindromes it will
detect.
Counting the number of words in a string
Counting the number of words in a string can seem pretty trivial at
¯rst, howeverthere are a few cases that we need to be aware of:
1. tracking when we are in a string
2. updating the word count at the correct place
3. skipping white space that delimits the words
As an example consider the string \Ben ate hay" Clearly this string
contains three words, each of which distinguished via white space. All of
the previously listed points can be managed by using three variables:
1. index
2. wordCount
3. inWord
String with three words
String with varying number of white space delimiting the words
Of the previously listed index keeps track of the current index we are at in
the string, wordCount is an integer that keeps track of the number of words
we have encountered, and ¯nally inWord is a Boolean °ag that denotes
whether or not at the present time we are within a word. If we are not
currently hitting white space we are in a word, the opposite is true if at the
present index we are hitting white space.
We don't take into account any particular splitting symbols you may use,
e.g. in .NET String.Split1 can take a char (or array of characters) that
determines a delimiter to use to split the characters within the string into
chunks of strings, resulting in an array of sub-strings.In Figure we present
a string indexed as an array. Typically the pattern is the same for most
words, delimited by a single occurrence of white space. Figure shows the
same string, with the same number of words but with varying white space
splitting them.Determining the number of repeated words within a string
With the help of an unordered set, and an algorithm that can split the
words within a string using a speci¯ed delimiter this algorithm is
straightforward to implement. If we split all the words using a single
occurrence of white space as our delimiter we get all the words within the
string back as elements of an array. Then if we iterate through these words
adding them to a set which contains only unique strings we can attain the
number of unique words from the string. All that is left to do is subtract
the unique word count from the total number of stings contained in the
array returned from the split operation.
a) Undesired uniques set; b) desired uniques set
1) algorithm RepeatedWordCount(value)
2) Pre: value 6= ;
3) Post: the number of repeated words in value is returned
4) words à value.Split(' ')
5) uniques à Set
6) foreach word in words
7) uniques.Add(word.Strip())
8) end foreach
9) return words.Length ¡uniques.Count
10) end RepeatedWordCount
RepeatedWordCount algorithm that we use the Strip method .This simply
removes any punctuationfrom a word. The reason we perform this
operation on each word is so thatwe can build a more accurate unique
string collection, e.g. \test", and \test!"are the same word minus the
punctuation. Determining the ¯rst matching characterbetween two strings
The algorithm to determine whether any character of a string matches any
of the characters in another string is pretty trivial. Put simply, we can parse
the strings considered using a double loop and check, discarding
punctuation, the equality between any characters thus returning a nonnegative index that represents the location of the ¯rst character in the
match (Figure 11.5); otherwise we return-1 if no match occurs. This
approach exhibit a run time complexity of O(n2).
a) First Step; b) Second Step c) Match Occurred
1) algorithm Any(word,match)
2) Pre: word; match 6= ;
3) Post: index representing match location if occured, ¡1 otherwise
4) for i à 0 to word:Length ¡ 1
5) while word[i] = whitespace
6) i à i + 1
7) end while
8) for index à 0 to match:Length ¡ 1
9) while match[index] = whitespace
10) index à index + 1
11) end while
12) if match[index] = word[i]
13) return index
14) end if
15) end for
16) end for
17) return ¡1
18) end Any
Sparse matrices
Sparse matrix is a matrix populated primarily with zeros. Sparse matrices
are stored using special data structures, which allow to store only nonzero
elements and save a lot of memory and CPU time when working with such
matrices.
Specialized data structures allow to solve computational problems which
are impossible to solve when matrices are stored using "conventional",
dense storage.
Usually it is linear systems with large number of variables, but almost
empty matrix. Such system arise in many areas - from partial differential
equations to large scale RBF interpolation problems. All these problems
are impossible to solve without sparse matrices. Hence, sparse
subpackage of the ALGLIB package contains data structures, which allow
tostore sparse matrices, and algorithms, which can work with them.
Below we will study different sparse storage formats employed by
sparsematrix structure, and functions which can be used on this structure.
We also briefly review algorithms which can be applied to sparse
matrices.
Contents
Sparse storage formats
Hash table storage
CRS representation
Use cases
Operations with sparse matrices
Creation - hash table storage format
Creation - CRS format
Reading matrix elements
Passing sparse matrix to other algorithms
Linear algebra operations with sparse matrices
Other functions
Sparse storage formats
Structure used for sparse matrix storage should provide following
functionality:
• Small number of non-zero entries
a) Dense matrix
b) Sparse matrix
• Non- zero encode connectivity
c)Structured matrix d)Unstructured matrix e)general matrix
Variety of direct and iterative methods
• Sparse matrix-vector manipulation
Y=A*X
• Vector scale and Add
x=x+ omega*r
• vector norm
norm( r)
maintain list of nonzero elements and their values
retrieve element by its indexes i/j
enumerate all nonzero elements in the matrix
insert new element in the matrix
multiply sparse matrix by vector (or dense matrix)
other service operations
There are several popular data structures which are used to store sparse
matrices, each with its own benefits and drawbacks. ALGLIB package
implements two such structures: hash table storage (also known as
Dictionary of keys) and CRS (Compressed row storage).
Hash table storage
Sparse matrix can be stored as hash table which maps keys (row/column
indexes) to values of corresponding elements. Such storage format has
following features:
Matrix Creation - requires to know only matrix size. It is not necessary
to know amount of nonzero elements, although you can benefit from such
knowledge. It will allow you to allocate required amount of space during
matrix creation and to avoid subsequent reallocations of the hash table
during initialization of the matrix elements.
Time To Insert Element - O(1). Elements can be inserted in arbitrary
order. However, when hash table becomes nearly full we have to spend
O(TableSize) time creating new, larger table and copying elements from
the old one.
Memory Requirements - O(γ·(2·sizeof(int)+sizeof(double))) per one
nonzero element in nearly full table. Here γ is a small constant from]which
is a consequence of the fact that hash table require some amount of "spare
memory".
Time To Read Element - O(1). Hash tables are quite fast and allow
arbitrary access to elements.
Time To Enumerate All Nonzero Elements - O (Table Size), where
Table Size is a total size of hash table (including both busy and free
elements). Hash table allows enumerating its entries, but it does not
provide any ordering guarantee. Elements of the matrix will be retrieved
in arbitrary order.
Linear Operations With Matrix (Matrix-Vector Products, MatrixMatrix Products)- not supported. Hash table stores matrix elements in
random order, which prevents efficient implementation of the linear
algebra operations. Thus, in order to use matrix in linear operations you
have to convert it to CRS format.
You may see that hash table storage allows easy creation and modification
of sparse matrices. We may access (read and write) elements in arbitrary
order, we do not have to know table size in advance; we have fast random
access to the table. However, this storage format.
UNIT II
A Brief History Linux
● UNIX was developed in 1969 at AT&T Bell Labs
● Many variants since then: BSD, Solaris, MacOS X, Linux ...
● The Linux kernel was first developed in 1991 by Linus Torvalds, a
student at the University of Helsinki
● Linux has been widely adopted for servers and HPC systems.
● All CCMST servers run Linux.
Introduction to Linux
Linux is quite possibly the most important achievement of free
software since the original Space War, or, more recently, Emacs. It has
developed into the operating system for businesses, education, and
personal productivity. Linux is no longer just for UNIX wizards who sit
for hours in front of the glowing console (although we assure you that
quite a number of users fall into this category). This book will help you
get the most out of it.
Linux (pronounced with a short i, as in LIH-nucks) is a clone of the
UNIX operating system that runs on Intel 80386 and 80486 computers. It
supports a wide range of software, from TEX to X Windows to the GNU
C/C++ compiler to TCP/IP. It’s a versatile, bona fide implementation of
UNIX, freely distributed by the terms of the GNU General Public License
(see Appendix E).
Linux can turn any 386 or 486 PC into a workstation. It will give
you the full power of UNIX at your fingertips. Businesses are installing
Linux on entire networks of machines, using the operating system
tomanage financial and hospital records, a distributed user computing
environment, telecommunications, and more. Universities worldwide are
using Linux for teaching courses on operating systems programming and
design. And, of course, computing enthusiasts everywhere are using
Linux at home, for programming, productivity,and all-around hacking.
What makes Linux so different is that it is a free implementation of UNIX.
It was and still is developed bya group of volunteers, primarily on the
Internet, exchanging code, reporting bugs, and fixing problems in an
open-ended environment. Anyone is welcome to join in the Linux
development effort: all it takes is interest in hacking a free UNIX clone
and some kind of programming know-how. The book that you hold in
your hands is your tour guide.
A Brief History of Linux
Linux is not difficult to install and use. However, as with any
implementation of UNIX, there is often some black magic involved to get
everything working correctly. We hope that this book will get you on the
Linux tourbus and show you how groovy this operating system can be.
• The design and philosophy of this unique operating system, and
what it can do for you.
• All of the details of what is needed to run Linux, including suggestions
on what kind of hardware configuration is recommended for a complete
system.
• How to obtain and install Linux. There are many distributions of the
Linux software. We present a general discussion of Linux software
distributions, how to obtain them, and generic instructions for
installing the software (which should be applicable to any distribution).
• A brief introductory UNIX tutorial, for those users who have never had
experience with UNIX before. This tutorial should, hopefully, provide
enough material for complete novices to have enough basic Know-how to
find their way around the system.
• An introduction to systems administration with Linux. This covers the
most important tasks that new Linux administrators will need to be
familiar with, such as creating users, managing filesystems, and so forth.
• Information on configuring more advanced aspects of Linux, such as the
X Window System, networking with TCP/IP and SLIP, and the setup of
electronic mail and news systems.
UNIX experience, but do expect novices to refer to other materials along
the way. For those unfamiliar with
UNIX, a list of useful sources of information is given in Appendix A.
The Linux Operating System
● The Kernel is the core of Linux.
● Boot code
● Device drivers
● Memory and file management
● TheDevelopment Environment
● Compilers, assembler, linker
● System libraries
● Other tools: object archive manager, debugger .
The User Interface handles interactions
Between user and system
● Command line interface aka the shell (bash, tcsh)
● Graphical desktop (Gnome, KDE)
● Communication software (ftp, ssh)
● TheDocumentation
● Man pages
● Linux is multi-user and multi-tasking.
Commands to Navigate the Directory Tree
● lslists the contents of a directory
● long listing: ls -l
● list hidden files: ls -a
● pwdprints the working directory
● cdchanges the working directory
● absolute paths start with a '/'
● . and ..are special directories
● ~ is an alias to the user home directory
● mkdircreates a directory.
Commands to Manipulate Files
● cpmakes a copy of a file
● cpfile1 file2 creates a copy of file1 and names it
file2
● mvrenames a file
● mvfile1 file2
● operates on files or directories
● rmremoves a file
● rm -i asks for confirmation
● in UNIX there is no simple undelete command
● rmdirremoves an empty directory.
● filedisplays the file type
● catdisplays the content of a file
● lessdisplays the content one page at a time
● <space>advances one page (b goes backward)
● <enter> advances one line
● /<expr>goes to the next occurrence of <expr>
● grep<expr> filename prints the lines of a file
matching the expression
● grep -i for case unsensitive matching
● wc-l filename counts the lines of a file
● wc -w counts the words
● wc -c counts the characters
● tailfilename displays the last few lines.
Input/Output redirection
● <redirects the input of a command
● >redirects the output of a command
● >>appends the output of a command
● | concatenates two commands: the output of
the first command becomes the input to the
second one
Wildcards
● ? matches exactly one occurrence of any
character
● ?ool matches cool, pool, fool but not spool
● * matches zero or more occurrences af any
character.
● *ool matches all the above, but not cooler.
Requirements
As it turns out, most of the popular hardware and peripherals for
80386/80486 systems are supported (in fact, Linux supports more
hardware than some commercial implementations of UNIX). However,
some of the more obscure and esoteric devices aren’t supported yet. As
time goes on, a wider range of hardware is supported, so if your favorite
devices aren’t listed here, chances are that support for them is
forthcoming.
Another drawback for hardware support under Linux is that many
companies have decided to keep the hardware interface proprietary. The
upshot of this is that volunteer Linux developers simply can’t write drivers
for those devices (if they could, those drivers would be owned by the
company that owned the interface, which would violate the GPL). The
companies that maintain proprietary interfaces write their own drivers for
operating systems such as MS-DOS and MicrosoftWindows; the end user
(that’s you) never needs to know about the interface. Unfortunately, this
does not allow Linux developers to write drivers for those
devices.
There is very little that can be done about the situation. In some
cases, programmers have attempted to write hackish drivers based on
assumptions about the interface. In other cases, developers will work with
the company in question and attempt to obtain information about the
device interface, with varying degrees of success.
In the following sections, we’ll attempt to summarize the hardware
requirements for Linux. The Linux Hardware HOWTO contains a more
complete listing of hardware supported by Linux.
Motherboard and CPU requirements
Linux currently supports systems with an Intel 80386, 80486, or
Pentium CPU. This includes all variations on this CPU type, such as the
386SX, 486SX, 486DX, and 486DX2. Non-Intel “clones”, such as AMD
and Cyrix processors, work with Linux as well. If you have a 80386 or
80486SX, you may also wish to use a math coprocessor, although one
isn’t required (the Linux kernel can do FPU emulation if you do not have
a math coprocessor). All standard FPU couplings are supported, such as
IIT, Cyrix FasMath, and Intel coprocessors.
The system motherboard must use ISA or EISA bus architecture.
These terms define how the system interfaces with peripherals and other
components on the main bus. Most systems sold today are either ISA or
EISA bus. IBM’s MicroChannel (MCA) bus, found on machines such as
the IBM PS/2, is not currently supported.
Systems which use a local bus architecture (for faster video and disk
access) are supported as well. It is suggested that you have a standard local
bus architecture such as the VESA Local Bus (“VLB”).
Memory requirements
Linux requires very little memory to run compared to other
advanced operating systems.2 megabytes of RAM however,it is strongly
suggested that you have 4 megabytes. The more
Hardware Requirements
Memory you have, the faster the system will run. Linux can support
the full 32-bit address range of the 386/486; in other words, it will utilize
your entire RAM automatically.
Linux will run happily with only 4 megabytes of RAM, including
all of the bells and whistles such as X Windows, Emacs, and so on.
However, having more memory is almost as important as having a faster
processor. 8 megabytes is more than enough for personal use; 16
megabytes or more may be needed if you are expecting a heavy user load
on the system.
Most Linux users allocate a portion of their hard drive as swap
space, which is used as virtual RAM. Even if you have a great deal of
physical RAM in your machine, you may wish to use swap space. While
swap space is no replacement for actual physical RAM, it can allow your
system to run larger applications by swapping out inactive portions of
code to disk. The amount of swap space that you should allocate depends
on several factors.
Hard drive controller requirements
`However, this is slow and very limited, and many users have access
to hard drive storage anyway. You must have an AT-standard (16-bit)
controller. There is support in the kernel for XT-standard (8 bit)
controllers; however, most controllers used today are AT-standard. Linux
should support all MFM, RLL, and IDE controllers.
Most, but not all, ESDI controllers are supported—only those which
do ST506 hardware emulation. The general rule for non-SCSI hard drive
and floppy controllers is that if you can access the drive from
MS-DOS or another operating system, you should be able to access
it from Linux. Linux also supports a number of popular SCSI drive
controllers, although support for SCSI is more limited because of the wide
range of controller interface standards. Supported SCSI controllers
include the Adaptec AHA1542B, AHA1542C, AHA1742A (BIOS
version 1.34), AHA1522, AHA1740, AHA1740(SCSI-2 controller, BIOS
1.34 in Enhanced mode); Future Domain 1680, TMC-850, TMC-950;
Seagate ST-02; UltraStor SCSI; Western Digital WD7000FASST. Clones
which are based on these cards should work as well.
Hard drive space requirements
Linux will support multiple hard drives in the same machine; you
can allocate space for Linux across multiple drives if necessary.
The amount of hard drive space that you will require depends greatly on
your needs and the amount of software that you’re installing. Linux is
relatively small as UNIX implementations go; you could run a complete
system in 10 to 20 megabytes of space on your drive. However, if you
want to have room for expansion, and for larger packages such as X
Windows, you will need more space. If you plan to allow multiple users
to use the machine, you will need to allocate storage for their files. Also,
unless you have a large amount of physical RAM(16 megabytes or more),
you will more than likely want to allocate swap space, to be used as virtual
RAM. We will discuss all of the details of installing and
Hardware Requirements
Each distribution of Linux usually comes with some literature that
should help you to gauge the precise amount of required storage
depending on the amount of software you plan to install. You can run a
minimal system with less than 20 megabytes; a complete system with all
of the bells and whistles in 80 megabytes or less; and a very large system
with room for many users and space for future expansion in the range of
100-150 megabytes. Again, these figures are meant only as a ballpark
approximation; you will have to look at your own needs and goals in order
to determine your specific storage requirements.
Monitor and video adapator requirements
Linux supports all standard Hercules, CGA, EGA, VGA, IBM
monochrome, and Super VGA video cards and monitors for the default
text-based interface. In general, if the video card and monitor coupling
worksunder another operating system such as MS-DOS, it should work
fine with Linux. Original IBM CGA cards suffer from “snow” under
Linux, which is not pleasant to use. Graphical environments such as the
X Window System have video hardware requirements of their own. In
short, to run the X Window System on your Linux machine, you will need
one of the video cards listed in that section.
Miscellaneous hardware
The above sections described the hardware which is required to run
a Linux system. However, most users have a number of “optional” devices
such as tape and CD-ROM storage, sound boards, and so on, and are
interested in whether or not this hardware is supported by Linux.
Mice and other pointing devices
For the most part, you will only be using a mouse under a graphical
environment such as the X Window System. However, several Linux
applications not associated with a graphics environment do make use of
the mouse.
Linux supports all standard serial mice, including Logitech, MM series,
Mouseman, Microsoft (2-button) and Mouse Systems (3-button). Linux
also supports Microsoft, Logitech, and ATIXL busmice. The PS/2 mouse
interface is supported as well.
All other pointing devices, such as trackballs, which emulate the above
mice, should work as well.
CD-ROM storage
Almost all CD-ROM drives use the SCSI interface. As long as you
have a SCSI adaptor supported by Linux, then your CD-ROM drive
should work. A number of CD-ROM drives have been verified to work
under Linux, including the NEC CDR-74, Sony CDU-541, and Texel
DM-3024. The Sony internal CDU-31a and the Mistsumi CD-ROM
drives are supported by Linux as well.Linux supports the standard ISO9660 filesystem for CD-ROMs.
Tape drives
There are several types of tape drives available on the market. Most
of them use the SCSI interface, all of which should be supported by Linux.
Among the verified SCSI tape drives are the Sankyo CP150SE; Tandberg
3600; Wangtek 5525ES, 5150ES, and 5099EN with the PC36 adaptor.
Other QIC-02 drives should be supported as well.
Drivers are currently under development for various other tape
devices, such as Colorado drives which hang off of the floppy controller.
Printers
Linux supports the complete range of parallel printers. If you are
able to access your printer via the parallel port from MS-DOS or another
operating system, you should be able to access it from Linux as well. The
Linux printing software consists of the UNIX standard lp and lpr software.
This software also allows you to print remotely via the network, if you
have one available.
Modems
As with printer support, Linux supports the full range of serial
modems, both internal and external. There is a great deal of
telecommunications software available for Linux, including Kermit,
pcomm, minicom, and Seyon. If your modem is accessible from another
operating system on the same machine, you should be able to access it
from Linux with no difficulty.
Ethernet cards
Many popular Ethernet cards and LAN adaptors are supported by Linux.
These include:
• 3com 3c503, 3c503/16
• Novell NE1000, NE2000
• Western Digital WD8003, WD8013
• Hewlett Packard HP27245, HP27247, HP27250
• D-Link DE-600
The following clones are reported to work:
• LANNET LEC-45
• Alta Combo
• Artisoft LANtastic AE-2
• Asante Etherpak 2001/2003.
Sources of Linux Information
• D-Link Ethernet II
• LTC E-NET/16 P/N 8300-200-002
• Network Solutions HE-203,
• SVEC 4 Dimension Ethernet
• 4-Dimension FD0490 EtherBoard 16
Clones which are compatible with any of the above cards should work as
well.
Sources of Linux Information
If you are new to the UNIX world, we seriously suggest that you
take the time to peruse one of these books before you attempt to brave the
jungles of Linux. Specifically, the book Learning the UNIX Operating
System, by Grace Todino and John Strang, is a good place to start.
Many of the following sources of information are available online
in some electronic form. That is, you must have access to an online
network, such as the Internet, USENET, or Fidonet, in order to access the
information contained therein. If you do not have online access to any of
this material, you might be able to find someone kind enough to give you
hardcopies of the documents in question.
Online documents
If you have access to the Internet, there are many Linux documents
available via anonymous FTP from archive sites all over the world. If you
do not have direct Internet access, these documents may still be available
to you: many Linux distributions on CD-ROM contain all of the
documents mentioned here. Also, they are distributed on many other
networks, such as Fidonet and CompuServe. If you are able to send mail
to Internet sites, you may be able to retrieve these files using one of the
ftpmail servers which will electronically mail you the documents or files
from FTP archive sites. See Appendix C for more information on using
ftpmail.
There is a great number of FTP archive sites which carry Linux
software and related documents. A list of well-known Linux archive sites
is given in Appendix C. In order to reduce network traffic, you should
always use the FTP site which is geographically (network-wise) closest to
you. Appendix A contains a listing of some of the Linux documents which
are available via anonymous FTP. The filenames will differ depending on
the archive site in question most sites keep Linux-related documents in
the docs subdirectory of their Linux archive space. For example, on the
FTP site sunsite.unc.edu, Linux files are stored in the directory
/pub/Linux, with Linux-related documentation being found in
/pub/Linux/docs.
Installing linux
Preparing to Install Linux
After you have obtained a distribution of Linux, you’re ready to
prepare your system for installation. This takes a certain degree of
planning, especially if you’re already running other operating systems. In
the following sections we’ll describe how to plan for the Linux
installation.
Preparing to Install Linux
Installation overview
While each release of Linux is different, in general the method used to
install the software is as follows:
1. Repartition your hard drive(s). If you have other operating systems
already installed, you will need to repartition the drives in order to
allocate space for Linux.
2. Boot the Linux installation media. Each distribution of Linux has
some kind of installation media— usually a “boot floppy”—which is used
to install the software. Booting this media will either present you with
some kind of installation program, which will step you through the Linux
installation, or allow you to install the software by hand.
3. Create Linux partitions. After repartitioning to allocate space for
Linux, you create Linux partitions on that empty space. This is
accomplished with the Linux fdisk program.
4. Create filesystems and swap space. At this point, you will create one
or more filesystems, used to store files, on the newly-created partitions. In
addition, if you plan to use swap space, you will create
the swap space on one of your Linux partitions.
5. Install the software on the new filesystems. Finally, you will install
the Linux software on your newly-created filesystems. After this, it’s
smooth sailing—if all goes well.
Many distributions of Linux provide an installation program which will
step you through the installation process, and automate one or more of the
above steps for you. Keep in mind throughout this chapter that any
number of the above steps may be automated for you, depending on the
distribution. The Slackware distribution of Linux, covered in this book,
only requires you to repartition your drive, using fdisk, and use the setup
program to accomplish the other steps.
Important hint: While preparing to install Linux, the best advice that we
can give is to take notes during the entire procedure. Write down
everything that you do, everything that you type, and everything that you
see that might be out of the ordinary. The idea here is simple: if (or when!)
you run into trouble, you want to be able to retrace your steps and find out
what went wrong. Installing Linux isn’t difficult, but there are many
details to remember. You want to have a record of all of these details so
that you can experiment with other methods if something goes wrong.
Also, keeping a notebook of your Linux installation experience is useful
when you want to ask other people for help, for example, when posting a
message to one of the Linux-related USENET groups. Your notebook is
also something that you’ll want to show to your grandchildren someday.
Repartitioning concepts
In general, hard drives are divided into partitions, where a single
partition is devoted to a single operatingsystem. For example, on one hard
drive, you may have several separate partitions—one devoted to, say, MSDOS, another to OS/2, and another to Linux.
The author shamefully admits that he kept a notebook of all of his
tribulations with Linux for the first few months of working with
the system. It is now gathering dust on his bookshelf.
Installing the Linux software
Copy onto this floppy all of the necessary MS-DOS utilities (usually most
of the software in the directory \DOS on your drive), as well as the
programs FORMAT.COM and FDISK.EXE. You should now be able to
boot this floppy, and run the command FDISK C: to start up FDISK.
Use of FDISK should be self-explanatory, but consult theMS-DOS
documentation for details. When you start FDISK, use the menu option to
display the partition table, and write down the information displayed
there. It is important to keep a record of your original setup in case you
want to back out of the Linux installation.
To delete an existing partition, choose the FDISK menu option
“Delete an MS-DOS Partition or Logical DOS Drive”. Specify the type
of partition that you wish to delete (primary, extended, or logical) and the
number of the partition.
To create a new (smaller) partition for MS-DOS, just choose the
FDISK option “Create an MS-DOS Partition or Logical DOS Drive”.
Specify the type of partition (primary, extended, or logical), and the size
of the partition to create (specified in megabytes). FDISK should create
the partition and you’re ready to roll.
After you’re done using FDISK, you should exit the program and
reformat any new partitions. For example, if you resized the first DOS
partition on your drive (C:) you should run the commandFORMAT /s C:
Configuring the Interface
•
•
•
•
TCP/IP support different physical networks
The installation prompts questions and put info in script files
We will examine the detail of ifconfig
We will also configure PPP, a standard Network Access Layer
protocol used to run TCP/IP over modem connection
ifconfig command
Set/check configuration values for network interfaces.
Sets IP, subnet mask, broadcast address
_ “ifconfig dnet0 172.16.12.2 netmask 255.255.255.0 broadcast
172.16.12.255”
• Interface
• Address
– If hostname, then has to show up in /etc/hosts because ifconfig usually
executes before DNS starts.
• Netmask mask
– Ifgnore this only if you are using the default mask
• Broadcast address
– Default is IP with all host bits set to 1.
• _ It can also be “ifconfig dnet0 172.16.12.2/24”.
How to find out the interface name
_ Get console message during boot-up
_ Check the system message using dmesg On Sun, use “dmesg | grep
Network”
On Linux, use “dmesg | grep eth”
_ Check hardware devices
• For example,
on HP-UX, “ioscan –funC lan”
on Tru64 Unix, “hwmgr -v h”
_ Use ifconfig command to show the interface
• Name
Check configured interfaces: netstat
For example On Sun Solaris:
[ruihong@cslserver ~]$ netstat -in
Name Mtu Net/Dest Address Ipkts Ierrs Opkts Oerrs Collis Queue
lo0 8232 127.0.0.0 127.0.0.1 2073163 0 2073163 0 0 0
hme0 1500 141.219.152.0 141.219.153.30 166004904 8 178666393 0 0 0
_ Name
_ Mtu
_ Net/Dest
• Special case: Point-to-point link
_ Address
_ Ipkts
_ Ierrs
_ Opkts
_ Oerrs
_ Collis
• Ethernet collisions are a normal condition caused by
Ethernet traffic contention.
_ Queue
• • How many packets are waiting transmission. Normally 0.
Checking the Interface with Ifconfig
_ Show what interfaces are available
_ Netstat only show configured
_ On Solaris, ifconfig –a
_ On Linux, ifconfig
_ Check the current value: ifconfig interface
• On SUN.
Assigning an address
• _ Directly
• _ #ifconfig e1000g0 192.168.100.11
• _ Indirectly
• _ Use a hostname from /etc/hosts
• • # ifconfig dnet0 crab netmask 255.255.255.0
• _ Vendor take address to another level of indirection.
• • Solaris
• – hostname in defined in the file /etc/hostname.interface.
ruihong@cslserver
/etc]$
more
hostname.hme0
cslserver.csl.mtu.edu
[ruihong@cslserver
/etc]$
grep
cslserver /etc/hosts
• 141.219.153.30
cslserver.csl.mtu.edu cslserver
Linux systems
– /etc/sysconfig/network-script/ifcfg-eth0
[ruihong@dafinn network-scripts]$ pwd; cat ifcfg-eth0
/etc/sysconfig/network-scripts
# Intel Corp.|82801EB (ICH5) PRO/100 VE Ethernet
Controller
DEVICE=eth0
BOOTPROTO=none
HWADDR=00:0C:F1:79:7C:53
IPADDR=141.219.152.107
NETMASK=255.255.252.0
ONBOOT=yes
TYPE=Ethernet
USERCTL=no
PEERDNS=no
GATEWAY=141.219.152.1
Assigning a Subnet Mask
_ Explicitly
# ifconfig le0 172.16.12.2 netmask 255.255.255.0
_ Indirectly
• Linux:
– /etc/sysconfig/network-script/ifcfg-eth0 has a line as
NETMASK=255.255.252.0
• Solaris:
– /etc/inet/netmasks
[ruihong@cslserver /etc]$ more /etc/inet/netmasks
#
# The netmasks file associates Internet Protocol (IP) address
# masks with IP network numbers.
#
# network-number netmask
# Both the network-number and the netmasks are specified in
# "decimal dot" notation, e.g:
#
# 128.32.0.0 255.255.255.0
#
141.219.152.0 255.255.252.0
Setting the Broadcast Address
_ Default
_ ifconfig can compute it automatically – all hosts
bits set to 1 ( RFC919)
_ Direct value
_ # ifconfig dnet0 172.16.12.1 netmask 255.255.255.0 broadcast
172.16.12.255
_ Use ifconfig with indirect value
• For Solaris, use /etc/inet/netmasks
# ifconfig dnet0 172.16.12.1 netmask + broadcast +
• For Linux, use /etc/sysconfig/network-script/ifcfgeth0
_ More Options
_ Enabling/disabling the interface before reconfigure the
interface
# ifconfig eth0 down
# ifconfig eth0 172.16.1.2 up
_ Disable ARP with keyword –arp and enable with keyword arp
• A host can not handle ARP
• Default is enabled, leave it as the default.
_ Promiscuous mode
• Examine the packets traveling on a local Ethernet .
– Passed all frames up without regard to the address in those frames.
• On Linux, enable it use promisc. Default is disabled.
$ifconfig eth0 promisc
_ Metric
• On some system, ifconfig creates an entry in the routing table.
Linux doesn’t.
# ifconfig std0 10.204.0.19 metric 3
• RIP make routing decisions based on the cost of a route.
• Set the routing metric in routing table is better than in ifconfig
command line.
More Options
_ Maximum Transmission Unit (MTU)
• Largest MTU is default because it normally provides
the best performance
• In special situation, smaller MTU may help:
– Traffic from large MTU network to smaller MTU network
, Fragmentation cause performance problem.
– Reduce buffer overruns temporarily.
» For example, low end equipment on serial line
connection.
• On Ethernet, the maximum size is 1500.
• To change MTU for FDDL from default 4500bytes to
1500:
#ifconfig fddi0 172.16.16.1
Lost the change after reboot?
_ Ifconfig only changes the runtime env
_ Putting ifconfig cmds in the startup scripts
• For SYSTEM V like Solaris, add to runlevel 3 dir
• For BSD or linux, add it to rc.local
_ Change the configuration files
_ Use system provided tools
_ FC: /usr/sbin/system-config-network
_ Solaris: sys-unconfig and reboot.
Nerwork Protocols In Linux
Network layers
Seven OSI layers
When talking about protocol layers, people usually mention the seven
layers of the osi protocol (Application, Presentation, Session, Transport,
Network, Data Link and Physical).We will discuss layers 2 and 3 in depth,
and focus less on the other layers. The reason isthat these layers are
important for understanding networks. You will hear administrators use
words like "this is a layer 2 device" or "this is a layer 3 broadcast", and
you should be able to understand what they are talking about.
Four DoD layers
The DoD (or tcp/ip) model has only four layers, roughly mapping
its network access layer to OSI layers 1 and 2 (Physical and Datalink),
its internet (IP) layer to the OSI network layer, its host-to-host (tcp,
udp) layer to OSI layer 4 (transport) and its application layer to OSI
layers 5, 6 and 7.
Below an attempt to put OSI and DoD layers next to some protocols and
devices.
Physical layer
The physical layer, or layer 1, is all about voltage, electrical signals
and mechanical connections. Some networks might still use coax cables,
but most will have migrated to utp with rj45 connectors.
Devices like repeaters and hubs are part of this layer. You cannot use
software to 'see' a repeater or hub on the network. The only thing these
devices are doing is amplifying electrical signals on cables. Passive hubs
are multiport amplifiers that amplify an incoming electrical signal on all
other connections. Active hubs do this by reading and retransmitting bits,
without interpreting any meaning in those bits. Network technologies like
csma/cd and token ring are defined on this layer.
Data link layer
The data link layer, or layer 2 is about frames. A frame has a crc
(cyclic redundancy check). In the case of ethernet (802.3), each network
card is identifiable by a unique 48-bit mac address (media access control
address).
On this layer we find devices like bridges and switches. A bridge is
more intelligent than a hub because a bridge can make decisions based on
the mac address of computers. A switch also understands mac addresses.
Network layer
Layer 3 is about ip packets. This layer gives every host a unique 32bit ip address. But ip is not the only protocol on this layer, there is also
icmp, igmp, ipv6 and more. A completelist can be found in the
/etc/protocols file.
On this layer we find devices like routers and layer 3 switches,
devices that know (and have) an ip address.
Transport layer
We will discuss the tcp and udp protocols in the context of layer 4.
The DoD model calls this the host-to-host layer
Layers 5, 6 and 7
The tcp/ip application layer includes layers 5, 6 and 7. Details on the
difference between these layers are out of scope of this course
Network layers
Stacking of layers in this book is based on the Protocols in Frame
explanation in thewireshark sniffer. When sniffing a dhcp packet, we
notice the following in the sniffer.
[Protocols in Frame: eth:ip:udp:bootp]
Sniffing for ntp (Network Time Protocol) packets gives us this line, which
makes us conclude to put ntp next to bootp in the protocol chart below.
[Protocols in Frame: eth:ip:udp:ntp]
Sniffing an arpbroadcast makes us put arp next to ip. All these protocols
are explained later in this chapter.
[Protocols in Frame: eth:arp]
Below is a protocol chart based on wireshark's knowledge. It contains
some very common protocols that are discussed in this book. The chart
does not contain all protocols.
Network file system
Protocol versions
The older nfs versions 2 and 3 are stateless (udp) by default, but they can
use tcp. Clients connect to the server using rpc (on Linux this is controlled
by the portmap daemon. Look at rpcinfo to verify that nfs and its related
services are running.
root@RHELv4u2:~# /etc/init.d/portmap status
portmap (pid 1920) is running...
root@RHELv4u2:~# rpcinfo -p
program vers proto port
100000 2 tcp 111 portmapper
100000 2 udp 111 portmapper
100024 1 udp 32768 status
100024 1 tcp 32769 status
root@RHELv4u2:~# service nfs start
Starting NFS services:
[ OK ]
Starting NFS quotas:
[ OK ]
Starting NFS daemon:
[ OK ]
The same rpcinfo command when nfs is started.
root@RHELv4u2:~# rpcinfo -p
program vers proto port
100000 2 tcp 111 portmapper
100000 2 udp 111 portmapper
100024 1 udp 32768 status
100024 1 tcp 32769 status
100011 1 udp 985 rquotad
100011 2 udp 985 rquotad
100011 1 tcp 988 rquotad
100011 2 tcp 988 rquotad
100003 2 udp 2049 nfs
100003 3 udp 2049 nfs
100003 4 udp 2049 nfs
100003 2 tcp 2049 nfs
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100021 1 udp 32770 nlockmgr
100021 3 udp 32770 nlockmgr
100021 4 udp 32770 nlockmgr
100021 1 tcp 32789 nlockmgr
100021 3 tcp 32789 nlockmgr
100021 4 tcp 32789 nlockmgr
100005 1 udp 1004 mountd
100005 1 tcp 1007 mountd
100005 2 udp 1004 mountd
100005 2 tcp 1007 mountd
100005 3 udp 1004 mountd
100005 3 tcp 1007 mountd
root@RHELv4u2:~#
nfs version 4 requires tcp (port 2049) and supports Kerberos user
authentication as an option. nfsauthentication only takes place when
mounting the share. nfsversions 2 and 3 authenticate only the host Starting
NFS mountd.
Configuring DHCP
Introduction to dhcp
Dynamic Host Configuration Protocol (or short dhcp) is a standard
tcp/ip protocol that distributes ip configurations to clients. dhcpis defined
in rfc 2131 (before that it was defined as an update to bootp in rfc
1531/1541. The alternative to dhcp is manually entering the ip
configuration on each client computer.
Four broadcasts
Dhcp works with layer 2 broadcasts. A dhcp client that starts, will
send a dhcp discover on the network. All dhcp servers (that have a lease
available) will respond with a dhcp offer. The client will choose one of
those offers and will send a dhcp request containingthe chosen offer. The
dhcp server usually responds with a dhcp ack(knowledge).
When this procedure is finished, then the client is allowed to use that
ip-configuration until the end of its lease time.
Picturing dhcp
Here we have a small network with two dhcp servers named DHCPSRV1 and DHCPSRV2 and two clients (SunWS1 and Mac42). All
computers are connected by a hub or switch (pictured in the middle). All
four computers have a cable to the hub (cables not pictured
1. The client SunWS1 sends a dhcp discover on the network. All
computers receive this
broadcast.
2. Both dhcp servers answer with a dhcp offer. DHCP-SRV1 is a
dedicated dhcp server
and is faster in sending a dhcp offer than DHCP-SRV2 (who happens to
also be a file server).
3. The client chooses the offer from DHCP-SRV1 and sends a dhcp
request on the network.
4. DHCP-SRV1 answers with a dhcp ack (short for acknowledge).
All four broadcasts (or five when you count both offers) can be layer 2
ethernet broadcast to mac address ff:ff:ff:ff:ff:ffand a layer 3 ip broadcast
to 255.255.255.255.
The same story can be read in rfc 2131.
Installing a dhcp server
dhcp server for Debian/Mint
debian5:~# aptitude install dhcp3-server
Reading package lists... Done
Building dependency tree
Reading state information... Done
Reading extended state information
Initializing package states... Done
Reading task descriptions... Done
The following NEW packages will be installed:
dhcp3-server
You get a configuration file with many examples.
debian5:~# ls -l /etc/dhcp3/dhcpd.conf
-rw-r--r-- 1 root root 3551 2011-04-10 21:23 /etc/dhcp3/dhcpd.conf
Dhcp server for RHEL/CentOS
Installing is easy with yum.
[root@rhel71 ~]# yum install dhcp
Loaded plugins: product-id, subscription-manager
Resolving Dependencies
--> Running transaction check
---> Package dhcp.x86_64 12:4.2.5-36.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
===================================================
=============================
Package Arch Version Repository Size
===================================================
=============================
Installing:
dhcp x86_64 12:4.2.5-36.el7 rhel-7-server-rpms 510 k
Transaction Summary
===================================================
=============================
Install 1 Package
Total download size: 510 k
Installed size: 1.4 M
Is this ok [y/d/N]: y
Downloading packages:
dhcp-4.2.5-36.el7.x86_64.rpm | 510 kB 00:01
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : 12:dhcp-4.2.5-36.el7.x86_64 1/1
Verifying : 12:dhcp-4.2.5-36.el7.x86_64 1/1
Installed:
dhcp.x86_64 12:4.2.5-36.el7
Complete!
[root@rhel71 ~]#
After installing we get a /etc/dhcp/dhcpd.conf that points us to an
example file named
dhcpd.conf.sample.
[root@rhel71 ~]# cat /etc/dhcp/dhcpd.conf
#
# DHCP Server Configuration file.
# see /usr/share/doc/dhcp*/dhcpd.conf.example
# see dhcpd.conf(5) man page
#
[root@rhel71 ~]#
So we copy the sample and adjust it for our real situation. We name the
copy /etc/dhcp/
dhcpd.conf.
[root@rhel71 ~]# cp /usr/share/doc/dhcp-4.2.5/dhcpd.conf.example
/etc/dhcp/dhcp\
d.conf
[root@rhel71 ~]# vi /etc/dhcp/dhcpd.conf
[root@rhel71 ~]# cat /etc/dhcp/dhcpd.conf
option domain-name "linux-training.be";
option domain-name-servers 10.42.42.42;
default-lease-time 600;
max-lease-time 7200;
log-facility local7;
subnet 10.42.0.0 netmask 255.255.0.0 {
range 10.42.200.11 10.42.200.120;
option routers 10.42.200.1;
}
[root@rhel71 ~]#
The 'routers' option is valid for the subnet alone, whereas the 'domainname' option is global
(for all subnets).
Time to start the server. Remember to use systemctl start dhcpd on
RHEL7/CentOS7 and
service dhcpd start on previous versions of RHEL/CentOS.
[root@rhel71 ~]# systemctl start dhcpd
[root@rhel71 ~]#
Client reservations
You can reserve an ip configuration for a client using the mac
address.
host pc42 {
hardware ethernet 11:22:33:44:55:66;
fixed-address 192.168.42.42;
}
You can add individual options to this reservation.
host pc42 {
hardware ethernet 11:22:33:44:55:66;
fixed-address 192.168.42.42;
option domain-name "linux-training.be";
option routers 192.168.42.1;
}
Example config files
Below you see several sections of /etc/dhcp/dhcpd.conf on a Debian 6
server
# NetSec Antwerp Network
introduction to dhcp
164
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.20 192.168.1.199;
option domain-name-servers ns1.netsec.local;
option domain-name "netsec.local";
option routers 192.168.1.1;
option broadcast-address 192.168.1.255;
default-lease-time 7200;
max-lease-time 7200;
}
Above the general configuration for the network, with a pool of 180
addresses.
Below two client reservations:
#
# laptops
#
host mac {
hardware ethernet 00:26:bb:xx:xx:xx;
fixed-address mac.netsec.local;
}
host vmac {
hardware ethernet 8c:7b:9d:xx:xx:xx;
fixed-address vmac.netsec.local;
}
Older example config files
For dhcpd.conf on Fedora with dynamic updates for a DNS domain.
[root@fedora14 ~]# cat /etc/dhcp/dhcpd.conf
authoritative;
include "/etc/rndc.key";
log-facility local6;
server-identifier fedora14;
ddns-domainname "office.linux-training.be";
ddns-update-style interim;
ddns-updates on;
update-static-leases on;
option domain-name "office.linux-training.be";
option domain-name-servers 192.168.42.100;
option ip-forwarding off;
default-lease-time 1800;
max-lease-time 3600;
zone office.linux-training.be {
primary 192.168.42.100;
}
subnet 192.168.4.0 netmask 255.255.255.0 {
range 192.168.4.24 192.168.4.40;
}
Allowing any updates in the zone database (part of the named.conf
configuration)
zone "office.linux-training.be" {
introduction to dhcp
165
type master;
file "/var/named/db.office.linux-training.be";
allow-transfer { any; };
allow-update { any; };
};
Allowing secure key updates in the zone database (part of the named.conf
configuration)
zone "office.linux-training.be" {
type master;
file "/var/named/db.office.linux-training.be";
allow-transfer { any; };
allow-update { key mykey; };
};
Sample key file contents:
[root@fedora14 ~]# cat /etc/rndc.key
key "rndc-key" {
algorithm hmac-md5;
secret "4Ykd58uIeUr3Ve6ad1qTfQ==";
};
Generate your own keys with dnssec-keygen.
How to include a key in a config file:
include "/etc/bind/rndc.key";
Also make sure that bind can write to your db.zone file (using
chmod/chown). For Ubuntu
this can be in /etc/bind, for Fedora in /var/named.
Advanced dhcp
Rule
DHCP servers should not be a single point of failure. Let us discuss
redundant dhcp server setups.
Relay agent
To avoid having to place a dhcp server on every segment, we can
use dhcp relay agents.
Rogue dhcp servers
Rogue dhcp servers are a problem without a solution. For example
accidental connection of a (believed to be simple) hub/switch to a network
with an internal dhcp server.
Dhcp and Ddns
DHCP can dynamically update DNS when it configures a client
computer. DDNS can be
used with or without secure keys.
When set up properly records can be added automaticall to the zone file:
root@fedora14~# tail -2 /var/named/db.office.linux-training.be
ubu1010srv A 192.168.42.151
TXT "00dfbb15e144a273c3cf2d6ae933885782"
Practice: dhcp
1. Make sure you have a unique fixed ip address for your DNS and DHCP
server (easier
on the same machine).
2. Install DHCP and browse the explanation in the default configuration
file /etc/dhcp/
dhcpd.conf or /etc/dhcp3/dhcpd.conf.
3. Decide on a valid scope and activate it.
4. Test with a client that your DHCP server works.
5. Use wireshark to capture the four broadcasts when a client receives an
ip (for the first
time).
6. Use wireshark to capture a DHCPNAK and a DHCPrelease.
7. Reserve a configuration for a particular client (using mac address).
8. Configure your DHCP/DNS server(s) with a proper hostname and
domainname (/etc/
hosts, /etc/hostname, /etc/sysconfig/network on Fedora/RHEL,
/etc/resolv.conf ...). You
may need to disable NetworkManager on *buntu-desktops.
9. Make sure your DNS server still works, and is master over (at least)
one domain.
There are several ways to do steps 10-11-12. Google is your friend in
exploring DDNS with
keys, with key-files or without keys.
10. Configure your DNS server to allow dynamic updates from your
DHCP server.
11. Configure your DHCP server to send dynamic updates to your DNS
server.
12
Test
the
working
of
Dynamic
DNS.
PPP in linux
Introduction
PPP (the Point to Point Protocol) is a mechanism for creating and
running IP (the Internet Protocol) and other network protocols over a
serial link − be that a direct serial connection (using a null−modem cable),
over a telnet established link, or a link made using modems and telephone
lines (and of course using digital lines such as ISDN).
Using PPP, you can connect your Linux PC to a PPP server and
access the resources of the network to which the server is connected
(almost) as if you were directly connected to that network. You can also
set up your Linux PC as a PPP server, so that other computers can dial
into your computer and access the resources on your local PC and/or
network.
As PPP is a peer−to−peer system, you can also use PPP on two
Linux PCs to link together two networks (or a local network to the
Internet), creating a Wide Area Network (WAN). One major difference
between serial based PPP and an Ethernet connection is of course speed
− a standard Ethernet connection operates at 10 Mbs (Mega − million bits
per second) or 100 Mbs maximum theoreticalthroughput, whereas an
analogue modem operates at speeds up to 56 kbps (kilo − thousand bits
per second).
Also, depending on the type of PPP connection, there may be some
limitations in usage of some applications and services.
Clients and Servers
PPP is strictly a peer to peer protocol; there is (technically) no
difference between the machine that dials in and the machine that is dialed
into. However, for clarity's sake, it is useful to think in terms of servers
and clients.
When you dial into a site to establish a PPP connection, you are a
client. The machine to which you connect is the server.When you are
setting up a Linux box to receive and handle dial−in PPP connections, you
are setting up a PPP server.
Any Linux PC can be both a PPP server and client – even
simultaneously if you have more than one serial port (and modem if
necessary). As stated above, there is no real difference between clients
and servers as far as PPP is concerned, once the connection is made.
This document refers to the machine that initiates the call (that dials
in) as the CLIENT, whilst the machine that answers the telephone, checks
the authentication of the dial in request (using user names, passwords and
possibly other mechanisms) is referred to as the SERVER.
The use of PPP as a client to link one or more machines at a location
into the Internet is, probably, the one in which most people are interested
− that is using their Linux PC as a client.
The procedure described in this document will allow you to establish
and automate your Internet connection.
This document will also give you guidance in setting up your Linux PC
as a PPP server and in linking two LANs together (with full routing) using
PPP (this is frequently characterized as establishing a WAN – wide area
network − link).
Differences between Linux distributions
There are many different Linux distributions and they all have their
own idiosyncrasies and ways of doing things.
In particular, there are two different ways a Linux (and Unix)
computer actually starts up, configures its interfaces, and so forth.
These are BSD system initialization and System V system
initialization. If you dip into some of the Unix news groups, you will find
occasional religious wars between proponents of these two systems.
Possibly the most widely used distributions are
• Slackware which uses BSD style system initialization
• Red Hat (and its former associate Caldera) which use SysV system
initialization (although in a slightly modified form)
• Debian which uses SysV system initialization BSD style
initialization typically keeps its initialization files in /etc/... and these
files are:−
/etc/rc
/etc/rc.local
/etc/rc.serial
(and possibly other files)
Of recent times, some BSD system initialization schemes use a /etc/rc.d...
directory to hold the start up file rather than putting everything into /etc.
System V initialization keeps its initialization files in directories under
/etc/... or
/etc/rc.d/... and a number of subdirectories under there:−
drwxr−xr−x 2 root root 1024 Jul 6 15:12 init.d
−rwxr−xr−x 1 root root 1776 Feb 9 05:01 rc
−rwxr−xr−x 1 root root 820 Jan 2 1996 rc.local
−rwxr−xr−x 1 root root 2567 Jul 5 20:30 rc.sysinit
drwxr−xr−x 2 root root 1024 Jul 6 15:12 rc0.d
drwxr−xr−x 2 root root 1024 Jul 6 15:12 rc1.d
Linux PPP HOWTO
Differences between Linux distributions
drwxr−xr−x 2 root root 1024 Jul 6 15:12 rc2.d
drwxr−xr−x 2 root root 1024 Jul 18 18:07 rc3.d
drwxr−xr−x 2 root root 1024 May 27 1995 rc4.d
drwxr−xr−x 2 root root 1024 Jul 6 15:12 rc5.d
drwxr−xr−x 2 root root 1024 Jul 6 15:12 rc6.d
If you are trying to track down where your Ethernet interface and
associated network routes are actually configured, you will need to track
through these files to actually find where the commands are that do this.
PPP configuration tools
There are many good tools available for configuring and using PPP on
Linux. This document will try to cover some of the more popular ones,
including:
• kppp A PPP setup and dialer tool for KDE.
• WvDial Another PPP driver for Linux, with an emphasis on
simplicity.
• RP3...(short for RedHat PPP). It is a simple configuration program
with a "wizard" interface− it asks a series of questions.
• Linuxconf A generalized tool for configuring and managing your
Linux machine, it has a section that
IP Numbers
Every device that connects to the Internet must have its own, unique
IP number. These are assigned centrally by a designated authority for each
country.
If you are connecting a local area network (LAN) to the Internet, YOU
MUST use an IP number from your own assigned network range for all
the computers and devices you have on your LAN. You MUST NOT pick
IP numbers out of the air and use these whilst connecting to another LAN
(let alone the Internet). At worst this will simply not work at all and could
cause total havoc as your 'stolen' IP number starts interfering with the
communications of another computer that is already using the IP number
you have picked out of the air. Please note that the IP numbers used
throughout this document (with some exceptions) are from the
'unconnected network numbers' series that are reserved for use by
networks that are not (ever) connected to the Internet.
There are IP numbers that are specifically dedicated to LANs that do not
connect to the Internet. The IP number sequences are:−
· One A Class Network Address 10.0.0.0 (netmask 255.0.0.0)
· 16 B Class Network Addresses 172.16.0.0 − 172.31.0.0 (netmask
255.255.0.0)
· 256 C Class Network Addresses 192.168.0.0 − 192.168.255.0 (netmask
255.255.255.0)
If you have a LAN for which you have not been allocated IP numbers by
the responsible authority in your country, you should use one of the
network numbers from the above sequences for your machines. These
numbers should neverbe used on the Internet. However, they can be used
for the local Ethernet on a machine that is connecting to the Internet. This
is because IP numbers are actually allocated to a network interface, not to
a computer. So whilst your Ethernet interface may use 10.0.0.1 (for
example), when you hook onto the Internet using PPP, your PPP interface
will
be given another (and valid) IP number by the server. Your PC will have
Internet connectivity, but the other computers on your LAN will not.
However, using Linux and the IP Masquerade (also known as NAT −
Network address Translation) capabilities of the Linux and the ipfwadm
software, you can connect your LAN to the Internet (with some restriction
of services), even if you do not have valid IP numbers for the machines
on your Ethernet.
Aims of this Document
Setting up a PPP Client
This document provides guidance to people who wish to use Linux
and PPP to dial into a PPP server and set up an IP connection using PPP.
It assumes that PPP has been compiled and installed on your Linux
machine (but does briefly coverreconfiguring/recompiling your kernel to
include PPP support).
Whilst DIP (the standard way of creating a SLIP connection) can be used
to set up a PPP connection, DIP scripts are generally quite complex. For
this reason, this document does NOT cover using DIP to set up a PPP
connection.
Instead, this document describes the standard Linux PPP software
(chat/pppd).
Linking two LANs or a LAN to the Internet using PPP
This document provides (basic) information on linking two LANs
or a LAN to the Internet using PPP.
Using intuitive configuration tools to set up PPP
There are many tools used for configuring your PPP connection.
This document will try to cover the most
common and easiest to use of said programs.
Setting up a PPP server
This document provides guidance on how to configure your Linux
PC as a PPP server (allowing other people to dial into your Linux PC
and establish a PPP connection).
You should note that there are a myriad of ways of setting up Linux
as a PPP server. This document gives one method − that used by the
author to set up several small PPP servers (each of 16 modems).
This method is known to work well. However, it is not necessarily the
best method.
Using PPP over a direct null modem connection
This document provides a brief overview of using PPP to link two
Linux PCs via a null modem cable. It is possible to link other OS's to
Linux this way as well. To do so, you will need to consult the
documentation for the operating system you are interested in.
Easy Configuration Utilities for PPP
KPPP − The KDE PPP Dialer
KPPP is an easy tool for configuring your PPP links. It comes with
the default installation of KDE, and is quite well integrated into that
environment.
KPPP also has a good help system built in. If you just right click on
the majority of the buttons in the application, a menu will pop up with an
item called "Quickhelp". Clicking it will give a quick summary of
whatever item you clicked on.
The opening screen of kppp will list any available connections, and allow
you to specify a Login ID and password for the connection. There is also
a "Show Log Window" option. Selecting this will show a log window.
This can be handy if you are trying to debug a connection.
Overview of what has to be done to get PPP working as a client
This document contains a great deal of information − and with each
version it grows! As a consequence, this section aims to provide a concise
overview of the actions you will need to take to get your Linux system
connected as a client to a PPP server the sysadmin/user support people of
the PPP server).
Using K development environment
Installing KDE Plasma Desktop and KDE Applications
You can install KDE applications, including KDE Plasma Desktop,
on a variety of different platforms, ranging from smartphones and tablets
to computers running Microsoft®Windows®, Mac®OS, UNIX®, BSD™
or Linux®. Binary packages are available for many different platforms
and distributions, or advanced users may build the source code.
Installing Packages
Hundreds of developers worldwide have done a lot of work to make
it easy to install KDE on a variety of different devices and platforms.
Linux
Nearly every Linux® distribution provides binary packages for
individual applications and the KDE Plasma Desktop as a whole.To install
an individual application, look for its name in your distribution’s package
collection. To install one of the KDE PlasmaWorkspaces, like KDE
Plasma Desktop, look for a metapackage or package group, typically
plasma-desktop.
NOTE
Some applications may be installed together with other applications
in a combined package named after the KDE package they are provided
in. For instance, Konqueror might be found in the kde-base apps package.
If you have trouble locating KDE packages for your distribution,
please contact their support resources. Many distributions also have a
team dedicated to packaging applications by KDE that can provide
assistance specific to them.
Microsoft Windows
The KDE on Windows Initiative provides binary packages of KDE
applications for Microsoft Windows. They also provide a special installer
application that permits you to install individual applications or groups
and all necessary dependencies easily.
Mac®OS
Individual KDE applications can be installed through several
different ‘ports’ systems available for Mac® OS. Several different KDE
applications also provide their own binary builds for Mac® OS.
BSD™
Most BSD™ distributions allows you to install KDE applications
and the KDE Plasma Desktop through their ‘ports’ system. For more
information on installing ports, see your BSD™ distribution’s
documentation.
Mobile Devices
Plasma Mobile is an exciting initiative to bring a new KDE
experience to mobile devices like smartphones or tablets. Binary releases
are provided for several different devices. For more information, visit
Plasma Mobile.
Live Media
Several Linux® and BSD™ distributions offer live media. This
permits you to try out the KDE Plasma Desktop without installing
anything to your system. All you have to do insert a CD or connect a USB
drive and boot from it. If you like what you see, most offer an option to
install it to your hard drive.
Building from Source Code
For detailed information on how to compile and install KDE Plasma
Desktop and applications see Build from source. Since KDE software uses
cmake you should have no trouble compiling it. Should you run into
problems please report them to the KDE mailing lists.
The recommended tool to build Frameworks, KDE Plasma Desktop and
all the other applications is kdesrc-build
Visual Dictionary
The KDE Plasma Workspaces feature many different graphical user
interface elements, commonly known as ‘widgets’. This guide will
introduce you to their names and functions.
Windows
This is the window of the KWrite, a text editor. Click on part of the
window to learn more about it.
1. TheWindow Menu
2. The Titlebar
KDE Fundamentals
3. Buttons to minimize, maximize, or close the window
4. The Menubar
5. The Toolbar
6. A very large Text Area that acts as this program’s Central Widget
7. A vertical Scrollbar (there is also a horizontal scrollbar below the text
box)
8. The Statusbar
This is the another window, that of the Dolphin file manager. Click on
part of the window to learn more about it.
1. A panel that contains a list of Places on the computer system
2. A Breadcrumb of the path of the displayed folder
3. A folder Icon
4. A file Icon
5. A highlighted Icon
6. A Context Menu listing actions that can be performed on a file
7. A Slider that changes the size of the Icons displayed
8. More Panels
9 KDE Fundamentals
GUI Elements
This screenshot, from the System Settings Formats panel, shows some
GUI elements. Click on
part of the window to learn more about it.
1. An Icon List (the second item is selected)
2. An open Drop Down Box
3. An item in the Drop Down Box that has been selected
4. Some more Buttons
KDE Fundamentals
This screenshot, from the System Settings Custom Shortcuts panel, shows
some more GUI elements.
1. A Tree View
2. A Check Box that has been selected
3. A pair of Spin Boxes
4. A Menu Button
This screenshot, from the System Settings Default Applications panel,
shows even more GUI
elements. Click on part of the window to learn more about it.
1. A List Box
2. A pair of Radio Buttons
3. A Text Box
This screenshot, from the System Settings Formats panel, shows some
GUI elements. Click on part of the window to learn more about it.
1. An Icon List (the second item is selected)
2. An open Drop Down Box
3. An item in the Drop Down Box that has been selected
4. Some more Buttons
The Widgets
The File Menu
The File menu allows you to perform operations on the currently
open file and access common tasks in applications.
Common menu items include:
File!New (Ctrl+N)
Creates a new file.
File!New Window
Opens a new window.
File!Open... (Ctrl+O)
Opens an already existing file.
File!Save (Ctrl+S)
Saves the file. If the file already exists it will be overwritten.
File!Save As...
Saves the file with a new filename.
File!Save All
Saves all open files.
File!Reload (F5)
Reloads the current file.
File!Reload All
Reloads all open files.
File!Print... (Ctrl+P)
Prints the file.
File!Close (Ctrl+W)
Closes the current file.
File!Close All
Closes all open files.
File!Quit (Ctrl+Q)
Exits the program.
The Edit Menu
The Edit menu allows
Edit!Undo (Ctrl+Z)
Undo the last action you performed in the file.
Edit!Redo (Ctrl+Shift+Z)
Redo the last action you performed in the file.
KDE Fundamentals
Edit!Cut (Ctrl+X)
Removes the currently selected portion of the file, if any, and places a
copy of it in the clipboard buffer.
Edit!Copy (Ctrl+C)
Places a copy of the currently selected portion of the file, if any, in the
clipboard buffer.
Edit!Paste (Ctrl+V)
Copies the first item in the clipboard buffer to the current location in the
file, if any.
Edit!Select All (Ctrl+A)
Selects the entire contents of the currently open file.
Edit!Find... (Ctrl+F)
Allows you to search for text in the currently open file.
Edit!Replace... (Ctrl+R)
Allows you to search for text in the currently open file and replace it with
something else.
Edit!Find Next (F3)
Go to the next match of the last Find operation.
Edit!Find Previous (Shift+F3)
Go to the previous match of the last Find operation.
The View Menu
The View menu allows you to change the layout of the currently open file
and/or the running
application.
This menu has different options depending on the application you are
using.
The Tools Menu
The Tools menu allows you to perform certain actions on the
currently open file.
Tools!Automatic Spell Checking (Ctrl+Shift+O)
Tools!Spelling...
This initiates the spellchecking program - a program designed to help the
user catch and
correct any spelling errors. For more information, see Section 4.3.1.
Tools!Spelling (from cursor)...
This initiates the spellchecking program, but only checks the portion of
the document from
the current location of the cursor to the end.
Tools!Spellcheck Selection...
This initiates the spellchecking program, but only checks the currently
selected text in thedocument.
Tools!Change Dictionary...
This allows you to change the dictionary used to check spellings.
The Settings Menu
The Settings allows you to customize the application.
This menu typically contains the following items:
Settings!Show Menubar (Ctrl+M)
Hides and shows the menubar.
Settings!Show Statusbar
Toggles the display of the statusbar on and off. Some KDE applications
use statusbar at the
bottom of their screen to display useful information.
Settings!Toolbars Shown
Allows you to show and hide the various toolbars supported by the
application.
Settings!Show Statusbar
When checked, this displays a small bar at the bottom of the application
containing information about the status. When unchecked the status bar is
hidden.
Settings!Configure Shortcuts...
Allows you to enable, disable, and modify keyboard shortcuts.
Settings!Configure Toolbars...
Allows you to customize the contents, layout, text, and icons of toolbars.
.
Settings!Configure Notifications.
This item displays a standard KDE notifications configuration
dialog, where you can change the notifications (sounds, visible messages,
etc.) used by the application.
For more information how to configure notifications please read the
documentation for the System Settings module Manage Notifications.
Settings!Configure Application...
Opens the configuration panel for the currently running application
The Help Menu
The Help menu gives you access to the application’s documentation
and other useful resources.
Help!Application Handbook (F1)
Invokes the KDE Help system starting at the running application’s
handbook.
Help!What’s This? (Shift+F1)
Changes the mouse cursor to a combination arrow and question mark.
Clicking on items
Within the application; will open a help window (if one exists for the
particular item) explaining the item’s function.
Help!Report Bug...
Opens the Bug report dialog where you can report a bug or request a
‘wishlist’ feature.
Help!Switch Application Language...
Opens a dialog where you can edit the Primary language and Fallback
language for this Application
Help!About Application
This will display version and author information for the running
application.
Help!About KDE
This displays the KDE Development Platform version and other basic
information
Common Tasks
Navigating Documents
Scrolling
You’re probably familiar with the scrollbar that appears on the right side
(and sometimes the bottom) of documents, allowing you to move within
documents. However, there are several other ways you can navigate
documents, some of which are faster and easier.
Several mice have a wheel in the middle. You can move it up and down
to scroll within a document. If you press the Shift key while using the
mouse wheel, the document will scroll faster. If you’re using a portable
computer like a laptop, you might also be able to scroll using the
touchpad. Some computers allow you to scroll vertically by moving your
finger up and down the rightmost side of the touchpad, and allow you to
scroll horizontally by moving your finger across the bottommost side of
the touchpad. Others let you scroll using two fingers: move both fingers
up and down anywhere on the touchpad to scroll vertically, and move
them left and right to scroll horizontally. Since this functionality emulates
the mouse wheel functionality described above, you can also press the
Shift key while you do this to scroll faster. If you use the KDE Plasma
Workspaces, you can control mouse wheel behavior in the Mousemodule
in System Settings, and you can control touchpad scrolling behavior in the
Touchpad module in System Settings. Otherwise, look in the
configuration area of your operating system or desktop environment.
Additionally, the scrollbar has several options in its context menu. You
can access these by right clicking anywhere on the scrollbar. The
following options are available:
Scroll here
Scroll directly to the location represented by where you rightclicked on the scrollbar. This is the equivalent of simply clicking on that
location on the scrollbar.
Top (Ctrl+Home)
Go to the beginning of the document.
Bottom (Ctrl+End)
Go to the end of the document.
Page up (PgUp)
Navigate to the previous page in a document that represents a printed
document, or one screen up in other types of documents.
Page down (PgDn)
Navigate to the next page in a document that represents a printed
document, or one screen
down in other types of documents.
Scroll up
Scroll up one unit (usually a line) in the document. This is the equivalent
of clicking the up
arrow at the top of the scrollbar.
Scroll down
Scroll down one unit (usually a line) in the document. This is the
equivalent
Zooming
Many applications permit you to zoom. This makes the text or image you
are viewing larger or smaller. You can generally find the zoom function
in the View menu, and sometimes in the status bar of the application.
You can also zoom using the keyboard by pressing Ctrl++ to zoom in, or
Ctrl+- to zoom out.
Opening and Saving Files
Introduction
Many KDE applications work with files. Most applications have a
File menu with options that allow you to open and save files.
However, there are lots of different operations that require selecting
a file. Regardless of the method, all KDE applications generally use the
same file selection window.
The File Selection Window
The Toolbar
This contains standard navigation tool buttons:
Back
Causes the folder view to change to the previously displayed folder in its
history. This button is disabled, if there is no previous item.
Forward
Causes the folder view to change to the next folder in its history. This
button is disabled, if there is no next folder.
Parent Folder
This will cause the folder view to change to the immediate parent of the
currently displayed folder, if possible.
Reload (F5)
Reloads the folder view, displaying any changes that have been made
since it was first loaded or last reloaded.
Show Preview
Displays a preview of each file inside the folder view.
Zoom Slider
This allows you to change the size of the icon or preview shown in the
folder view.
Options
Options!Sorting
Options!Sorting!By Name
Sort files listed in the folder view alphabetically by name.
Options!Sorting!By Size
Sort files listed in the folder view in order of their file size.
Options!Sorting!By Date
Sort files listed in the folder view by the date they were last modified.
Options!Sorting!By Type
Sort files listed in the folder view alphabetically by their file type.
Options!Sorting!Descending
When unchecked (the default), files in the folder view will be sorted in
ascending order. (For instance, files sorted alphabetically will be sorted
from A to Z, while files sorted numerically will be sorted from smallest
to largest.) When checked, files in the folder will be sorted in descending
order (in reverse).
Options!Sorting!Folders First
When enabled (the default), folders will appear before regular files.
Security
user management
useradd, usermod and userdel to create, modify and remove user
accounts.
user management
User management on Linux can be done in three complementary
ways. You can use the graphical tools provided by your distribution.
These tools have a look and feel that depends on the distribution. If you
are a novice Linux user on your home system, then use the graphical tool
that is provided by your distribution. This will make sure that you do not
run into problems.
Another option is to use command line tools like useradd, usermod,
gpasswd, passwd and others. Server administrators are likely to use these
tools, since they are familiar and very similar across many different
distributions. This chapter will focus on these command line tools.
A third and rather extremist way is to edit the local configuration files
directly using vi (or vipw/vigr). Do not attempt this as a novice on
production systems!
/etc/passwd
The local user database on Linux (and on most Unixes) is /etc/passwd.
[root@RHEL5 ~]# tail /etc/passwd
inge:x:518:524:art dealer:/home/inge:/bin/ksh
ann:x:519:525:flute player:/home/ann:/bin/bash
frederik:x:520:526:rubius poet:/home/frederik:/bin/bash
steven:x:521:527:roman emperor:/home/steven:/bin/bash
pascale:x:522:528:artist:/home/pascale:/bin/ksh
geert:x:524:530:kernel developer:/home/geert:/bin/bash
wim:x:525:531:master damuti:/home/wim:/bin/bash
sandra:x:526:532:radish stresser:/home/sandra:/bin/bash
annelies:x:527:533:sword fighter:/home/annelies:/bin/bash
laura:x:528:534:art dealer:/home/laura:/bin/ksh
As you can see, this file contains seven columns separated by a colon. The
columns contain the username, an x, the user id, the primary group id, a
description, the name of the home directory, and the login shell.
More information can be found by typing man 5 passwd.
[root@RHEL5 ~]# man 5 passwd
Root
The root user also called the superuser is the most powerful
account on your Linux system. This user can do almost anything,
including the creation of other users. The root user always has userid 0
(regardless of the name of the account).
[root@RHEL5 ~]# head -1 /etc/passwd
root:x:0:0:root:/root:/bin/bash
useradd
You can add users with the useradd command. The example below
shows how to add a user named yanina (last parameter) and at the same
time forcing the creation of the home directory (-m), setting the name of
the home directory (-d), and setting a description (-c).
[root@RHEL5 ~]# useradd -m -d /home/yanina -c "yanina
wickmayer" yanina
[root@RHEL5 ~]# tail -1 /etc/passwd
yanina:x:529:529:yanina wickmayer:/home/yanina:/bin/bash
The user named yanina received userid 529 and primary group id
/etc/default/useradd
Both Red Hat Enterprise Linux and Debian/Ubuntu have a file called
/etc/default/useradd that contains some default user options. Besides
using cat to display this file, you can alsouse useradd -D.
[root@RHEL4 ~]# useradd -D
GROUP=100
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/bash
SKEL=/etc/skel
userdel
You can delete the user yanina with userdel. The -r option of userdel
will also remove the home directory.
[root@RHEL5 ~]# userdel -r yanina
usermod
You can modify the properties of a user with the usermod
command. This example uses
usermodto change the description of the user harry.
[root@RHEL4 ~]# tail -1 /etc/passwd
harry:x:516:520:harry potter:/home/harry:/bin/bash
[root@RHEL4 ~]# usermod -c 'wizard' harry
[root@RHEL4 ~]# tail -1 /etc/passwd
harry:x:516:520:wizard:/home/harry:/bin/bash
Creating home directories
The easiest way to create a home directory is to supply the -m option
with useradd (it is likely set as a default option on Linux).
A less easy way is to create a home directory manually with mkdir which
also requires setting the owner and the permissions on the directory with
chmod and chown.
[root@RHEL5 ~]# mkdir /home/laura
[root@RHEL5 ~]# chown laura:laura /home/laura
[root@RHEL5 ~]# chmod 700 /home/laura
[root@RHEL5 ~]# ls -ld /home/laura/
drwx------ 2 laura laura 4096 Jun 24 15:17 /home/laura/
/etc/skel/
When using useradd the -m option, the /etc/skel/ directory is copied to
the newly created home directory. The /etc/skel/ directory contains some
(usually hidden) files that contain profile settings and default values for
applications. In this way /etc/skel/ serves as a default home directory and
as a default user profile.
[root@RHEL5 ~]# ls -la /etc/skel/
total 48
drwxr-xr-x 2 root root 4096 Apr 1 00:11 .
drwxr-xr-x 97 root root 12288 Jun 24 15:36 ..
-rw-r--r-- 1 root root 24 Jul 12 2006 .bash_logout
-rw-r--r-- 1 root root 176 Jul 12 2006 .bash_profile
-rw-r--r-- 1 root root 124 Jul 12 2006 .bashrc
Deleting home directories
The -r option of userdel will make sure that the home directory is deleted
together with the user account.
[root@RHEL5 ~]# ls -ld /home/wim/
drwx------ 2 wim wim 4096 Jun 24 15:19 /home/wim/
[root@RHEL5 ~]# userdel -r wim
[root@RHEL5 ~]# ls -ld /home/wim/
ls: /home/wim/: No such file or directory
login shell
The /etc/passwd file specifies the login shell for the user. In the
screenshot below you can see that user annelies will log in with the
/bin/bash shell, and user laura with the /bin/ksh shell.
[root@RHEL5 ~]# tail -2 /etc/passwd
annelies:x:527:533:sword fighter:/home/annelies:/bin/bash
laura:x:528:534:art dealer:/home/laura:/bin/ksh
You can use the usermod command to change the shell for a user.
[root@RHEL5 ~]# usermod -s /bin/bash laura
[root@RHEL5 ~]# tail -1 /etc/passwd
laura:x:528:534:art dealer:/home/laura:/bin/bash
chsh
Users can change their login shell with the chsh command. First,
user harry obtains a list of available shells (he could also have done a cat
/etc/shells) and then changes his login shell to the Korn shell (/bin/ksh).
At the next login, harry will default into ksh instead of bash.
[laura@centos7 ~]$ chsh -l
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/ksh
/bin/tcsh
/bin/csh
[laura@centos7 ~]$
Note that the -l option does not exist on Debian and that the above
screenshot assumes that ksh and csh shells are installed.
The screenshot below shows how lauracan change her default shell
(active on next login).
[laura@centos7 ~]$ chsh -s /bin/ksh
Changing shell for laura.
Password:
Shell changed.
user passwords
passwords for local users. Three methods for setting passwords are
explained; using the passwd command, using openssel passwd, and using
the crypt function in a C program.
password settings and disabling, suspending or locking accounts.
passwd
Passwords of users can be set with the passwd command. Users will
have to provide their old password before twice entering the new one.
[tania@centos7 ~]$ passwd
Changing password for user tania.
Changing password for tania.
(current) UNIX password:
New password:
BAD PASSWORD: The password is shorter than 8 characters
New password:
BAD PASSWORD: The password is a palindrome
New password:
BAD PASSWORD: The password is too similar to the old one passwd:
Have exhausted maximum number of retries for service
As you can see, the passwd tool will do some basic verification to prevent
users from using
too simple passwords. The root user does not have to follow these rules
(there will be
a warning though). The root user also does not have to provide the old
password before
entering the new password twice.
root@debian7:~# passwd tania
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
encryption with passwd
Passwords are stored in an encrypted format. This encryption is
done by the crypt function. The easiest (and recommended) way to add a
user with a password to the system is to add the user with the useradd m user command, and then set the user's password with passwd.
[root@RHEL4 ~]# useradd -m xavier
[root@RHEL4 ~]# passwd xavier
Changing password for user xavier.
New UNIX password:
Retype new UNIX password:
passwd: all authentication tokens updated successfully.
[root@RHEL4 ~]#
Encryption with openssl
Another way to create users with a password is to use the -p option
of useradd, but that option requires an encrypted password. You can
generate this encrypted password with the openssl passwd command.
The openssl passwd command will generate several distinct hashes for
the same password,for this it uses a salt.
paul@rhel65:~$ openssl passwd hunter2
86jcUNlnGDFpY
paul@rhel65:~$ openssl passwd hunter2
Yj7mDO9OAnvq6
paul@rhel65:~$ openssl passwd hunter2
YqDcJeGoDbzKA
paul@rhel65:~$
This salt can be chosen and is visible as the first two characters of the
hash.
paul@rhel65:~$ openssl passwd -salt 42 hunter2
42ZrbtP1Ze8G.
paul@rhel65:~$ openssl passwd -salt 42 hunter2
42ZrbtP1Ze8G.
paul@rhel65:~$ openssl passwd -salt 42 hunter2
42ZrbtP1Ze8G.
paul@rhel65:~$
This example shows how to create a user with password.
root@rhel65:~# useradd -m -p $(openssl passwd hunter2) mohamed
Disabling a password
Passwords in /etc/shadow cannot begin with an exclamation mark.
When the second field in /etc/passwd starts with an exclamation mark,
then the password can not be used.
Using this feature is often called locking, disabling, or suspending
a user account. Besides vi(or vipw) you can also accomplish this with
usermod.
The first command in the next screenshot will show the hashed
password of laurain /etc/ shadow. The next command disables the
password of laura, making it impossible for Laurato authenticate using
this password.
root@debian7:~# grep laura /etc/shadow | cut -c1-70
laura:$6$JYj4JZqp$stwwWACp3OtE1R2aZuE87j.nbW.puDkNUYVk7
mCHfCVMa3CoDUJV
root@debian7:~# usermod -L laura
As you can see below, the password hash is simply preceded with an
exclamation mark.
root@debian7:~# grep laura /etc/shadow | cut -c1-70
laura:!$6$JYj4JZqp$stwwWACp3OtE1R2aZuE87j.nbW.puDkNUYVk7
mCHfCVMa3CoDUJ
root@debian7:~#
The root user (and users with sudo rights on su) still will be able to
su into the lauraaccount (because the password is not needed here). Also
note that laurawill still be able to login
if she has set up passwordless ssh!
root@debian7:~# su - laura
laura@debian7:~$
You can unlock the account again with usermod -U.
root@debian7:~# usermod -U laura
root@debian7:~# grep laura /etc/shadow | cut -c1-70
laura:$6$JYj4JZqp$stwwWACp3OtE1R2aZuE87j.nbW.puDkNUYVk7
mCHfCVMa3CoDUJV
Watch out for tiny differences in the command line options of passwd,
usermod, and useradd on different Linux distributions. Verify the local
files when using features like "disabling, suspending, or locking" on
user accounts and their passwords
user profiles
Logged on users have a number of preset (and customized) aliases,
variables, and functions, but where do they come from ? The shell uses a
number of startup files that are execute (or rather sourced) whenever the
shell is invoked. What follows is an overview of startup scripts.
System profile
Both the bash and the ksh shell will verify the existence of
/etc/profile and source it if it exists. When reading this script, you will
notice (both on Debian and on Red Hat Enterprise Linux) that it builds the
PATH environment variable (among others). The script might also change
the PS1 variable, set the HOSTNAME and execute even more scripts like
/etc/inputrc This screenshot uses grep to show PATH manipulation in
/etc/profile on Debian.
root@debian7:~# grep PATH /etc/profile
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
export PATH
root@debian7:~#
This screenshot uses grep to show PATH manipulation in /etc/profile on
RHEL7/CentOS7.
[root@centos7 ~]# grep PATH /etc/profile
case ":${PATH}:" in
PATH=$PATH:$1
PATH=$1:$PATH
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE
HISTCONTROL
[root@centos7 ~]#
The root user can use this script to set aliases, functions, and variables
for every user on the system.
~/.bash_profile
When this file exists in the home directory, then bash will source it.
On Debian Linux 5/6/7 this file does not exist by default.
RHEL7/CentOS7 uses a small
~/.bash_profile where it checks for the existence of
~/.bashrc and then sources it. It also adds $HOME/bin to the $PATH
variable.
[root@rhel7 ~]# cat /home/paul/.bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/.local/bin:$HOME/bin
export PATH
[root@rhel7 ~]#
~/.bash_login
When .bash_profile does not exist, then bash will check for
~/.bash_login and source it.
Neither Debian nor Red Hat have this file by default.
~/.profile
When neither ~/.bash_profile and~/.bash_login exist, then bash will
verify the existence of ~/.profile and execute it. This file does not exist
by default on Red Hat.
On Debian this script can execute ~/.bashrc and will add $HOME/bin to
the $PATH variable.
root@debian7:~# tail -11 /home/paul/.profile
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
RHEL/CentOS does not have this file by default.
~/.bashrc
The ~/.bashrc script is often sourced by other scripts. Let us take a
look at what it does by default.
Red Hat uses a very simple ~/.bashrc, checking for /etc/bashrc and
sourcing it. It also leavesroom for custom aliases and functions.
[root@rhel7 ~]# cat /home/paul/.bashrc
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# Uncomment the following line if you don't like systemctl's auto paging
feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
On Debian this script is quite a bit longer and configures $PS1, some
history variables and a number af active and inactive aliases.
root@debian7:~# wc -l /home/paul/.bashrc
110 /home/paul/.bashrc
~/.bash_logout
When exiting bash, it can execute ~/.bash_logout. Debian use this
opportunity to clear the console screen.
serena@deb503:~$ cat .bash_logout
# ~/.bash_logout: executed by bash(1) when login shell exits.
# when leaving the console clear the screen to increase privacy
if [ "$SHLVL" = 1 ]; then
[ -x /usr/bin/clear_console ] && /usr/bin/clear_console -qfi
Red Hat Enterprise Linux 5 will simple call the /usr/bin/clear command
in this script.
[serena@rhel53 ~]$ cat .bash_logout
# ~/.bash_logout
/usr/bin/clear
Red Hat Enterprise Linux 6 and 7 create this file, but leave it empty
(except for a comment).
paul@rhel65:~$ cat .bash_logout
# ~/.bash_logout
File security
file ownership
user owner and group owner
The users and groups of a system can be locally managed in /etc/passwd
and /etc/group, or they can be in a NIS, LDAP, or Samba domain. These
users and groups can own files.
Actually, every file has a user owner and a group owner, as can be seen
in the following
screenshot.
paul@rhel65:~/owners$ ls -lh
total 636K
-rw-r--r--. 1 paul snooker 1.1K Apr 8 18:47 data.odt
-rw-r--r--. 1 paul paul 626K Apr 8 18:46 file1
-rw-r--r--. 1 root tennis 185 Apr 8 18:46 file2
-rw-rw-r--. 1 root root 0 Apr 8 18:47 stuff.txt
paul@rhel65:~/owners$
User paul owns three files; file1 has paul as user owner and has the group
paul as group owner, data.odt is group owned by the group snooker,
file2 by the group tennis.
The last file is called stuff.txt and is owned by the root user and the root
group.
chgrp
You can change the group owner of a file using the chgrp command.
root@rhel65:/home/paul/owners# ls -l file2
-rw-r--r--. 1 root tennis 185 Apr 8 18:46 file2
root@rhel65:/home/paul/owners# chgrp snooker file2
root@rhel65:/home/paul/owners# ls -l file2
-rw-r--r--. 1 root snooker 185 Apr 8 18:46 file2
root@rhel65:/home/paul/owners#
chown
The user owner of a file can be changed with chown command.
root@laika
:/home/paul# ls -l FileForPaul
-rw-r--r-- 1 root paul 0 2008-08-06 14:11 FileForPaul
root@laika:/home/paul# chown paul FileForPaul
root@laika:/home/paul# ls -l FileForPaul
-rw-r--r-- 1 paul paul 0 2008-08-06 14:11 FileForPaul
You can also use chown to change both the user owner and the group
owner.
root@laika:/home/paul# ls -l FileForPaul
-rw-r--r-- 1 paul paul 0 2008-08-06 14:11 FileForPaul
root@laika:/home/paul# chown root:project42 FileForPaul
root@laika:/home/paul# ls -l FileForPaul
-rw-r--r-- 1 root project42 0 2008-08-06 14:11 FileForPaul
list of special files
When you use ls -l, for each file you can see ten characters before
the user and group owner. The first character tells us the type of file.
Regular files get a -, directories get a d, symbolic links are shown with an
l, pipes get a p, character devices a c, block devices a b, and sockets an s.
Unix special files first character file type
- normal file
d directory
l symbolic link
p named pipe
b block device
c character device
s socket
IP Masquerading
IP Masquerade is a networking function in Linux similar to the
one−to−many (Many) NAT (NetworkAddress Translation) servers found
in many commercial firewalls and network routers. For example, if
aLinux host is connected to the Internet via PPP, Ethernet, etc., the IP
Masquerade feature allows other "internal" computers connected to this
Linux box (via PPP, Ethernet, etc.) to also reach the Internet as well.
Linux IP Masquerading allows for this functionality even though these
internal machines don't have an officially assigned IP address.
MASQ allows a set of machines to invisibly access the Internet via the
MASQ gateway. To other machines on the Internet, the outgoing traffic
will appear to be from the IP MASQ Linux server itself. In addition to the
added functionality, IP Masquerade provides the foundation to create a
HEAVILY secured networking environment. With a well-built firewall,
breaking the security of a well configured masquerading system and
internal LAN should be considerably difficult to accomplish
Benefit From IP Masquerade
• If you have a Linux host connected to the Internet and.. if you have
internal computers running TCP/IP connected that are connected to
this Linux box via on a network, and/or
• if your Linux host has more than one modem and acts as a PPP or
SLIP server connected to other computers, and these machines do
not have official or public assigned IP addresses (i.e. addressedwith
private TCP/IP numbers).
• If you want those OTHER machines to communicate to the Internet
without spending extra money to acquire additional Public / Official
TCP/IP addresses from your ISP, then you should either configure
Linux to be a router or purchase an external router.
Need IP Masquerade
• If your machine is a stand−alone Linux host connected to the
Internet (setting up a firewall is a good idea though), or
• If you already have multiple assigned public addresses for your
OTHER machines, and if you don't like the idea of a 'free ride' using
Linux and feel more comfortable using expensivecommercial tools
to perform the exact same functionalities.
In the above drawing, a Linux box with IP_MASQUERADING is
installed as Linux #1 and is connected to the Internet via PPP, Ethernet,
etc. It has an assigned public IP address of 111.222.121.212. It also has
another network interface (e.g. modem2) connected to allow incoming
network traffic be it from a PPP connection,
The second system (which does not need to be Linux) connects into the
Linux #1 box and starts its network traffic to the Internet. This second
machine does NOT have a publicly assigned IP address from the Internet,
so it uses an RFC1918 private address, say 192.168.0.100. (see below for
more info) With IP Masquerade and the routing configured properly, this
second machine "Anybox" can interact with the Internet as if it was
directly connected to the Internet with a few small exceptions [noted
later].
Quoting Pauline Middelink (the founder of Linux's IPMASQ): "Do not
forget to mention that the "ANYBOX" machine should have the Linux #1
box configured as its default gateway (whether it be the default route or
just a subnet is no matter). If the "ANYBOX" machine is connected via a
PPP or SLIP connection, the Linux #1 machine should be configured to
support proxy arp for all routed addresses. But, the setup and
configuration of proxy arp is beyond the scope of this document.
This short text is based from a previous post on comp.os.linux.networking
which has been edited to match the names used in the above example\
Another IP Masquerading Example:
A typical example is given in the diagram below:
In this example, there are (4) computer systems that we are concerned
about. There is also presumably something on the far right that your
PPP/ETH connection to the Internet comes through (modem server, DSL
DSLAM, Cablemodem router, etc.). Out on the Internet, there exists some
remote host (very far off to the right of the page) that you are interested
in communicating with). The Linux system named Masq−Gate is the IP
Masquerading gateway for ALL internal networked machines. In this
example, the machines A−box, B−box, and C−box would have to go
through the Masq−Gate to reach the Internet. The internal network uses
one of several RFC−1918 assigned private network addresses, where in
this case, would be the Class−Cnetwork 192.168.0.0. If you aren't familiar
with RFC1918, it is encouraged to read the first few chapters of the RFC
but the jist of it is that the TCP/IP addresses 10.0.0.0/8, 172.16−31.0.0/12,
and 192.168.0.0/16 are reserved. When we say "reserved", we mean that
anyone can use these addresses as long as they aren't routed over the
Internet. ISPs are even allowed to use this private addressing space as long
as they keep these addresses within their own networks and NOT
advertise them to other ISPs. Unfortunately, this isn't always the case but
that’s beyond the scope of this HOWTO.
Anyway, the Linux box in the diagram above has the TCP/IP address
192.168.0.1 while the other systems has
the addresses:
· A−Box: 192.168.0.2
· B−Box: 192.168.0.3
· C−Box: 192.168.0.4
The three machines, A−box, B−box and C−box, can have any one of
several operating systems, just as long as they can speak TCP/IP. Some
such as Windows 95, Macintosh MacTCP or OpenTransport, or even
another Linux box have the ability to connect to other machines on the
Internet. When running the IP Masquerade, the masquerading system or
MASQ−gate converts all of these internal connections so that they appear
to originate from the masq−gate itself. MASQ then arranges so that the
data coming back to a masqueraded connection is relayed to the proper
originating system. Therefore, the systems on the internal network are
only able to see a direct route to the internet and are unaware that their
data is being masqueraded. This is called a "Transparent" connection.
Requirements for IP Masquerade on Linux 2.4.x
Kernels are now using both a completely new TCP/IP network stack
as well as a new NAT sub−system called NetFilter. Within this NetFilter
suite of tools, we now have a tool called IPTABLES for the 2.4.x kernels
much like there was IPCHAINS for the 2.2.x kernels and IPFWADM for
the 2.0.x kernels. The new IPTABLES system is far more powerful
(combines several functions into one place like true NAT functionality),
offers better security (stateful inspection), and better performance with the
new 2.4.x TCP/IP stack. But this new suite of tools can be a bit
complicated in comparison to older generation kernels. Hopefully, if you
follow along with this HOWTO carefully, setting up IPMASQ won't be
too bad. If you find anything unclear, downright wrong, etc. please email
David about it.
Unlike the migration to IPCHAINS from IPFWADM, the new NetFilter
tool has kernel modules that can actually support older IPCHAINS and
IPFWADM rulesets with minimal changes. So re−writing your old
MASQ or firewall ruleset scripts is no longer required. BUT..with the
2.4.x kernels, you cannot use the old 2.2.x MASQ modules like
ip_masq_ftp, ip_masq_irc, etc. AND IPCHAINS is incompatible with the
new IPTABLES modules like ip_conntrack_ftp, etc. So, what does this
mean? It basically means that if you want to use IPMASQ or PORTFW
functionality under a 2.4.x kernel, you shouldn't use IPCHAINS rules but
IPTABLES ones instead. Please also keep in mind that there might be
several benefits in performing a full ruleset re−write to take advantage of
the newer IPTABLES features like stateful tracking, etc. but that is
dependant upon how much time you have to migrate your old rulesets.
PROs:
• Lots of new protocols modules like: amanda, eggdrop, ipsec, ipv6,
portscan, pptp, quota, rsh, talk, and tftp
• TRUE 1:1 NAT functionality for those who have TCP/IP addresses
and subnets to use (no more iproute2 commands)
• Stateful application level (FTP, IRC, etc.) and stateful protocol level
(TCP/UDP/ICMP) network traffic inspection
• Built−in PORT Forwarding (no more ipmasqadm or ipportfw
commands) The built−in PORTFW'ing support works for both
external and internal traffic. This means that users that have
PORTFW for external traffic and REDIR for internal port
redirection do not need to use two tools any more!
• PORT Forwarding of FTP traffic to internal hosts is now completely
supported and is handled in the conn_trak_ftp module
• Full Policy−Based routing features (source−based TCP/IP address
routing)
•
• Compatibility with Linux's FastRoute feature for significantly faster
packet forwarding (a.k.a Linux network switching).
• Note that this feature is still not compatible with packet filtering for
strong firewall rulesets.
• Fully supports TCP/IP v4, v6, and even DECnet (ack!)
• Supports wildcard interface names like "ppp*" for serial interfaces
like ppp0, ppp1, etc
• Supports filtering on both input and output INTERFACES (not just
IP addresses)
• Source Ethernet MAC filtering
• Denial of Service (DoS) packet rate limiting
• Packet REJECTs now have user−selectable return ICMP messages
• Variable levels of logging (different packets can go to different
SYSLOG levels)
• Other features like traffic mirroring, securing traffic per login, etc.
Netfilter is an entirely new architecture thus most of the older 2.2.x
MASQ kernel modules written to make non−NAT friendly network
applications work through IPMASQ need to be re−written for the 2.4.x
kernels. Because of this, if you specifically need functionality from some
of these modules, you should stay with a 2.2.x kernel until these modules
have been either ported or the application has been updated to use
NAT−friendly protocols. If you are curious on the porting status of a given
module, please email the author of the module and NOT David or
Ambrose. We don't code..we just document.
Here is the status of the known IP Masq kernel modules or patches as
found on the IPMASQ WWW site's Application Support Matrix. In
addition, you should also setup out the Netfilter Patch−o−Matic URL as
well. If you have the time and knowledge to help in the porting of code,
your efforts would behighly appreciated:
UNIT III
C++ ARRAYS
C++ provides a data structure, the array, which stores a fixed-size
sequential collection of elements of the same type. An array is used to store a
collection of data, but it is often more useful to think of an array as a
collection of variables of the same type.
Instead of declaring individual variables, such as number0, number1, and
number99, you declare one array variable such as numbers and use
numbers[0], numbers[1], and ..., numbers[99] to represent individual
variables. A specific element in an array is accessed by an index.
All arrays consist of contiguous memory locations. The lowest address
corresponds to the first element and the highest address to the last element.
Declaring Arrays:
To declare an array in C++, the programmer specifies the type of the
elements and the number of elements required by an array as follows:
type array Name [ arraySize ];
This is called a single-dimension array. The arraySize must be an integer
constant greater than
zero and type can be any valid C++ data type. For example, to declare a 10element array called
balance of type double, use this statement:
double balance[10];
Initializing Arrays:
You can initialize C++ array elements either one by one or using a single
statement as follows:
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
The number of values between braces { } cannot be larger than the number
of elements that we declare for the array between square brackets [ ].
Following is an example to assign a single element of the array:
If you omit the size of the array, an array just big enough to hold the
initialization is created.
Therefore, if you write:
double balance[] = {1000.0, 2.0, 3.4, 17.0, 50.0};
You will create exactly the same array as you did in the previous example.
Balance[4] = 50.0;
The above statement assigns element number 5th in the array a value of 50.0.
Array with 4th index will be 5th, i.e., last element because all arrays have 0
as the index of their first element which is also called base index. Following
is the pictorial representation of the same array we discussed above:
Accessing Array Elements:
An element is accessed by indexing the array name. This is done by placing
the index of the element within square brackets after the name of the array.
For example:
double salary = balance[9];
The above statement will take 10th element from the array and assign the
value to salary variable. Following is an example, which will use all the
above-mentioned three concepts viz. declaration, assignment and accessing
arrays:
#include <iostream >
using name espace std;
#include <iom anip>
using std::setw;
int main ()
{
int n[ 10 ]; // n is an array of 10 integers
// initialize elements of array n to 0
for (int i = 0; i < 10; i++)
{
n[ i ] = i + 100; // set element at location i to i + 100
}
cout << "Element" << setw ( 13 ) << "Value" << endl;
// output each array element's value
for ( int j = 0; j < 10; j++ )
{
cout << setw(7 )<< j << setw( 13 ) << n[ j ] << endl;
}
return 0;
}
This program makes use of setw function to format the output. When the
above code is compiled and executed, it produces the following result:
Element Value
0 100
1 101
2 102
3 103
4 104
5 105
6 106
7 107
8 108
9 109
C++ Arrays in Detail:
Arrays are important to C++ and should need lots of more detail. There are
following few important concepts, which should be clear to a C++
programmer:
Concept
Multi-dimensional arrays
simplest
Description
C++ supports multidimensional arrays. The
form of the multidimensional array is the two
dimensional array.
Pointer to an array
You can generate a pointer to the first element of
an array by simply specifying the array name,
without any index.
Passing arrays to functions you can pass to the function a pointer to an array
by specifying the arrays
Return array from functions C++ allows a function to return an array.
C++ MULTIDIMENSIONAL ARRAY
C++ allows multidimensional arrays. Here is the general form of a
multidimensional array declaration:
type name [size1][size2]...[size N];
For example, the following declaration creates a three dimensional 5. 10. 4
integer array:
int three dim [5][10][4];
Two-Dimensional Arrays:
The simplest form of the multidimensional array is the two-dimensional array.
A two-dimensional array is, in essence, a list of one-dimensional arrays. To
declare a two-dimensional integer array of size x,y, you would write
something as follows:
type array Name [x ][ y ];
Where type can be any valid C++ data type and array Name will be a valid
C++ identifier.
A two-dimensional array can be think as a table, which will have x number of
rows and y number of columns. A 2-dimensional array a, which contains three
rows and four columns can be shown as below:
Thus, every element in array a is identified by an element name of the form a[
i ][ j ], where a is the name of the array, and i and j are the subscripts that
uniquely identify each element in a.
Initializing Two-Dimensional Arrays:
Multi dimensioned arrays may be initialized by specifying bracketed values
for each row. Followings an array with 3 rows and each row have 4 columns.
int a[3][4] = {
{0, 1, 2, 3}, /* initializers for row indexed by 0 * /
{4, 5, 6, 7} , /* initializers for row indexed by 1 * /
{8, 9, 10, 11} /* initializers for row indexed by 2 * /
};
The nested braces, which indicate the intended row, are optional. The
following initialization is equivalent to previous example:
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
Accessing Two-Dimensional Array Elements:
An element in 2-dimensional array is accessed by using the subscripts, i.e.,
row index and column index of the array. For example:
int val = a[2][3];
The above statement will take 4th element from the 3rd row of the array. You
can verify it in the above diagram.
#include <iostream >
using namespace std;
int main ()
{
// an array with 5 rows and 2 columns.
int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}};
// output each array element's value
for ( int i = 0; i < 5; i++ )
for (int j = 0; j < 2; j++ )
{
cout << "a[" << i << "][" << j << "]: ";
cout << a[i][j]<< endl;
}
return 0;
}
When the above code is compiled and executed, it produces the following
result:
a [0][0]: 0
a [0][1]: 0
a [1][0]: 1
a [1][1]: 2
a [2][0]: 2
a [2][1]: 4
a [3][0]: 3
a [3][1]: 6
a [4][0]: 4
a [4][1]: 8
As explained above, you can have arrays with any number of dimensions,
although it is likely that most of the arrays you create will be of one or two
dimensions
C++ POINTERS
C++ pointers are easy and fun to learn. Some C++ tasks are performed more
easily with pointers, and other C++ tasks, such as dynamic memory
allocation, cannot be performed without them.
As you know every variable is a memory location and every memory
location has its address defined which can be accessed using ampersand &
operator which denotes an address in memory. Consider the following which
will print the address of the variables defined:
#include <iostream >
using namespace std;
int main ()
{
int var1;
char var2 [10];
cout << "Address of var1 variable: ";
cout <<&var1 << endl;
cout << "Address of var2 variable: ";
cout <<&var2 << endl;
return 0;
}
When the above code is compiled and executed, it produces result
something as follows:
Address of var1 variable: 0xbfebd5c0
Address of var2 variable: 0xbfebd5b6
What Are Pointers?
A pointer is a variable whose value is the address of another variable. Like
any variable or constant, you must declare a pointer before you can work
with it. The general form of a pointer
variable declaration is:
type * var-name;
Here, type is the pointer's base type; it must be a valid C++ type and varname is the name of the pointer variable. The asterisk you used to declare a
pointer is the same asterisk that you use for multiplication. However, in this
statement the asterisk is being used to designate a variable as a pointer.
Following are the valid pointer declaration:
int * ip; // pointer to an integer
double * dp; // pointer to a double
float * fp; // pointer to a float
char * ch // pointer to character
The actual data type of the value of all pointers, whether integer, float,
character, or otherwise, is the same, a long hexadecimal number that
represents a memory address. The only difference between pointers of
different data types is the data type of the variable or constant that the
pointer points to.
Using Pointers in C++:
There are few important operations, which we will do with the pointers very
frequently. a we define a pointer variables b assign the address of a variable
to a pointer and c finally access the value at the address available in the
pointer variable. This is done by using unary operator * that returns the
value of the variable located at the address specified by its operand.
Following example makes
use of these operations:
#include <iostream >
using namespace std;
int main ()
{
int var = 20; // actual variable declaration.
int * ip; // pointer variable
ip = &var; // store address of var in pointer variable
cout << "Value of var variable: ";
cout << var << endl;
// print the address stored in ip pointer variable
cout << "Address stored in ip variable: ";
cout << ip << endl;
// access the value at the address available in pointer
cout << "Value of * ip variable: ";
cout << * ip << endl;
return 0;
}
When the above code is compiled and executed, it produces result
something as follows:
Value of var variable: 20
Address stored in ip variable: 0xbfc601ac
Value of * ip variable: 20
C++ Pointers in Detail:
Pointers have many but easy concepts and they are very important to C++
programming. There are following few important pointer concepts which
should be clear to a C++ programmer:
Concept
C++ Null Pointers
constant with a
Description
C++ supports null pointer, which is a
Value of zero defined in several standard
libraries.
C++ pointer arithmetic
be used
There are four arithmetic operators that can
pointers: ++, --, +, -
C++ pointers vs. array
pointers and
There is a close relationship between
arrays. Let us check how?
C++ array of pointers
pointers.
You can define arrays to hold a number of
C++ pointer to pointer
C++ allows you to have pointer on a pointer.
Passing pointers to functions
Passing an argument by reference or by
address both enable the passed argument to
be changed in the calling function by the
called function.
Return pointer from functions C++ allows a function to return a pointer to
local
Variable, static variable and dynamically
allocated memory as well.
C++ DATA STRUCTURES
C/C++ arrays allow you to define variables that combine several data items
of the same kind but structure is another user defined data type which
allows you to combine data items of different kinds.
Structures are used to represent a record, suppose you want to keep track
of your books in a library. You might want to track the following attributes
about each book:
• Title
• Author
• Subject
• Book ID
Defining a Structure:
To define a structure, you must use the struct statement. The struct
statement defines a new data type, with more than one member, for your
program. The format of the struct statement is this:
struct [structure tag]
{
member definition;
member definition;
...
member definition;
} [one or more structure variables];
The structure tag is optional and each member definition is a normal
variable definition, such as int i; or float f; or any other valid variable
definition. At the end of the structure's definition, before the final
semicolon, you can specify one or more structure variables but it is
optional. Here is the way you would declare the Book structure:
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
}book;
Accessing Structure Members:
To access any member of a structure, we use the member access operator
.. The member
access operator is coded as a period between the structure variable name and
the structure
member that we wish to access. You would use struct keyword to define
variables of structure
type. Following is the example to explain usage of structure:
#include <iostream >
#include <cstring>
using namespace std;
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
int m ain( )
{
struct Books Book1; // Declare Book1 of type Book
struct Books Book2; // Declare Book2 of type Book
// book 1 specification
strcpy( Book1.title, "Learn C++ Program m ing");
strcpy( Book1.author, "Chand Miyan");
strcpy( Book1.subject, "C++ Program m ing");
Book1.book_id = 6495407;
// book 2 specification
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Yakit Singha");
strcpy( Book2.subject, "Telecom ");
Book2.book_id = 6495700;
// Print Book1 info
cout << "Book 1 title : " << Book1.title <<endl;
cout << "Book 1 author : " << Book1.author <<endl;
cout << "Book 1 subject : " << Book1.subject <<endl;
cout << "Book 1 id : " << Book1.book_id <<endl;
// Print Book2 info
cout << "Book 2 title : " << Book2.title <<endl;
cout << "Book 2 author : " << Book2.author <<endl;
cout << "Book 2 subject : " << Book2.subject <<endl;
cout << "Book 2 id : " << Book2.book_id <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following
result:
Book 1 title : Learn C++ Program m ing
Book 1 author : Chand Miyan
Book 1 subject : C++ Program m ing
Book 1 id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Yakit Singha
Book 2 subject : Telecom
Book 2 id : 6495700
Structures as Function Arguments:
You can pass a structure as a function argument in very similar way as you
pass any other variable or pointer. You would access structure variables in
the similar way as you have accessed in the above example:
#include <iostream >
#include <cstring>
using namespace std;
void print Book( struct Books book );
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
int m ain( )
{
struct Books Book1; // Declare Book1 of type Book
struct Books Book2; // Declare Book2 of type Book
// book 1 specification
strcpy( Book1.title, "Learn C++ Program m ing");
strcpy( Book1.author, "Chand Miyan");
strcpy( Book1.subject, "C++ Program m ing");
Book1.book_id = 6495407;
// book 2 specification
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Yakit Singha");
strcpy( Book2.subject, "Telecom ");
Book2.book_id = 6495700;
// Print Book1 info
print Book( Book1 );
// Print Book2 info
print Book( Book2 );
return 0;
}
void printBook( struct Books book )
{
cout << "Book title : " << book.title <<endl;
cout << "Book author : " << book. Author <<endl;
cout << "Book subject : " << book.subject <<endl;
cout << "Book id : " << book.book_id <<endl;
}
When the above code is compiled and executed, it produces the following
result:
Book title : Learn C++ Program m ing
Book author : Chand Miyan
Book subject : C++ Program m ing
Book id : 6495407
Book title : Telecom Billing
Book author : Yakit Singha
Book subject : Telecom
Book id : 6495700
Pointers to Structures:
You can define pointers to structures in very similar way as you define
pointer to any other
variable as follows:
struct Books * struct_pointer;
Now, you can store the address of a structure variable in the above defined
pointer variable. To find the address of a structure variable, place the &
operator before the structure's name as follows:
struct_pointer = &Book1;
To access the members of a structure using a pointer to that structure, you
must use the ->
operator as follows:
struct_pointer->title;
Let us re-write above example using structure pointer, hope this will be
easy for you to understand the concept:
#include <iostream >
#include <cstring>
using namespace std;
void print Book( struct Books * book );
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
int m ain( )
{
struct Books Book1; // Declare Book1 of type Book
struct Books Book2; // Declare Book2 of type Book
// Book 1 specification
strcpy( Book1.title, "Learn C++ Program m ing");
strcpy( Book1.author, "Chand Miyan");
strcpy( Book1.subject, "C++ Program m ing");
Book1.book_id = 6495407;
// Book 2 specification
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Yakit Singha");
strcpy( Book2.subject, "Telecom ");
Book2.book_id = 6495700;
// Print Book1 info, passing address of structure
Print Book( &Book1 );
// Print Book1 info, passing address of structure
Print Book( &Book2 );
return 0;
}
//This function accept pointer to structure as parameter.
void print Book( struct Books * book )
{
cout << "Book title : " << book->title <<endl;
cout << "Book author : " << book->author <<endl;
cout << "Book subject : " << book->subject <<endl;
cout << "Book id : " << book->book_id <<endl;
}
When the above code is compiled and executed, it produces the following
result:
Book title : Learn C++ Program m ing
Book author : Chand Miyan
Book subject : C++ Program m ing
Book id : 6495407
Book title : Telecom Billing
Book author : Yakit Singha
Book subject : Telecom
Book id : 6495700
The typed Keyword
There is an easier way to define structs or you could "alias" types you
create. For example:
typedef struct
{
char title[50];
char author[50];
char s ubject[100];
int book_id;
}Books;
Now, you can use Books directly to define variables of Books type without
using struct keyword.
Following is the example:
Books Book1, Book2;
You can use typedef keyword for non-structs as well as follows:
typedef long int * pint32;
pint32 x, y, z;
STRUCTURES AND UNIONS
We studied earlier that array is a data structure whose element are all of the
same data type. Now we are going towards structure,which is a data
structure whose individual elements can differ in type.
Thus a single structure might contain integer elements,floating– point
elements and character elements. Pointers, array sand other structures can
also be included as elements within a structure.
The individual structure elements are referred to as members. This
lesson is concerned with the use of structure withina 'c' program. We will
see how structures are defined, and how their individual members are
accessed and processed within a program.The relationship between
structures and pointers, arrays and functions will also be examined. Closely
associated with the structure is the union, which also contains multiple
members.
OBJECTIVES
After going through this lesson you will be able to
•
explain the basic concepts of structure
•
process a structure
•
use typedef statement
•
explain the between structures and pointers
STRUCTURE
In general terms, the composition of a structure may be defined as
struct tag
{ member 1;
member 2;
-----------------------member m; }
In this declaration, struct is a required keyword ,tag is a name that
identifies structures of this type.
The individual members can be ordinary variables, pointers, arraysor
other structures. The member names within a particular structure must
be distict from one another, though a member name can be same as the
name of a variable defined outside of the structure.
A storage class, however, cannot be assigned to an individual
member, and individual members cannot be initialized within a structuretype declaration. For example:
struct student
{
char name [80];
int roll_no;
float marks;
};
we can now declare the structure variable s1 and s2 as follows:
struct student s1, s2;
s1 and s2 are structure type variables whose composition is
identified by the tag student.
It is possible to combine the declaration of the structure composition
with that of the structure variable as shown below.
storage- class struct tag
Structures and Unions :: 281
{
member 1;
member 2;
- ——
- —- member m;
} variable 1, variable 2 --------- variable n;
The tag is optional in this situation.
struct student {
char name [80];
int roll_no;
float marks;
} s1, s2;
The s1, s2, are structure variables of type student. Since the variable
declarations are now combined with the declaration of the structure type,
the tag need not be included.
As a result, the above declaration can also be written as
struct{
char name [80];
int roll_no;
float marks ;
} s1, s2, ;
A structure may be defined as a member of another structure. In such
situations, the declaration of the embedded structure must appear before the
declaration of the outer structure. The members of a structure variable can
be assigned initial values in much the same manner as the elements of an
array. The initial values must appear in the order in which they will be
assigned to their corresponding
structure members, enclosed in braces and separated by commas. The
general form is storage-class struct tag variable = { value1, value 2,-------,
value m};
A structure variable, like an array can be initialized only if its storage
class is either external or static.
e.g. suppose there are one more structure other than student.
Computer Applications
struct dob
{ int month;
int day;
int year;
};
struct student
{ char name [80];
int roll_no;
float marks;
struct dob d1;
};
static struct student st = { “ param”, 2, 99.9, 17, 11, 01};
It is also possible to define an array of structure, which is an array in which
each element is a structure. The procedure is shown in the following
example:
struct student{
char name [80];
int roll_no ;
float marks ;
} st [100];
In this declaration at is a 100- element array of structures.It means each
element of at represents an individual student record.
PROCESSING A STRUCTURE
The members of a structure are usually processed individually, as separate
entities. Therefore, we must be able to access the individual structure
members. A structure member can be accessed by writing variable.member
name.
This period (.) is an operator, it is a member of the highest
precedence group, and its associativity is left-to-right.
Thus in the case of student and dob structure, to access the month of date of
birth of a student, we would write st.d1.month The use of the period operator
can be extended to arrays of structure,by writing array [expression]. Member
Structures members can be processed in the same manner as ordinary
variables of the same data type. Single-valued structure members can appear
in expressions. They can be passed to functions and they can be returned
from functions, as though they were ordinary single-valued variables.
e.g. suppose that s1 and s2 are structure variables having the same
composition as described earlier. It is possible to copy the values of
s1 to s2 simply by writing
s2=s1;
It is also possible to pass entire structure to and from functions
though the way this is done varies from one version of 'C' to another.
Let us consider an example of structure:
#include <stdio.h>
struct date {
int month;
int day;
int year;
};
struct student{
Computer Applications
char name[80];
char address[80];
int roll_no;
char grade;
float marks;
struct date d1;
}st[100];
main()
{
int i,n;
void read input (int i);
void write output(int i);
printf(“Student system”);
printf(“How many students are there ?”);
scanf(“%d” &n);
for (i=0; i<n; ++i){
readinput (i);
if( st[i].marks <80)
st[i].grade=’A’;
else
st[i].grade='A'+;
}
for (i=0; i<n; ++i)
writeoutput(i);
}
void readinput (int i)
{
printf(“\n student no % \n”, i+1);
printf(“Name:”);
scanf(“%[^\n]”, st[i].name);
printf(“Address:”);
scanf(“%[^\n]", st[i].address);
Structures and Unions :: 285
printf(“Roll number”);
scanf(“%d”, &st[i].roll_no);
printf(“marks”);
scanf(“%f”,&st[i].marks);
printf(“Date of Birth {mm/dd/yyyy)”);
scanf(“%d%d%d”, & st[i].d1.month & st[i].d1.day, & st[i].d1.year);
return;
}
void writeoutput(int i)
{
printf(“\n Name:%s”,st[i].name);
printf(“Address %s\n”, st[i].address);
printf(“Marks % f \n”, st[i].marks);
printf(“Roll number %d\n”, st[i].roll_no);
printf(“Grade %c\n”,st[i].grade);
return;
}
It is sometimes useful to determine the number of bytes required by an
array or a structure.
USER-DEFINED DATA TYPES (Typedef)
The typedef feature allows users to define new data types that are
equivalent to existing data types. Once a user-defined data type has been
established, then new variables, arrays, structure and so on, can be declared
in terms of this new data type. In general terms, a new data type is defined
as
Computer Applications
typedef type new type;
Where type refers to an existing data type and new-type refers to the new
user-defined data type.
e.g. typedef int age;
In this declaration, age is user- defined data type equivalent to type
int. Hence, the variable declaration age male, female;is equivalent to writing
int age, male, female;
The typedef feature is particularly convenient when defining structures,
since it eliminates the need to repeatedly write struct tag whenever a
structure is referenced. As a result, the structure can be referenced more
concisely.In general terms, a user-defined structure type can be written as
typedef struct
{ member 1;
member 2:
------member m;
}new-type;
The typedef feature can be used repeatedly, to define one data type in terms
of other user-defined data types.
STRUCTURES AND POINTERS
The beginning address of a structure can be accessed in the same manner as
any other address, through the use of the address (&)operator.
Thus, if variable represents a structure type variable, then & variable
represents the starting address of that variable. We can declare a pointer
variable for a structure by writing type *ptr;
Where type is a data type that identities the composition of the structure,
and ptr represents the name of the pointer variable.
We can then assign the beginning address of a structure variable to this
pointer by writing
ptr= &variable;
Let us take the following example:
typedef struct {
char name [ 40];
int roll_no;
float marks;
}student;
student s1,*ps;
In this example, s1 is a structure variable of type student, and ps is a
pointer variable whose object is a structure variable of type student.Thus,
the beginning address of s1 can be assigned to ps by writing.
ps = &s1;
An individual structure member can be accessed in terms of its
Corresponding pointer variable by writing ptr ®member Where ptr refers to
a structure- type pointer variable and the operator ® is comparable to the
period (.) operator. The associativity of this
operator is also left-to-right.
The operator ® can be combined with the period operator (.) to access a
sub member within a structure. Hence, a sub member can be accessed by
writing ptr ® member.submember
PASSING STRUCTURES TO A FUNCTION
There are several different ways to pass structure–type information to or
from a function. Structure member can be transferred individually, or entire
structure can be transferred. The individual structures members can be
passed to a function as arguments in the function call; and a single structure
member can be returned via the return statement. To do so, each structure
member is treated the same way as an ordinary, single- valued variable.
Computer Applications
A complete structure can be transferred to a function by passing a structure
type pointer as an argument. It should be understood that a structure passed
in this manner will be passed by reference rather than by value.. Let us
consider the following example:
# include <stdio.h>
typedef struct{
char *name;
int roll_no;
float marks ;
} record ;
main ( )
{
void adj(record *ptr);
static record stduent={“Param”, 2,99.9};
printf(“%s%d%f\n”, student.name,
student.roll_no,student.marks);
adj(&student);
printf(“%s%d%f\n”, student.name,
student.roll_no,student.marks);
}
void adj(record*ptr)
{
ptr ® name=”Tanishq”;
ptr ® roll_no=3;
ptr ® marks=98.0;
return;
}
Let us consider an example of transferring a complete structure,
rather than a structure-type pointer, to the function.
# include <stdio.h>
typedef struct{
Structures and Unions :: 289
char *name;
int roll_no;
float marks;
}record;
main()
{
void adj(record stduent); /* function declaration */
static record student={“Param,” 2,99.9};
printf(“%s%d%f\n”,
student.name,student.roll_no,student.marks);
adj(student);
printf(“%s%d%f\n”,
student.name,student.roll_no,student.marks);
}
void adj(record stud) /*function definition */
{
stud.name=”Tanishq”;
stud.roll_no=3;
stud.marks=98.0;
return;
}
UNIONS
Union, like structures, contain members whose individual data types may
differ from one another. However, the members that compose a union all
share the same storage area within the computer’s memory
Computer Applications
, whereas each member within a structure is assigned its own unique storage
area. Thus, unions are used to conserve memory.In general terms, the
composition of a union may be defined as
union tag{
member1;
member 2;
--member m
};
Where union is a required keyword and the other terms have the same
meaning as in a structure definition. Individual union variables can then be
declared as storage-class union tag variable1, variable2, -----, variable n;
where storage-class is an optional storage class specifier, union is a required
keyword, tag is the name that appeared in the union definition and variable
1, variable 2, variable n are union variables of type tag.
The two declarations may be combined, just as we did in the case of
structure. Thus, we can write.Storage-class union tag{
member1;
member 2;
--member m
}variable 1, varibale2. . . variable n;
The tag is optional in this type of declaration.
Let us take a 'C' program which contains the following union
declaration:
union code{
char color [5];
int size ;
}purse, belt;
Here we have two union variables, purse and belt, of type code.
Structures and Unions :: 291
Each variable can represent either a 5–character string (color)
or an integer quantity (size) of any one time.
A union may be a member of a structure, and a structure may be a member
of a union.
An individual union member can be accessed in the same manner as an
individual structure members, using the operators (®) and.
Thus if variable is a union variable, then varibale.member refers to a member
of the union. Similarly, if ptr is a pointer variable that points to a union, then
ptr® member refers to a member of that union.
Let us consider the following C program:
# include <stdio.h>
main()
union code{
char color;
int size;
};
struct {
char company [10];
float cost ;
union code detail;
}purse, belt;
printf(“%d\n”, sizeof (union code));
purse.detail.color=’B’;
printf(“%c%d\n”, purse.detail.color,purse.detail.size);
purse.detail.size=20;
printf(“%c%d\n”, purse. detail.color,purse.detail.size);
}
The output is as follows:
2
B- 23190
@ 20
The first line indicates that the union is allocated 2 bytes of memory
WHAT YOU HAVE LEARNT
In this lesson you have learnt about structures. Structures contain the
variables of different data types. You can also pass structures to functions.
You have also learnt about unions. All members of a union share the same
storage area within the computer’s memory.
Control statements in c++
The normal flow of execution in a high level language is sequential, i.e.,
each statement is executed in the order of its appearance in the program.
However, depending on the requirements of a problem it might be required to
alter the normal sequence of execution in a program. The statements which
specify the order of execution of statements are called control flow statements.
Sometimes the program needs to be executed depending upon a particular
condition. C++ provides the following statements for implementing the
selection control structure.
(i) ‘if ’ statement
(ii) ‘if else’ statement
(iii) ‘nested if’ statement
(iv) ‘switch’ statement
1.If statement
syntax of the ‘if’ statement
if (condition)
{
statement(s);
}
From the flowchart it is clear that if the 'if condition' is true, statement 1 is
executed; otherwise it is skipped. The statement 1 may either be a single or
compound statement.
2. if else statement
Syntax of the if- else statement
if (condition)
statement1;
else
statement2;
From the above flowchart it is clear that the given condition is evaluated first.
If the condition is true, statement1 is executed, followed by statement3. If the
condition is false, statement2 is executed, followed by statement 3. It should
be kept in mind that statement1 and statement2 can be single or compound
statement.
Example
# include <iostream.h>
void main ()
{
int x, y;
cout << “Enter two numbers” <<“\n”;
cin>> x >> y ;
if ( x > y)
cout << “The bigger number is ” << X;
else
cout << “The bigger number is” <<y;
}
3. Nested if statement
Syntax of the nested if statement
(i) The if block may be nested in another if or else block. This is called
nesting
of if or else block.
if (condition1)
{
if (condition2)
{
statement(s);
}
}
if (condition 1)
statement1;
else if (condition2)
statement2;
else statement 3;
From the flowchart it is clear that condition 1, condition2, etc. are nested in
sequence until a condition is reached that evaluates to TRUE. Only one
statement will be executed. If condition1 is TRUE, then statement1 is
executed. If none of the conditions is TRUE, then statement 3 is executed.
Regardless of which statement is executed, control is passed to the statement
following statement3. Each statement can be single or compound statement.
Example
# include < isostream.h>
void main ( )
{
int x, y, z;
cout << “Enter three numbers” << “\n”;
cin >> x >> y >> z ;
if ( x > y )
{
if (x >z)
cout << “The greatest number is “ << x;
else
cout << “The greatest number is “<<z;
}
else
{
if (y > z)
cout << “The greatest number is “<< y;
else
cout “The greatest number is “ << z;
}
}
4.Switch statement
The if and if-else statements permit two way branching whereas switch
statement permits multiple branching.
The syntax of switch statement is:
switch (var / expression)
{
case constant1 : statement1;
break;
case constant2 : statement2;
break;
default : statement3;
}
The execution of switch statement begins with the evaluation of
expression. If the values of expression matches with the constant then the
statements following this statement execute sequentially till it executes
break. The break statement transfers control to the end of the switch
statement. If the value of expression does not match with any constant, the
statement with default is executed.
Example
# include < iostream.h>
void main ( )
{
char ch;
cout << "Enter a character";
cin >> ch;
switch (ch)
{
case 'a' : cout << "vowel a";
break ;
case 'e' : cout << "vowel e";
break ;
case 'o' : cout << "vowel o";
break ;
case 'i' : cout << "vowel i"
break ;
case ‘u’ : cout << “vowel u”;
break;
default : cout <<“not a vowel”;
}
}
The program needs the break statement to confine execution to particular
portion of switch. If the break statement is removed from the above program
then it starts executing the statements associated with case labels specified
till it comes across either the break statement or end of switch statement. The
above switch statement can be written as:
switch (ch)
{
case ‘a’ :
case ‘A’ : cout << “vowel a”;
case ‘e’ :
case ‘E’ : cout << “vowel e”;
case ‘i’ :
case ‘I’ : cout << “vowel i”;
break;
case ‘o’ :
case ‘O’ : cout << “vowel o”;
break;
default : cout << “not a vowel”;
}
The input character either in small letter or capital will be accepted.
Loop Construct
It is also called a Repetitive control structure. Sometimes we require a set of
statements to be executed a number of times by changing the value of one or
more variables each time to obtain a different result. This type of program
execution is called looping. C++ provides the following constructs.
(i) while loop
(ii) do - while loop
(iii) for loop\
1.While loop
Syntax of while loop
while (condition)
{
statement(s);
}
The flow diagram indicates that a condition is first evaluated. If the condition
is true, the loop body is executed and the condition is re-evaluated. Hence, the
loop body is executed repeatedly as long as the condition remains true. As
soon as the condition becomes false, it comes out of the loop and goes to the
statement next to the ‘while’ loop. To make it more clear, we take the
following example.
The variable n is called a loop control variable since its value is used to
control loop repetition. Normally, the three operations listed below must be
performed on the loop control variable.
(i) Initialize the loop control variable
(ii) Test the loop control variable
(iii) Update the loop control variable
Operation (i) must be performed before the loop is entered.
Operation (ii) must be performed before each execution of the loop body;
depending on the result of this test, the loop will either be repeated or
make an exit.
Operation (iii) must be included as part of the loop body. Unless the loop
control variable is updated in the loop body,its value cannot change and
loop exit will never occur.
Example
To find the sum of first ten natural numbers i.e. 1, 2, 3 ...10.
# include <iostream.h>
void main ( )
{ int n, total = 0 ;
n=1;
while (n < = 10)
{
total + = n ;
n++;
}
cout << “sum of first ten natural number” << total :
}
1. Do while loop
Syntax of do-while loop
do
{
} while (condition);
The flow diagram indicates that after each execution of the loop body, the
condition is true, the loop body is executed again. If the condition evaluates
to false, loop exit occurs and the next program statement is executed.
Note : that the loop body is always executed at least once.
One important difference between the while loop and the do-while loop is the
relative ordering of the conditional test and loop body execution. In the while
loop, the loop repetition test is performed before each execution of the loop
body; the loop body is not executed at all if the initial test fails. In the do-while
loop, the loop termination test is Performed after each execution of the loop
body; hence, the loop body is always executed at least once.
Let us take an example to explain it further.
Example
To find the sum of the first N natural number.
# include < iostream.h>
void main ( )
{
int N, number, sum;
cin >> N;
sum = 0;
number = 1;
do
{
sum + = number;
number + + ;
}
while (number < = N) ;
cout << sum;
}
2.For loop
It is a count controlled loop in the sense that the program knows in advance
how many times the loop is to be executed.
syntax of for loop
for (intialization; decision; increment/decrement)
{
statement(s);
}
The flow diagram indicates that in for loop three operations take place:
(i) Initialization of loop control variable
(ii) Testing of loop control variable
(iii) Update the loop control variable either by incrementing or decrementing.
Operation (i) is used to initialize the value.
On the other hand,
operation (ii) is used to test whether the condition is true or false. If the
condition is true, the program executes the body of the loop and then the
value of loop control variable is updated. Again it checks the condition and so
on. If the condition is true, it gets out of the loop.
Example
for (int i = 0 ; i < 5 ; i + + )
cout << i ;
The output of the above program is
01234
for (char i = ‘A’; i < ‘E’ ; i + + )
cout << i ;
The output of the above program is
ABCD
Data types in C++
A data type determines the type and the operations that can be performed on the
data. C++ provides various data types and each data type is represented
differently within the computer's memory. The various data types provided by
C++ are built-in data types, derived data types and user-defined data types as
shown in Figure.
Built-In Data Types
The basic (fundamental) data types provided by c++ are integral, floating
point and void data type. Among these data types, the integral and floating-point
data types can be preceded by several type modifiers.
These modifiers (also known as type qualifiers) are the keywords that alter
either size or range or both of the data types. The various modifiers are short,
long, signed and unsigned. By default the modifier is signed.
In addition to these basic data types, ANSI C++ has introduced two more data
types namely, bool and wchart.
Integral Data Type:
The integral data type is used to store integers and includes char (character) and
int (integer) data types.
Char: Characters refer to the alphabet, numbers and other characters (such as
{, @, #, etc.) defined in the ASCII character set. In C++, the char data type is
also treated as an integer data type as the characters are internally stored as
integers that range in value from -128 to 127. The char data type occupies 1
byte of memory (that is, it holds only one character at a time).
The modifiers that can precede char are signed and unsigned. The various
character data types with their size and range are listed in Table
Int:Numbers without the fractional part represent integer data. In C++, the int
data type is used to store integers such as 4, 42, 5233, -32, -745. Thus, it cannot
store numbers such as 4.28, -62.533. The various integer data types with their
size and range are listed in Table
Floating-point Data Type: A floating-point data type is used to store real
numbers such as 3 .28, 64. 755765, 8.01, -24.53. This data type includes float
and double' data types. The various floating -point data types with their size and
range are listed in Table
Void: The void data type is used for specifying an empty parameter list to a
function and return type for a function. When void is used to specify an empty
parameter list, it indicates that a function does not take any arguments and
when it is used as a return type for a function, it indicates that a function does
not return any value.
Bool and wchat : The boo1data type can hold only Boolean values, that is;
either true or false, where true represents 1 and false represents O. It requires
only one bit of storage, however, it is stored as an integer in the memory.
Thus, it is also considered as an integral data type. The bool data type is most
commonly used for expressing the results of logical operations performed on
the data. It is also used as a return type of a function indicating the success or
the failure of the function.
In addition to char data type, C++ provides another data type wchart which is
used to store 16- bit wide characters. Wide characters are used to hold large
character sets associated with some non-English languages.
Derived Data Types: Data types that are derived from the built-in data types
are known as derived data types. The various derived data types provided by
C++ are arrays, junctions, references and pointers.
• Array An array is a set of elements of the same data type that are
referred to by the same name. All the elements in an array are stored at
contiguous (one after another) memory locations and each element is
accessed by a unique index or subscript value. The subscript value
indicates the position of an element in an array.
• Function A function is a self-contained program segment that carries
out a specific well-defined task. In C++, every program contains one
or more functions which can be invoked from other parts of a program,
if required.
• Reference A reference is an alternative name for a variable. That is, a
reference is an alias for a variable in a program. A variable and its
reference can be used interchangeably in a program as both refer to the
same memory location. Hence, changes made to any of them (say, a
variable) are reflected in the other (on a reference).
• Pointer A pointer is a variable that can store the memory address of
another variable. Pointers allow to use the memory dynamically. That
is, with the help of pointers, memory can be allocated or de-allocated
to the variables at run-time, thus, making a program more efficient.
User-Defined Data Types
Various user-defined data types provided by C++ are structures, unions,
enumerations andclasses.
• Structure, Union andClass: Structure and union are the significant
features of C language. Structure and union provide a way to group
similar or dissimilar data types referred to by a single name.
However, C++ has extended the concept of structure and union by
incorporating some new features in these data types to support
object -oriented programming.
• C++ offers a new user-defined data type known as class, which
forms the basis of object-oriented programming. A class acts as a
template which defines the data and functions that are included in
an object of a class. Classes are declared using the keyword class.
Once a class has been declared, its object can be easily created.
• Enumeration: An enumeration is a set of named integer constants
that specify all the permissible values that can be assigned to
enumeration variables. These set of permissible values are known as
enumerators. For example, consider this statement.
enum country {US, UN, India, China};
// declaring an
// enum type
• In this statement, an enumeration data-type country (country is a tag
name), consisting of enumerators US, UN and so on, is declared.
Note that these enumerators represent integer values, so any
arithmetic operation can be performed on them.
By default, the first enumerator in the enumeration data type is assigned the
value zero. The value of subsequent enumerators is one greater than the value
of previous enumerator. Hence, the value of US is 0, value of UN is 1 and so
on. However, these default integer values can be overridden by assigning values
explicitly to the enumeratorsas shown here.
enum country {US, UN=3, India, china} ;
In this declaration, the value of US is O by default, the value of UN is 3, India
is 4 and soon.
Once an enum type is declared, its variables can be declared using this
statement.
country countryl, country2;
These variables countryl, country2 can be assigned any of the values specified
in enum declaration only. For example, consider these statements.
countryl India; // valid
country2 Japan; // invalid
Though the enumerations are treated as integers internally in C++, the compiler
issues a warning, if an int value is assigned to an enum type. For example,
consider these statements.
Country1 = 3;
Country1 = UN;
//warning
/ /valid
Country1 = (country) 3; / /valid
C++ also allows creating special type of enums known as anonymous
enums, that is, enums without using tag name as shown in this statement.
enum {US, UN=3, India, China};
The enumerators of an anonymous enum can be used directly in the program as
shown here.
int count = US;
Operator In C++
An operator is a symbol that tells the compiler to perform specific mathematical
or logicalmanipulations.
C++ is rich in built-in operators and provides the following types of operators:
Ø Arithmetic Operators
Ø Relational Operators
Ø Logical Operators
Ø Bitwise Operators
Ø Assignment Operators
Ø Misc. Operator
This chapter will examine the arithmetic, relational, logical, bitwise,
assignment and other operators one by one.
Arithmetic Operators:
There are following arithmetic operators supported by C++ language:
Assume variable A holds 10 and variable B holds 20, then: Show Examples
Operator
Description
Example
+
30
Adds two operands
A + B will give
10
Subtracts second operand from the first
A - B will give -
*
200
Multiplies both operands
A * B will give
/
Divides numerator by de-numerator
B / A will give 2
%
Modulus Operator and remainder of after
an integer division
B % A will give
Increment operator, increases integer
value by one
A++ will give
0
++
11
--
Decrement operator, decreases integer
value by one
A-- will give 9
Relational Operators:
There are following relational operators supported by C++ language Assume
variable A
holds 10 and variable B holds 20, then: Show Examples
Operator
==
!=
Description
Example
Checks if the values of two operands are
equal or not, if yes then condition
becomes true.
A == B is not true.
Checks if the values of two operands are
equal or not, if values are not equal then
condition becomes true.
A! = B is true.
>
Checks if the value of left operand is
greater than the value of right operand, if
yes then condition becomes true.
A >B is not true.
<
Checks if the value of left operand is less
than the value of right operand, if yes
then condition becomes true.
A <B is true.
>=
Checks if the value of left operand is
greater than or equal to the value of right
operand, if yes then condition becomes
true.
A >= B is not true.
<=
Checks if the value of left operand is less
than or equal to the value of right
operand, if yes then condition becomes
true.
A <= B is true.
Logical Operators:
There are following logical operators supported by C++ language
Assume variable A holds 1 and variable B holds 0, then:
Show Examples
Operator
Description
Example
&&
Called Logical AND operator. If both the
operands are non-zero, then condition
becomes true.
A && B is false.
||
Called Logical OR Operator. If any of the
two operands is non-zero, then condition
becomes true.
A | | B is true.
!
Called Logical NOT Operator. Use to
reverses the logical state of its operand. If
a condition is true, then Logical NOT
operator will make false.
! A && B is
true.
Bitwise Operators:
Bitwise operator works on bits and perform bit-by-bit operation. The truth
tables for &, |, and ^ are as follows:
pq p&qp|qp^q
00 0
0
0
01 0
1
1
11 1
1
0
10 0
1
1
Assume if A = 60; and B = 13; now in binary format they will be as follows:
A = 0011 1100
B = 0000 1101
----------------A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011
The Bitwise operators supported by C++ language are listed in the following
table. Assume
variable A holds 60 and variable B holds 13, then:
Show Examples
Operator
Description
Example
&
Binary AND Operator
0000 1100
A & B will give 12 which is
|
1101
Binary OR Operator
A | B will give 61 which is 0011
^
0001
Binary XOR Operator
AB will give 49 which is 0011
Binary Ones Complement
Operator is unary
0011
A will give -61 which is 1100
~
.
<<
Binary Left Shift Operator. The left
operands value is moved left by the
number of bits specified by the right
operand.
A << 2 will give 240 which is
11110000
>>
Binary Right Shift Operator. The left
Operands value is moved right by the
number of bits specified by the right
operand.
A >> 2 will give 15 which is
0000 1111
Assignment Operators:
There are following assignment operators supported by C++ language:
Show Examples
Operator
Description
Example
=
Simple assignment operator, Assigns
values from right side operands to left
side operand
C = A + B will assign
value of A + Binto C
+=
Add AND assignment operator, It adds
right operand to the left operand and
assign the result to left operand
-= Subtract AND assignment operator, It
subtracts right operand from the left
*=
/=
Multiply AND assignment operator, It
multiplies right operand with the left
operand and assign the result to left
Divide AND assignment operator, It
divides left operand with the right
operand and assign the result to left
C += A is
equivalent to C
=C+A
C -= A is
equivalent to C
=C-A
C *= A is
equivalent to C =
C*A
C /= A is
equivalent to C =
C/A
%=
Modulus AND assignment operator, It
akes modulus using two operands and
assign the result to left operand
C %= A is
equivalent to C
=C%A
<<=Left shift AND assignment operator C <<= 2 is same as C C<< 2
>>= Right shift AND assignment operator
C=C>> 2
&=
=C & 2
^=
|=
C >>= 2 is same as
Bitwise AND assignment operator
C &= 2 is same as C
bitwise exclusive OR and assignment
operator
C ^= 2 is same as C = C ^ 2
bitwise inclusive OR and assignment
Operator
C |= 2 is same as C =
C|2
Misc Operators
There are few other operators supported by C++ Language.
Operator
Sizeof
Description
sizeof operator returns the size of a variable. For
example, sizeofa,where a is integer, will return 4.
Condition? X: Y
Conditional operator. If Condition is true? then it
returns value X:
otherwise value Y
,
. dot and ->arrow
Comma operator causes a sequence of operations to be
performed. The value of the entire comma expression is
the value of the last expression of the comma-separated
list.
Member operators are used to reference individual
members of classes, structures, and unions.
Cast
example,
Casting operators convert one data type to another. For
Int2.2000 would return 2.
&
Pointer operator & returns the addressofanvariable.
Forexample;willgiveactualaddressofthevariable.
*
Pointeroperator*ispointertoavariable.Forexample
*var;willpointertoavariablevar.
Operators Precedence in C++:
Operator precedence determines the grouping of terms in an expression.
This affects how an
expression is evaluated. Certain operators have higher precedence than
others; for example, the
Multiplication operator has higher precedence than the addition operator:
For example x = 7 + 3 * 2; here, x is assigned 13, not 20 because
operator * has higher
precedence than +, so it first gets multiplied with 3*2 and then adds into 7.
Here, operators with the highest precedence appear at the top of the table,
those with the lowest
appear at the bottom. Within an expression, higher precedence operators
will be evaluated first.
Show Examples
Category
Postfix
Unary
left
Operator
[] -> . ++ - + - ! ~ ++ - - type* & sizeof
Associativity
Left to right
Right to
Multiplicative
*/%
right
Additive
+right
Shift
<<>>
right
Relational
<<= >>=
right
Equality
== !=
right
Bitwise AND
&
right
Bitwise
XOR ^
right
Bitwise
OR |
right
Logical AND
&&
right
Logical
OR ||
right
Conditional
?
Assignment = += -= *= /= %=>>= <<= &= ^= |=
Comma
,
Left to right
Left to
Left to
Left to
Left to
Left to
Left to
Left to
Left to
Left to
Left to
Right to left
Right to left
UNIT-IV
Derivedclasses
Any class type (whether declared with class-key class or struct) may be declared
as derived from one or more base classes which, in turn, may be derived from their
own base classes, forming an inheritance hierarchy.
The list of base classes is provided in the base-clause of the class declaration
syntax. The base-clause consists of the character: followed by a comma-separated
list of one or more base-specifiers.
attr(C++11) - optional sequence of any number of attributes
access-specifier - one of private, public, or protected
virtual-specifier - the keyword virtual
Virtual-specifier and access-specifier may appear in any order
If access-specifier is omitted, it defaults to public for classes declared with classkey struct and to private for classes declared with class-key class.
Struct Base {
Int a, b, c;
};
// every object of type Derived includes Base as a sub object
Struct Derived: Base {
Int b;
};
// every object of type Derived2 includes Derived and Base as sub objects
Struct Derived2: Derived {
Int c;
};
The classes listed in the base-clause are direct base classes. Their bases are indirect
base classes. The same class cannot be specified as a direct base class more than
once, but the same class can be both direct and indirect base class.
Each direct and indirect base class is present, as base class subobject, within the
object representation of the derived class at implementation-defined offset. Empty
base classes usually do not increase the size of the derived object due to empty
base optimization.
Virtual base classes
For each distinct base class that is specified virtual, the most derived object
contains only one base class subobject of that type, even if the class appears many
times in the inheritance hierarchy (as long as it is inherited virtual every time).
Struct B {int n ;};
Class X: public virtual B {};
Class Y: virtual public B {};
Class Z: public B {};
// every object of type AA has one X, one Y, one Z, and two B's:
// one that is the base of Z and one that is shared by X and Y
Struct AA: X, Y, Z {
Void f () {
X::n = 1; // modifies the virtual B subobject's member
Y::n = 2; // modifies the same virtual B subobject's member
Z::n = 3; // modifies the non-virtual B subobject's member
std::cout<< X::n << Y::n << Z::n << '\n'; // prints 223
}
};
All virtual base subobjects are initialized before any non-virtual base subobject, so
only the most derived class calls the constructors of the virtual bases in its member
initializer list:
Struct B {
Int n;
B (int x): n(x) {}
};
Struct X: virtual B {X (): B (1) {} };
Struct Y: virtual B {Y (): B (2) {} };
Struct AA: X, Y {AA (): B (3), X (), Y () {} };
// the default constructor of AA calls the default constructors of X and Y
// but those constructors do not call the constructor of B because B is a virtual base
AA a; // a.n == 3
// the default constructor of X calls the constructor of B
X x; // x.n == 1
They are special rules for unqualified name lookup for class members when virtual
inheritance is involved (sometimes referred to as the rules of dominance),
see unqualified_lookup#Member_function_definition.
Public inheritance
• When a class uses public member access specifier to derive from a base, all
public members of the base class are accessible as public members of the
derived class and all protected members of the base class are accessible as
protected members of the derived class Public inheritance models the sub
typing relationship of object-oriented programming: the derived class object
IS-A base class object.
• References and pointers to a derived object are expected to be usable by any
code that expects references or pointers to any of its public bases (see LSP)
or, in DbC terms, a derived class should maintain class invariants of its
public bases, should not strengthen any precondition or weaken any post
condition of a member function it overrides.
• This section is incomplete
Reason: typical Shape, Vehicle, and Animal don't do much with invariants.
Would be nice to have a concise example that adjusts contracts correctly:
weakens pre and/or strengthens post in the derived class
Protected inheritance
When a class uses protected member access specifier to derive from a base, all public
and protected members of the base class are accessible as protected members of the
derived class (private members of the base are never accessible unless friended)
Protected inheritance may be used for "controlled polymorphism": within the
members of Derived, as well as within the members of all further-derived classes,
the derived class IS-A base: references and pointers to Derived may be used where
references and pointers to Base are expected.
Private inheritance
• When a class uses private member access specifier to derive from a base, all
public and protected members of the base class are accessible as private
members of the derived class (private members of the base are never
accessible unless friended).
• Private inheritance is commonly used in policy-based design, since policies
are usually empty classes, and using them as bases both enables static
polymorphism and leverages empty-base optimization
• Private inheritance can also be used to implement the composition
relationship (the base class sub object is an implementation detail of the
derived class object).
Use of members to implement composition is also not applicable in the case of
multiple inheritance from a parameter pack or when the identities of the base classes
are determined at compile time through template met programming.
Similar to protected inheritance, private inheritance may also be used for
controlled polymorphism: within the members of the derived (but not within
further-derived classes), derived IS-A base.
Template<type name Transport>
Class service: Transport // private inheritance from the Transport policy
{
Public:
Void transmits () {
This->send (...); // send using whatever transport was supplied
}
};
// TCP transport policy
Class tcp {
Public:
Void send (...);
};
// UDP transport policy
Class udp {
Public:
Void send (...);
};
Service<tcp> service (host, port);
Service. Transmit (...); // send over TCP
Type conversions
Implicitconversion
Implicitconversionsareautomaticallyperformedwhenavalueiscopiedtoa
compatibletype.Forexample:
Short a=2000;
int b;
b=a;
Here, the value of a is promoted from short to int without the need of any explicit
operator. This is known as a standard conversion. Standard conversions affect
fundamental data types, and allow the conversions between numerical types
(short to int, int to float, double to int...), to or from bool, and some pointer.
Converting to int from some smaller integer type, or to double from float is known
as promotion, and is guaranteed to produce the exact same value in the destination
type. Other conversions between arithmetic types may not always be able to
represent the same value exactly:
•
•
•
If a negative integer value is converted to an unsigned type, the resulting
value corresponds to its 2's complement bitwise representation (i.e., 1 becomes the largest value represent able by the type, -2 the second
largest,).
The conversions from/to bool consider false equivalent to zero (for numeric
types) and to null pointer (for pointer types); true is equivalent to all other
values and is converted to the equivalent of 1.
If the conversion is from a floating-point type to an integer type, the value is
truncated (the decimal part is removed). If the result lies outside the range of
represent able values by the type, the conversion causes undefined
behaviour.
•
Otherwise, if the conversion is between numeric types of the same kind
(integer-to-integer or floating-to-floating), the conversion is valid, but the
value is implementation-specific (and may not be portable).
Some of these conversions may imply a loss of precision, which the compiler can
signal with a warning. This warning can be avoided with an explicit conversion.
For non-fundamental types, arrays and functions implicitly convert to pointers, and
pointers in general allow the following conversions:
•
Null pointers can be converted to pointers of any type
Pointers to any type can be converted to void pointers.
Pointer upcast: pointers to a derived class can be converted to a pointer
ofan accessible and unambiguous base class, without modifying
its const or volatile qualification.
Implicitconversionswithclasses
Intheworldofclasses,implicitconversionscanbecontrolledbymeansofthree
memberfunctions:
Single-argument constructors: allow implicit conversion from a particular type
to initialize an object.
•
•
Assignment operator: allow implicit conversion from a particular type on
assignments.
Type-cast operator: allow implicit conversion to a particular type.
For example:
// implicit conversion of classes:
#include <iostream>
Using namespace std;
class A {};
Class B {
Public:
// conversion from A (constructor):
B (const A& x) {}
// conversion from A (assignment):
B& operator= (const A& x) {return *this ;}
// conversion to A (type-cast operator)
Operator A () {return A () ;}
};
Int main ()
{
A foo;
B bar = foo; // calls constructor
Bar = foo;
// calls assignment
foo = bar;
// calls type-cast operator
return 0;
}
The type-cast operator uses a particular syntax: it uses the operator keyword
followed by the destination type and an empty set of parentheses. Notice that the
return type is the destination type and thus is not specified before
the operator keyword.
Keyword explicit
On a function call, C++ allows one implicit conversion to happen for each
argument. This may be somewhat problematic for classes, because it is not
always what is intended. For example, if we add the following function to the
last example:
Void fn (B arg) {}
This function takes an argument of type B, but it could as well be called with an
object of type A as argument:
fn (foo);
This may or may not be what was intended. But, in any case, it can be prevented
by marking the affected constructor with the explicit keyword:
// explicit:
#include <iostream>
Using namespace std;
Class A {};
class B {
Public:
Explicit B (const A& x) {}
B& operator= (const A& x) {return *this ;}
Operator A () {return A () ;}
};
Void fn (B x) {}
int main ()
{
A foo;
B bar (foo);
bar = foo;
foo = bar;
// fn (foo); // not allowed for explicit ctor.
fn (bar);
return 0;
}
B bar = foo;
Type-cast member functions (those described in the previous section) can also be
specified as explicit. This prevents implicit conversions in the same way
as explicit-specified constructors do for the destination type.
Type casting
C++ is a strong-typed language. Many conversions, specially those that imply a
different interpretation of the value, require an explicit conversion, known in C++
as type-casting. There exist two main syntaxes for generic typecasting: functional and c-like:
double x = 10.3;
int y;
y = int (x); // functional notation
y = (int) x; // c-like cast notation
The functionality of these generic forms of type-casting is enough for most needs
with fundamental data types. However, these operators can be applied
indiscriminately on classes and pointers to classes, which can lead to code that while being syntactically correct-, can cause runtime errors. For example, the
following code compiles without errors:
// class type-casting
#include <iostream>
using namespace std;
class Dummy {
double i,j;
};
class Addition {
Int x, y;
public:
Addition (int a, int b) {x=a; y=b; }
Int result () {return x+y ;}
};
int main () {
Dummy d;
Addition * padd;
padd = (Addition*) &d;
cout << padd->result();
return 0;
}
The program declares a pointer to Addition, but then it assigns to it a reference to
an object of another unrelated type using explicit type-casting:
Padd = (Addition*) &d
Unrestricted explicit type-casting allows to convert any pointer into any other
pointer type, independently of the types they point to. The subsequent call to
member result will produce either a run-time error or some other unexpected
results.
In order to control these types of conversions between classes, we have four
specific casting
operators: dynamic_cast, reinterpret_cast, static_cast and const_cast. Their format
is to follow the new type enclosed between angle-brackets (<>) and immediately
after, the expression to be converted between parentheses.
dynamic cast <new type> (expression)
reinterpret cast <new type> (expression)
static cast <new type> (expression)
const_cast <new type> (expression)
The traditional type-casting equivalents to these expressions would be:
(new type) expression
new type (expression)
but each one with its own special characteristics:
Dynamic cast
Dynamic cast can only be used with pointers and references to classes (or
with void*). Its purpose is to ensure that the result of the type conversion points to
a valid complete object of the destination pointer type.
This naturally includes pointer upcast (converting from pointer-to-derived to
pointer-to-base), in the same way as allowed as an implicit conversion.
But dynamic cast can also downcast (convert from pointer-to-base to pointer-toderived) polymorphic classes (those with virtual members) if -and only if- the
pointed object is a valid complete object of the target type. For example:
// dynamic cast
#include <iostream>
#include <exception>
using namespace std;
class Base {virtual void dummy() {} };
class Derived: public Base {int a; };
int main () {
try {
Base * pba = new Derived;
Base * pbb = new Base;
Derived * pd;
Pd = dynamic cast<Derived*> (pba);
If (Pd==0) cout << "Null pointer on first type-cast.\n";
Pd = dynamic cast<Derived*> (pbb);
If (pd==0) cout << "Null pointer on second type-cast.\n";
} catch (exception& e) {cout << "Exception: " << e.what () ;}
return 0;
}
The code above tries to perform two dynamic casts from pointer objects of
type Base* (pba and pbb) to a pointer object of type Derived*, but only the first
one is successful. Notice their respective initializations:
Base * pba = new Derived;
Base * pbb = new Base;
Even though both are pointers of type Base*, pba actually points to an object of
type Derived, while pbb points to an object of type Base. Therefore, when their
respective type-casts are performed using dynamic cast, pba is pointing to a full
object of class Derived, whereas pbb is pointing to an object of class Base, which
is an incomplete object of class Derived.
When dynamic cast cannot cast a pointer because it is not a complete object of the
required class -as in the second conversion in the previous example- it returns
a null pointer to indicate the failure. If dynamic cast is used to convert to a
reference type and the conversion is not possible, an exception of type bad cast is
thrown instead.
Dynamic cast can also perform the other implicit casts allowed on pointers: casting
null pointers between pointers types (even between unrelated classes), and casting
any pointer of any type to a void* pointer.
STATIC_CAST
Static cast can perform conversions between pointers to related classes, not only up
casts (from pointer-to-derived to pointer-to-base), but also downcast (from pointerto-base to pointer-to-derived). No checks are performed during runtime to
guarantee that the object being converted is in fact a full object of the destination
type. Therefore, it is up to the programmer to ensure that the conversion is safe. On
the other side, it does not incur the overhead of the type-safety checks of dynamic
cast.
Class Base {};
class Derived: public Base {};
Base * a = new Base;
Derived * b = static cast<Derived*> (a);
This would be valid code, although b would point to an incomplete object of the
class and could lead to runtime errors if dereferenced.
Therefore, static cast is able to perform with pointers to classes not only the
conversions allowed implicitly, but also their opposite conversions.
Static cast is also able to perform all conversions allowed implicitly (not only those
with pointers to classes), and is also able to perform the opposite of these. It can:
•
•
Convert from void* to any pointer type. In this case, it guarantees that if
the void* value was obtained by converting from that same pointer type; the
resulting pointer value is the same.
Convert integers, floating-point values and enum types to enum types.
Additionally, static cast can also perform the following:
•
•
•
•
Explicitly call a single-argument constructor or a conversion operator.
Convert to revalue references.
Convert enum class values into integers or floating-point values.
Convert any type to void, evaluating and discarding the value.
REINTERPRET_CAST
Reinterpret cast converts any pointer type to any other pointer type, even of
unrelated classes. The operation result is a simple binary copy of the value
from one pointer to the other. All pointer conversions are allowed: neither
the content pointed nor the pointer type itself is checked.
It can also cast pointers to or from integer types. The format in which this
integer value represents a pointer is platform-specific. The only guarantee is
that a pointer cast to an integer type large enough to fully contain it (such
as intptr_t), is guaranteed to be able to be cast back to a valid pointer.
The conversions that can be performed by reinterpret cast but not by static
•
•
•
•
cast are low-level operations based on reinterpreting the binary
representations of the types, which on most cases results in code which is
system-specific, and thus non-portable. For example:
class A { /* ... */ };
class B { /* ... */ };
A * a = new A;
B * b = reinterpret cast<B*>(a);
This code compiles, although it does not make much sense, since now b points to
an object of a totally unrelated and likely incompatible class. Dereferencing b is
unsafe.
CONST_CAST
This type of casting manipulates the constness of the object pointed by a pointer,
either to be set or to be removed. For example, in order to pass a const pointer to a
function that expects a non-const argument:
// const_cast
#include <iostream>
using namespace std;
void print (char * str)
{
cout << str << '\n';
}
int main () {
const char * c = "sample text";
Print (const_cast<char *> (c));
return 0;
}
The example above is guaranteed to work because function print does not write to
the pointed object. Note though, that removing the constness of a pointed object to
actually write to it causes undefined behaviour.
TYPEID
Typeid allows to check the type of an expression:
typeid (expression)
this operator returns a reference to a constant object of type type info that is
defined in the standard header <typeinfo>. A value returned by typeid can be
compared with another value returned by typeid using operators == and! = or can
serve to obtain a null-terminated character sequence representing the data type or
class name by using its name () member.
// typeid
#include <iostream>
#include <typeinfo>
using namespace std;
int main () {
int * a,b;
a=0; b=0;
if (typeid (a) != typeid(b))
{
Cout << "a and b are of different types:\n";
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid(b).name() << '\n';
}
return 0;
}
When typeid is applied to classes, typeid uses the RTTI to keep track of the type of
dynamic objects. When typeid is applied to an expression whose type is a
polymorphic class, the result is the type of the most derived complete object:
// typeid, polymorphic class
#include <iostream>
#include <typeinfo>
#include <exception>
using namespace std;
class Base { virtual void f(){} };
class Derived : public Base {};
int main () {
try {
Base* a = new Base;
Base* b = new Derived;
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid (b).name() << '\n';
cout << "*a is: " << typeid (*a).name() << '\n';
cout << "*b is: " << typeid(*b).name() << '\n';
} catch (exception& e) { cout << "Exception: " << e.what() << '\n'; }
return 0;
}
If the type typeid evaluates is a pointer preceded by the dereference operator (*),
and this pointer has a null value, typeid throws a bad_typeid exception.
Virtual Functions
Virtual Function is a function in base class, which is overrided in the derived class,
and which tells the compiler to perform Late Binding on this function.
Virtual Keyword is used to make a member function of the base class Virtual
Late Binding
In Late Binding function call is resolved at runtime. Hence, now compiler
determines the type of object at runtime, and then binds the function call. Late
Binding is also called Dynamic Binding or Runtime Binding.
Problem without Virtual Keyword
class Base
{
public:
void show()
{
cout << "Base class";
}
};
class Derived: public Base
{
public:
void show()
{
cout << "Derived Class";
}
}
int main()
{
Base* b;
//Base class pointer
Derived d;
//Derived class object
b = &d;
b->show();
//Early Binding Occurs
}
Output : Base class
When we use Base class's pointer to hold Derived class's object, base class pointer
or reference will always call the base version of the function
Using Virtual Keyword
We can make base class's methods virtual by using virtual keyword while
declaring them. Virtual keyword will lead to Late Binding of that method.
class Base
{
public:
virtual void show()
{
cout << "Base class";
}
};
class Derived: public Base
{
public:
void show()
{
cout << "Derived Class";
}
}
int main()
{
Base* b;
Derived d;
//Base class pointer
//Derived class object
b = &d;
b->show();
//Late Binding Ocuurs
}
Output: Derived class
On using Virtual keyword with Base class's function, Late Binding takes place and
the derived version of function will be called, because base class pointer pointes to
Derived class object.
Using Virtual Keyword and Accessing Private Method of Derived
class
We can call private function of derived class from the base class pointer with the
help of virtual keyword. Compiler checks for access specifier only at compile time.
So at run time when late binding occurs it does not check whether we are calling
the private function or public function.
#include
using namespace std;
class A
{
public:
virtual void show()
{
cout << "Base class\n";
}
};
class B: public A
{
private:
virtual void show()
{
cout << "Derived class\n";
}
};
int main ()
{
A *a;
B b;
a = &b;
a -> show();
}
Output: Derived class
Mechanism of Late Binding
To accomplich late binding, Compiler creates VTABLEs, for each class with
virtual function. The address of virtual functions is inserted into these tables.
Whenever an object of such class is created the compiler secretly inserts a pointer
called vpointer.
Important Points to Remember
1. Only the Base class Method's declaration needs the Virtual Keyword, not the
definition.
2. If a function is declared as virtual in the base class, it will be virtual in all its
derived classes.
3. The address of the virtual Function is placed in the VTABLE and the copiler
uses VPTR(vpointer) to point to the Virtual Function.
VirtualFunctionsandRuntimePolymorphisminC++
Considerthefollowingsimpleprogramwhichisanexampleofruntime
polymorphism
#include<iostream>
usingnamespacestd;
classBase
{
public:
virtualvoidshow() { cout<<" In Base \n";
}
};
classDerived: publicBase
{
public:
voidshow() { cout<<"In Derived \n"; }
};
intmain(void)
{
Base *bp = newDerived;
bp->show(); // RUN-TIME POLYMORPHISM
return0;
}
Output:
InDerived
Themainthingtonoteabouttheaboveprogramis,derivedclassfunctionis
calledusingabaseclasspointer.Theideais, virtualfunctions arecalledaccording
tothetypeofobjectpointedorreferred,notaccordingtothetypeofpointeror
reference.Inotherwords,virtualfunctionsareresolvedlate,atruntime.
What is the use?
Virtualfunctionsallowustocreatealistofbaseclasspointersandcallmethods
ofanyofthederivedclasseswithoutevenknowingkindofderivedclassobject.
Forexample,consideraemployeemanagementsoftwareforanorganization,let
thecodehasasimplebaseclass Employee,theclasscontainsvirtualfunctions
like raiseSalary (), transfer (), promote ().etc.
Differenttypesofemployeeslike Manager, Engineer,etcmayhavetheirown
implementationsofthevirtualfunctionspresentinbaseclass Employee.
Inourcompletesoftware,wejustneedtopassalistofemployeeseverywhere
andcallappropriatefunctionswithoutevenknowingthetypeofemployee.For
example,wecaneasilyraisesalaryofallemployeesbyiteratingthroughlistof
employees.Everytypeofemployeemayhaveitsownlogicinitsclass,wedon’t
needtoworrybecauseif raiseSalary () ispresentforaspecificemployeetype,
onlythatfunctionwouldbecalled.
classEmployee
{
public:
virtualvoidraiseSalary()
{ /* common raise salary code */}
virtualvoidpromote()
{ /* common promote code */}
};
classManager: publicEmployee {
virtualvoidraiseSalary()
{ /* Manager specific raise salary code, may
contain
increment of manager specific
incentives*/}
virtualvoidpromote()
{ /* Manager specific promote */}
};
// Similarly, there may be other types of
employees
// We need a very simple function to increment
salary of all employees
// Note that emp[] is an array of pointers and
actual pointed objects can
// be any type of employees. This function should
ideally be in a class // like Organization, we have made it global to
keep things simple
voidglobalRaiseSalary(Employee *emp[], intn)
{
for(inti = 0; i < n; i++)
emp[i]->raiseSalary(); // Polymorphic
Call: Calls raiseSalary() // according to
the actual object, not // according to
the type of
pointer
}
like globalRaiseSalary (),therecanbemanyotheroperationsthatcanbe
appropriatelydoneonalistofemployeeswithoutevenknowingthetypeof
actualobject.
Virtualfunctionsaresousefulthatlaterlanguageslike Javakeepallmethodsas
virtualbydefault.
How does compiler do this magic of late resolution?
Compilermaintainstwothingstothismagic:
vtable: Atableoffunctionpointers.Itismaintainedperclass.
vptr: Apointertovtable.Itismaintainedperobject(See thisforanexample).
Compileraddsadditionalcodeattwoplacestomaintainanduse vptr.
1) Codeineveryconstructor.Thiscodesetsvptroftheobjectbeingcreated.This
codesets vptr topointto vtable oftheclass.
2) Codewithpolymorphicfunctioncall(e.g. bp->show() inabovecode).
Whereverapolymorphiccallismade,compilerinsertscodetofirstlook
for vptr usingbaseclasspointerorreference(Intheaboveexample,sincepointed
orreferredobjectisofderivedtype,vptrofderivedclassisaccessed).
Once vptr isfetched, vtable ofderivedclasscanbeaccessed.Using vtable,
addressofderivedderivedclassfunction show() isaccessedandcalled.
Is this a standard way for implementation of run-time polymorphism in C++?
TheC++standardsdonotmandateexactlyhowruntimepolymorphismmustbe
implemented,butcompilersgenerallyuseminorvariationsonthesamebasic
model.
UNIT V
CONSOLE I/O OPERATIONS
C++ FILES AND STREAMS
So far, we have been using the iostream standard library, which provides cin and
cout methods for reading from standard input and writing to standard output
respectively.
This tutorial will teach you how to read and write from a file. This requires another
standard C++ library called fstream, which defines three new data types:
Data Type Description
ofstream
this data type represents the output file stream and is used
to create files and to write information to files.
This data type represents the input file stream and is used
ifstream
to read
information from files.
fstream
This data type represents the file stream generally, and
has the
capabilities of both ofstream and ifstream which means it
can
create files, write information to files, and read
information from
files.
To perform file processing in C++, header files <iostream> and <fstream> must be
included in
your C++ source file.
Opening a File:
A file must be opened before you can read from it or write to it. Either the
ofstream or fstream object may be used to open a file for writing and ifstream
object is used to open a file for reading purpose only.
Following is the standard syntax for open function, which is a member of fstream,
ifstream, and ofstream objects.
void open (const char * filename e, ios::openm ode m ode);
Here, the first argument specifies the name and location of the file to be opened
and the second argument of the open member function defines the mode in which
the file should be opened.
Mode Flag
Description
ios::app
the end.
Append mode. All output to that file to be appended to
ios::ate
the end
Open a file for output and move the read/write control to
of the file.
ios::in
Open a file for reading.
ios::out
Open a file for writing.
Ios::trunc
If the file already exists, its contents will be truncated
beforeopening the file.
You can combine two or more of these values by them together. For example if
you want to open a file in write mode and want to truncate it in case it already
exists, following will be the syntax:
ofstream out file;
outfile.open ("file.dat", ios::out | ios::trunc);
Similar way, you can open a file for reading and writing purpose as follows:
fstream afile;
afile.open ("file.dat", ios::out | ios::in);
Closing a File
When a C++ program terminates it automatically closes flushes all the streams,
release all the allocated memory and close all the opened files. But it is always a
good practice that a
programmer should close all the opened files before program termination.
Following is the standard syntax for close function, which is a member of fstream,
ifstream, and ofstream objects.
void close ();
Writing to a File:
While doing C++ programming, you write information to a file from your program
using the stream insertion operator << just as you use that operator to output
information to the screen.The only difference is that you use an ofstream or
fstream object instead of the cout object.
Reading from a File:
You read information from a file into your program using the stream extraction
operator >> just as you use that operator to input information from the keyboard.
The only difference is that you use an ifstream or fstream object instead of the cin
object.
Read & Write Example:
Following is the C++ program which opens a file in reading and writing mode.
After writing information inputted by the user to a file named afile.dat, the
program reads information from the file and outputs it onto the screen:
#include <fstream >
#include <iostream >
using name espace std;
int m ain ()
{
char data[100];
// open a file in write mode.
ofstream outfile;
outfile.open("afile.dat");
cout << "Writing to the file" << endl;
cout << "Enter your name
+: "
cin.getline (data, 100);
// write inputted data into the file.
Outfile<< data << endl;
cout << "Enter your age: ";
cin >> data;
cin. Ignore ();
// again write inputted data into the file.
outfile << data << endl;
// close the opened file.
outfile. Close ();
// open a file in read m ode.
ifstream infile;
infile.open("afile.dat");
cout << "Reading from the file" << endl;
infile >> data;
// write the data at the screen.
cout << data << endl;
// again read the data from the file and display it.
infile >> data;
cout << data << endl;
// close the opened file.
infile.close ();
return 0;
}
When the above code is compiled and executed, it produces the following sample
input and Output:
$. /a.out
Writing to the file
Enter your name: Zara
Enter your age: 9
Reading from the file
Zara
9
Above examples make use of additional functions from cin object, like get line
function to read the line from outside and ignore function to ignore the extra
characters left by previous read statement.
File Position Pointers:
Both istream and ostream provide member functions for repositioning the fileposition pointer. These member functions are seekg " seekget " for istream and
seekp " seekput " for ostream.
The argument to seekg and seekp normally is a long integer. A second argument
can be specifiedto indicate the seek direction. The seek direction can be ios::beg
thedefault for positioning relative to the beginning of a stream, ios::cur for
positioning relative to the current position in a stream or Ios::endfor positioning
relative to the end of a stream.
The file-position pointer is an integer value that specifies the location in the file as
a number of bytes from the file's starting location. Some examples of positioning
the "get" file-position pointer are:
// position to the nth byte of file Object (assumes ios::beg)
fileObject.seekg (n);
// position n bytes forward in file Object
fileObject.seekg (n, ios::cur);
// position n bytes back from end of file Object
fileObject.seekg (n, ios::end);
// position at end of file Object
File Object. Seekg (0, ios::end);
File Handling in C++
File Handling concept in C++ language is used for store a data permanently in
computer. Using file handling we can store our data in Secondary memory (Hard
disk).
Why use File Handling
•
For permanent storage.
•
The transfer of input - data or output - data from one computer to another can
be easily done by using files.
For read and write from a file you need another standard C++ library
called fstream, which defines three new data types:
Datatype
Description
ofstream
This is used to create a file and write data on files
ifstream
This is used to read data from files
fstream
This is used to both read and write data from/to files
How to achieve File Handling
For achieving file handling in C++ we need follow following steps
•
Naming a file
•
Opening a file
•
Reading data from file
•
Writing data into file
•
Closing a file
Functions use in File Handling
Function
Operation
open()
To create a file
close()
To close an existing file
get()
Read a single character from a file
put()
write a single character in file.
read()
Read data from file
write()
Write data into file.
Defining and Opening a File
The function open () can be used to open multiple files that use the same
stream object.
Syntax
File-stream-class stream-object;
Stream-object opens (“filename”);
Example
Ofstream out file: //create stream
Out file open (“data 1”) //connect stream to data 1
Closing a File
A file must be close after completion of all operation related to file. For
closing file we need close () function.
Syntax
out file. close ()
File Opening mode
Mode
Meaning
Purpose
ios :: out
Write
Open the file for write only.
ios :: in
read
Open the file for read only.
ios :: app
Appending
Open the file for appending data to end-of-file.
ios :: ate
Appending
take us to the end of the file when it is opened.
Both ios: app and ios: ate take us to the end of the file when it is opened. The difference
between the two parameters is that the ios :: app allows us to add data to the end of file
only, while ios :: ate mode permits us to add data or to modify the existing data anywhere
in the file.
The mode can combine two or more parameters using the bitwise OR operator (symbol |)
Example
fstream file:
file Open (“data. txt”, ios;; out / IOS ;; in);
File pointer
Each file have two associated pointers known as the file pointers. One of them is
called the input pointer (or get pointer) and the other is called the output pointer
(or put pointer). The input pointer is used for reading the contents of a given file
location and the output pointer is used for writing to a given file location.
Function for manipulation of file pointer
When we want to move file pointer to desired position then use these function for
manage the file pointers.
Function
Operation
seekg()
moves get pointer (input) to a specified location.
seekp()
moves put pointer (output) to a specified location.
tellg()
gives the current position of the get pointer.
tellp()
gives the current position of the put pointer.
fout . seekg(0, ios :: beg)
go to start
fout . seekg(0, ios :: cur)
stay at current position
fout . seekg(0, ios :: end)
go to the end of file
fout . seekg(m, ios :: beg)
move to m+1 byte in the file
fout . seekg(m, ios :: cur)
go forward by m bytes from the current position
fout . seekg(-m, ios :: cur)
go backward by m bytes from the current position
fout . seekg(-m, ios :: end)
go backward by m bytes from the end
Put () and get () function
The function put () write a single character to the associated stream.
Similarly, the function get() reads a single character from the associated
stream.
Read () and write() function
These function take two arguments. The first is the address of the variable
V, and the second is the length of that variable in bytes. The address of
variable must be cast to type char * (i.e pointer to character type).
Example
file. read ((char *)&V , size of (V));
file. Write ((char *)&V , size of (V));
Read and Write data from/to File
FilehandlinginC++
#include<iostream.h>
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<fstream.h>
classstudent
{
public:
introll;
charname[15],f_name[20];
voidput();
voidget();
Voidswitchcase();
};students;
voidstudent::put()
{
clrscr();
fstreamfile;
cout<<"Enterrollno:";
cin>>roll;
cout<<"Entername:";
gets(name);
cout<<"Enterfathername:";
gets(f_name);
file.open("stu.dat",ios::out|ios::app);
//file.seekp(0,ios::beg);
file.write((char*)this,sizeof(student));
file.close();
ketch();
s.switch_case();
}
voidstudent::get()
{
inttemp;
clrscr();
cout<"Enterrollno:";
cin>>temp;
fstreamfile;
file.open("stu.dat",ios::in);
file.seekg(0,ios::beg);
while(file.read((char*)this,sizeof(student)));
{
if(roll==temp)
{
cout<<"rollno."<<roll<<endl;
cout<<"stuname:"<<name<<endl;
cout<<"fathername:"<<f_name;
}
}
file.close();
getch();
s.switch_case();
}
voidstudent::switch_case()
{
inti;
cout<<"Enteryourchoice(1-Read,2-Write,3-exit):";
cin>>i;
switch(i)
{
case1:
s.put();
break;
case2:
s.get();
break;
case3:
exit(0);
default:
cout<<"wrongchoice";
}
}
voidmain()
{
clrscr();
s.switch_case();
}
DownloadCode
Output
Enteryourchoice(1-Read,2-Write,3-exit):1
Enterroll_no:1
Entername:Hitesh
Enterfathername:Pandit
Enteryourchoice(1-Read,2-Write,3-exit):2
Enterroll_no.:1
rollno.:1
stuname:Hitesh
fathername:Pandit
Command Line Argument in C++
An executable program that performs a specific task for the operating system is
called a command. The commands are issued from the command prompt of the
operating system. Some arguments are associated with the commands.
Similar to C, in C++, every program starts with a main() function, and this
function marks the beginning of the program. We have not provided any
arguments so far in the main() function. The first argument contains the number of
arguments, and the second arguments are an array of chair pointers.
1.Argument argc:- The argument argc counts the total number of arguments
passed from command prompt.It returns a value that is equal to the total number
of arguments passed through the main().
2. Argument argc:-It is a pointer to an array of character strings that contains
names of arguments.
Syntax – main (int argc, char * argv );
Example-ren file 1 file 2.
Here, file 1and file2 are arguments, and copy is a command .The first arguments
is always an executable program followed by associated arguments.
If any input value is passed through command prompt at the time of running of
program is known as command line argument. It is a concept to passing the
arguments to the main() function by using command prompt.
When Use Command Line Argument
When you need to developing an application for DOS operating system then in
that case command line arguments are used. DOS operating system is a command
interface operating system so by using command we execute the program. With
the help of command line arguments we can create our own commands.
In Command line arguments application main() function will takes two
arguments that is;
•
argc
•
argv
argc: argc is an integer type variable and it holds total number of arguments
which is passed into main function. It take Number of arguments in the command
line including program name.
argv[]: argv[] is a char* type variable, which holds actual arguments which is
passed to main function.
Compile and run CMD programs
Command line arguments are not compile and run like normal C++ programs,
these programs are compile and run on command prompt. To Compile and Link
Command Line Program we need TCC Command.
•
First open command prompt
•
Follow you directory where your code saved.
•
For compile -> C:/TC/BIN>TCC mycmd.cpp
•
For run -> C:/TC/BIN>mycmd 10 20
•
Explanation: Here mycmd is your program file name and TCC is a
Command. In "mycmd 10 20" statement we pass two arguments.
Example of Command Line Argument in C++
#include<iostream.h>
#include<conio.h>
Void main(int argc, char* argv[])
{
int i;
clrscr();
cout<<"Total number of arguments: "<<argc;
for(i=0;i< argc;i++)
{
cout<<endl<< i;<<"argument: "<<argv[i];
getch();
}
}
Output
C:/TC/BIN>TCC mycmd.cpp
C:/TC/BIN>mycmd 10 20
Number of Arguments: 3
0 arguments c:/tc/bin/mycmd.exe
1 argument: 10
2 arguments: 20
Note: In above output we passed two arguments but is show "Number of
Arguments: 3" because argc take Number of arguments in the command line
including program name. So here two arguments and one program name
(mycmd.exe) total 3 arguments.
Example of Command line argument
#include<iostream.h>
#include<conio.h>
void main (int argc, char* argv[])
{
clrscr();
cout<<"\n Program name: \n"<<argv[0];
cout<<"1st arg :\n"<<argv[1];
cout<<"2nd arg :\n"<<argv[2];
cout<<"3rd arg :\n"<<argv[3];
cout<<"4th arg: \n"<<argv[4];
cout<<"5th arg :\n"<<argv[5];
getch();
}
Output
C:/TC/BIN>TCC mycmd.cpp
C:/TC/BIN>mycmd this is a program
Program name : c:/tc/bin/mycmd.cpp
1st arg : this
2nd arg : is
3rd arg : a
4th arg : program
5th arg : (null)
Explanation: In the above example.
Example
argc
= 5
argv[0] = "mycmd"
argv[1] = "this"
argv[2] = "is"
argv[3] = "a"
argv[4] = "program"
argv[5] = NULL
Why command line arguments program not directly run form TC IDE
Command line arguments related programs are not execute directly from TC IDE
because arguments cannot be passed.
Edit Command Line Argument Program
To Edit the Command Line Argument Program use edit Command.
Syntax
C:/cprogram>edit mycmd.cpp
•
Whenever the program is compiled and link we will get .exe file and that
.exe file itself is command.
•
In above example program name is mycmd.cpp so executable file is
mycmd.exe and command name is mycmd.
•
To load the application in to the memory we required to use program name
and command name.
Access data from outside of main
•
argc and agrv are local variables to main function because those are the main
function parameters.
•
According to the storage classes of C argc and argv are auto variable to main
function, so we cannot extend the range of auto variable.
•
By using argc and argv we cannot access command from data outside of the
main function.
•
In implementation when we required to access command from data outside
of the main function then use _argc, _argv variables.
•
_argc and _argv are global variable which is declared in dos.h.
Example
#include<iostream.h>
#include<conio.h>
#include<dos.h>
void abc()
{
int i;
cout<<"data in abc:";
cout<<"Total no. of arguments: ",_argc;
for (i=0;i< _argc;i++)
{
cout<<i+1<<endl<<"argument:"<<_argv[i];
}
}
void main(int argc, char*argv[])
{
int i;
clrscr();
cout<<"\n data in main:";
cout<<"\n total no. of arguments: "<<argc;
for(i=0;i< argc;i++)
{
cout<<i+1<<<<endl"arguments: "<<argv[i];
}
abc();
getch();
}
Download PDF
Similar pages