C++ Basics
C++ Basics
Derived datatypes
void data type in C++: The void data type has no values and no operations.
Integer data types in C++: An integer is a number without a fractional part.
The size of the integer data types are as shown in the table below:
Note: In C++ this size is machine dependent, hence there can be a variation.
Floating point datatypes in C++:
Floating point: A floating point type is a number with a fractional part, such as 43.32. C++ supports
three different sizes of floating point numbers.
The size of the integer data types are as shown in the table below:
Character Datatype in C++: character type can hold an ASCII character .When initializing a
constant or a variable of char type, or when changing the value of a variable of char type, the value
is enclosed in single quotation marks.
Variable Declarations
A constant declaration specifies the type, the name and the value of the constant.
A variable declaration specifies the type, the name and possibly the initial value of the
variable.
When you declare a constant or a variable, the compiler reserves a memory location in
which to store the value of the constant or variable.
Associates the name of the constant or variable with the memory location. In the program
this name is used for referring to the constant or variable.
Constants are used to store values that never change during the program execution.
Declaring Arrays:
To declare an array in C++, the specify the type of the elements and the number of elements as size
required by an array :
Syntax: type arrayName [ 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 Ex: double balance[5];
The above code declare a 5-element array called balance of type double
Initializing an Array:
An array can be initialized along with declaration. For array initialization it is required to place the
elements separated by commas enclosed within braces.
You can initialize C++ array elements either one by one as follows:
You can initialize C++ array elements using a single statement as follows:
The number of values between braces { } can not be larger than the number of elements that we
declare for the array between square brackets [ ].
The above code will create exactly the same array as you did in the previous example.
Accessing Array Elements
In any point of a program in which an array is visible, we can access the value of any of its elements
individually as if it was a normal variable, thus being
able to both read and modify its value. This is done by placing the index of the element within square
brackets after the name of the array. For example:
The above statement will take 5th 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:
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
A structure is one or a group of data elements of different types grouped together under one
name .
A structure is declared in C++ by using the keyword struct using the following syntax
struct structure_name
{
member_datatype1 member_name1;
member_dataype2 member_name2;
..................
};
For example: struct students
{
char studentName[10]; //name of student
int SSN; // social security number
char standard[10];
float score;
}
Accessing the members of a Structure: We can access all the members of a structure by adding
a period after the name of the structure variable name and then the name of the field we want to
access.
There are the two formats to access structure members:
struct_name_variable.member_name // structure
struct_name_pointer->member_name // structure pointer
For example if we create a structure variable of type Student declared above as,
Struct Student newStudent={Renuka,234576,12th,78.5};
The name of the newStudent can be changed as
newStudent.studentName=Renuka Lal;
If a pointer to structure is declared as,
struct Student *studentPtr=&newStudent;
In this case the members can be accessed using the instead of . As folows
studentPtr->newStudent;
1.2.3.2 Union
A union is also a user defined composite datatype like structure.
Unlike structure it enables to store different data types in the same memory location.
A union can be defined with many members, but only one member can contain a value at any given
time.
Unions provide an efficient way of using the same memory location for multi-purpose.
The memory occupied by a union will be large enough to hold the largest member of the union. For
example, in above example
To define a union, you must use the keyword union is used in very similar way like structure. The
syntax of the union declaration statement is as follows:
union union_name
{
member_datatype1 member_name1;
member_dataype2 member_name2;
..................
};
union students
{
char studentName[20]; //name of student
int SSN; // social security number
char standard[10];
float score;
}
Now, a variable of Student type can store either an integer or a floating-point number, or a string of
characters. This means that a single variable ie. same memory location can be used to store
multiple types of data. The memory occupied by a union will be large enough to hold the largest
member of the union. For example, in above example Data type will occupy 20 bytes of memory
space because this is the maximum space which can be occupied by character string.
Accessing the members of a union is same as structure.
Enumaration
Enumerated types used is to create new data types that can take on only a restricted range of
values and these values are all expressed as constants.
When an enumerated type is declared, the name of the new type is specified along with the
possible values it can take on.
Syntax is enum datatype_name {list of values};
For example , enum studentGrade {'A','B','C','D'};
Class
Please refer to the chapter - 2.1 Introduction to OOP concepts
C++ Fundamentals
C++ Overview
C++ was developed by Bjarne Stroustrup starting in 1979 at Bell Labs in Murray Hill, New
Jersey, as an enhancement to the C language and originally named C with Classes but later
it was renamed C++ in 1983.
C++ is a superset of C, and that virtually any legal C program is a legal C++ program.
Note: A programming language is said to use static typing when type checking is performed during
compile-time as opposed to run-time.
Writing first C++ Program
Let us have a look at a sample code in C++ that would print Hello World in the console:
The C++ language defines several headers, which contain information that is either
necessary to your program. For this program, the header <iostream> is needed.
using namespace std; tells the compiler to use the namespace std.
cout << "Hello World."; Displays the message Hello World on screen.
// prints Hello World : Is a single-line comment available in C++. Singleline comments begin
with // and stop at the end of the line
return 0; terminates main()function and return the value 0 to the calling process.
Open a command prompt and go to the directory where you saved the file.
Type 'g++ hello.cpp ' and press enter to compile your code. If there are no errors in your
code the command prompt will take you to the next line and would generate a.out executable
file.
You will be able to see ' Hello World ' printed on the window.
The name of a variable can be composed of letters, digits, and the underscore character. It must
begin with either a letter or an underscore. Upper and lowercase letters are distinct because C++ is
case-sensitive.
A variable declaration tells the compiler where and how much to create the storage for the variable.
A variable declaration specifies a data type, and contains a list of one or more variables of that type
as follows:
Syntax: <datatype> variable_list;
Here, type must be a valid C++ data type including char, int, float, double, bool etc., and variable_list
may consist of one or more identifier names separated by commas. Some valid declarations are
shown here:
You can declare more than one variable of same type in a single statement
The following example shows how variable can be declared an initialized inside the main function:
When the above code is compiled and executed, it produces the following result:
30
23.3333
Scope of Variable
A scope is a region of the program where variables can be declared:
Inside a function or a block which is called local variables,
Outside of all functions which is called global variables.
Local Variables:
Variables that are declared inside a function or block are local variables.
They can be used only by statements that are inside that function or block of code. Local variables
are not known to functions outside their own. Following is the example using local variables:
Global Variables:
Global variables are defined outside of all the functions, usually on top of the program. The global
variables will hold their value throughout the life-time of your program.
A global variable can be accessed by any function. That is, a global variable is available for use
throughout the entire program after its declaration.
Following is the example using global and local variables:
A program can have same name for local and global variables but value of local variable inside a
function will take preference. For example:
When the above code is compiled and executed, it produces the following result:
10
Using Constants in C++
Constants refers to fixed values that program may not alter. They are also called literals.
Any attempt to change the value of a constant will result in an error message. Constants can be of
any of the basic data types and can be divided into Integer constants, Floating-Point constants,
Character constants, String constants and Boolean constants.
Constants are treated just like regular variables except that their values cannot be modified after
their definition.
You can use const prefix to declare constants with a specific type as follows:
Syntax: <const type> variable = value;
Following example explains it in detail:
When the above code is compiled and executed, it produces the following result:
15
A
Conditional Structures
Objective
If Statement
If .. Else Statement
Nested if statement
If Statement
If statement can be use to evaluate conditional statements. Based on the result of evaluation one of
more statements can be executed
syntax of the if statement
if(condition)
{
statement(s) if condition evaluates to true;
}
Statements are executed if the condition is true. No output if the condition false.
if .. else statement
To perform some action in either of the situation based on the conditional evaluation if.. else
construct can be used.
syntax of the if..else statement
if(condition)
{
statement(s) if condition evaluates to true;
}
else
{
statement(s) if condition evaluates to false;
}
Note: If only one statement is there after the condition, {} are not required
if (condition)
statement;
else
statement;
If .. elseif ..else statement
Using if...elseif...else multiple condition can be evaluated.
syntax of the if statement
if(condition)
{
statement(s) if condition evaluates to true;
}
else if (condition2)
{
statement(s) if condition2 evaluates to true;
}
else
{
statement(s) if none of the above conditions are true;
}
Note: If only one statement is there after the condition, {} are not required
Consider the following example:
#include<iostream>
using namespace std;
int main()
{
int Size;
char Type;
cout<<Enter TV Size [20/30] :;
cin>>Size;
if(Size==20)
cout<< Discount = 10% <<endl;
else
{
cout<< Enter TV Type [ C:CRT / L:LED] : ;
if(Type=='C')
cout<< Discount= 15 % <<endl;
else
cout<< Discount= 20 % <<endl;
}
return 0;
}
Nested If statements
To evaluate multilevel conditional statements, If statements can be placed within another if/else
block.
Consider the following example:
#include<iostream>
using namespace std;
int main()
{
int Age;
cout<<Enter Age ;
cin>>Age;
if(Age<13)
cout<< Child <<endl;
else if(Age<18)
cout<< Teen <<endl;
else if(Age<40)
cout<< Young <<endl;
else if(Age<55)
cout<< Middle Aged<<endl;
else
cout<< Old<<endl;
return 0;
}
Switch-case statements
The other way conditional evaluation can be performed using switch statement which permits
multiple branching:
The syntax of switch statement is:
switch (var / expression)
{
case constant1 :
statement 1;
break;
case constant2 :
statement 2;
break;
...
default:
statement n;
break;
}
The execution of switch statement begins with the evaluation of expression. If the value of
expression matches with the constant then the statements following this statement execute
sequentially till it reaches the break statement. 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.
The default case need not to be used at last case. It can be placed at any place.
The while iterative construct is called a entry-controlled (pre-testing) looping. It evaluates the
logical expression for exit of the loop at the beginning.
If the logical expression in the while loop evaluates to true, then the statements associated
with the loop are executed. If the logical expression evaluates to false, then the statements
associated with the loop are not executed.
Since the test for exit of the loop is performed before the first instruction in the loop, based
on the condition it may not execute for a single time.
The variables appearing in the logical expression are initialized (assigned a value) prior to
the beginning of the while loop. This is necessary since the logical expression in the while
loop is tested before the actual loop is executed.
int main()
{
int Counter;
Counter=1;
// initialization of counter
while(Counter<=10)
// Test Expression
{
cout<<Counter<< ;
Counter = Counter + 2; // increment of counter
}
return 0;
}
Output : 1 3 5 7 9
do..While iterative construct
The do ... while iterative construct is called a exit-controlled (post-testing) loop. It evaluates
the logical expression for exit of the loop at the end.
First, the statements associated with the loop are executed, at the end of first execution the
logical expression is evaluated if the expression evaluates to true, then it re-executes, else
the statements associated with the loop are not executed.
Since the test for exit of the loop is performed end of the loop body, whatever the condition is
the loop body will executed at least once
The variables appearing in the logical expression are initialized (assigned a value) prior to
the beginning of the while loop. This is necessary since the logical expression in the while
loop is tested before the actual loop is executed.
For looping construct is known for its neat and clean syntax. Unlike other loop in for loop all three
loop controlling statements (initialization, test condition and increment/decrement) are clearly
mentioned in the first line of it.
The general syntax is:
for( initialization; test condition; increment/decrement)
{
// statements to be executed in the body of the loop
}
The following example accepts a number and prints the table of that number
#include<iostream>
using namespace std;
int main()
{
int Ctr,Num;
cout<< Enter a number : ;
cin>>Num;
for(Ctr=1;Ctr<=10;Ctr++)
{
cout<< Num << * <<Ctr<< = <<Num*Ctr <<endl;
}
return 0;
}
Output :
Enter a Number : 9
9*1 = 9
9 * 2 = 18
9 * 3 = 27
9 * 4 = 36
9 * 5 = 45
9 * 6 = 54
9 * 7 = 63
9 * 8 = 72
9 * 9 = 81
9 * 10 = 90
Break Keyword
In the program flow when break statement encountered it terminate a loop or an switch block,
skipping the following statements in the block.
Continue Keyword
In the program flow when continue statement encountered it re-starts a loop, skipping the following
statements in the block.
The following program prints even numbers upto 8
#include<iostream>
using namespace std;
int main()
{
int Ctr;
for(Ctr=1;Ctr<=20;Ctr++)
{
if(Ctr%2!=0) continue;
if(Ctr==10) break;
cout<< Ctr <<endl;
}
return 0;
}
The output of the code is :
2
4
6
8
Operators
Objective
Understand operator
Type Of Operators
An operator is a symbol that tells the compiler to perform specific mathematical or logical
manipulations on variables or values. C++ is rich in built-in operators and provides the following
types of operators:
Arithmetic Operators
Logical Operators
Arithmetic Operators
Arithmetical operators are used to perform an arithmetic (numeric) operation on variables and
values.
Assume variable A holds 10 and variable B holds 20, then:
Example:
#include<iostream>
using namespace std;
int main()
{
int a=10,b=20;
cout<<"Addition:"<<a+b<<endl;
cout<<"Division:"<<b/a<<endl;
cout<<"Multiplication:"<<a*b<<endl;
cout<<"Modulo:"<<b%a<<endl;
return 0;
}
Output:
Addition:30
Division:2
Multiplication:200
Modulo:0
Comparison Operators
The comparison or relational operators are used to test the relation between two values. All
comparison operators are binary operators and therefore require two operands. A relational
expression returns zero when the relation is false and a non-zero when it is true.
Assume variable A holds 10 and variable B holds 20, then:
Example:
#include<iostream>
using namespace std;
int main()
{
int a=10;
int b=20;
bool c= a < b;
cout<<"Result is"<<c;
return 0;
}
Output:
Result is 1
Arithmetic Assignment Operators
Arithmetic Assignment operators are combination of both Arithmetic and Assignment Operators. It
assigns value to variable after arithmetic operation.
Example:
#include<iostream>
using namespace std;
int main()
{
int a=10;
a+=1;
cout<<"Value of a:"<<a;
return 0;
}
Output:
Value of a:11
Logical Operators
The logical operators are used to combine one or more relational expression.
Assume variable A holds 1 and variable B holds 0, then:
Example:
#include<iostream>
using namespace std;
int main()
{
int a=10;
int b=20;
int c=30;
bool x= (a < b) && (a < c);
cout<<"C is Largest Number:"<<x;
return 0;
}
Output :
C is Largest Number: 1
Unary Operators
Operators that operates on single operand are named as unary operators.
C++ provides unary operators like ++ ( increment) and (decrement) .
Increment(++) operator increments the value present in a variable by 1.
Decrement(- -) operator decrements the value present in a variable by 1.
Unary operators an operate from two different position
>> pre-fix when operator placed before a variable. For example (++Count)
>> post-fix when operator placed after a variable. For example(Count++)
The difference in result is explained in the following example.
#include<iostream>
using namespace std;
int main()
{
int a=10;
a++;
cout<<a<<endl;
a--;
cout<<a<<endl;
// prints 11
// prints 10;
b=++a;
//pre-fix , so a incremented first
cout<<a<<endl // prints 11;
cout<<b<<endl // b gets the incremented value
// prints 11.
a=10;
// a value reset to 10
b=a++;
// post-fix, so assignment first
cout<<a<<endl; // prints 11
cout<<b<<endl; // prints 10;
return 0;
}
Sometimes, binary operators can act as unary operator.
a=-50;
a=+50;
Here plus sign (+) and minus sign (-) are unary because they are not used between two variables.
Ternary Operator
The C++ programming language provides another Boolean operator that can be
extremely useful in certain situations: the ?: operator.
The ?: operator is written in two parts and requires three operands. The general form of the
operation is
(condition) ? exp1 : exp2
When a C++ program encounters the ?: operator, it first evaluates the condition. If the condition
turns out to be true, exp1 is evaluated and used as the value of the entire expression if the condition
is false, the value is the result of evaluating exp2.
For example, we can use the ?: operator to assign to max either the value of x or the value of y,
whichever is greater, as follows:
max = (x > y) ? x : y;
Operator precedence and associativity
Operator precedence determines which operator will be performed first in a group of operators with
different precedences.
For example , the expression , 5 + 3 * 2 is calculated as 5 + (3 * 2), giving 11, and not as (5 + 3) * 2,
giving 16.
The operator associativity rules define the order in which adjacent operators with the same
precedence level are evaluated.
For example , the expression 8 - 3 - 2 is calculated as (8 - 3) - 2, giving 3, and and not as 8 - (3 - 2),
giving 7. In this case we say that subtraction is left associative meaning that the left most subtraction
must be done first.
Following table shows the operator precedence and associativity:
Understanding Functions
Function Prototyping
Function Definition
Function Calling
Pre-Defined Functions
Understanding Functions
The function is a self contained block of statements which performs a coherent task of same kind.
It is required to invoke or call functions. When a function is called in a program, the program control
goes to the function body. Then, it executes the statements which are involved in a function body.
Therefore, it is possible to call function whenever we want to pro cess the statements in the
function.
Types of Functions
There are two types of functions as:
Built in Functions
Built in Functions also called as 'library functions' are the functions are the functions provided by
system. These functions are stored in library files.
e.g. cout, cin, maths functions, power()
User defined functioons are the functions defined by the user.
The advantage of creating functions are
>> To make the program more understandable
>> To modularize the tasks of the program
>> Write a module once use several time
Function Prototype
Functions should be declared before they are used. The declaration of a function is called function
prototype. Function prototype gives compiler information about function name, type of arguments to
be passed and return type.
The typical syntax for function prototyping is:
return_type function_name(datatype1 [,datatype2...] );
For example,
int add(int, int);
Swap(Num1,Num2);
cout<< After swap in main;
cout<< 1st Num= <<Num1<< ; 2nd Num=<<Num2;
return 0;
}
void Swap(int a,int b)
{
int c=a;
a=b;
b=c;
cout<< After swap in swap;
cout<< 1st Num= <<a<< ; 2nd Num=<<b;
}
Output :
Enter two Numbers: 20 30
After swap in swap 1st Num= 30; 2nd Num=20;
After swap in main 1st Num= 20; 2nd Num=30;
Call by reference means to pass the reference of an argument in the calling function to the
corresponding formal parameter of the called function. The called function can modify the value of
the argument by using its reference passed in. The arguments in the function are declared as a
reference variable, hence when the function is called, the value of the arguments are not copied to
the formal parameter. Formal parameters are used as a reference.
For example,
#include<iostream>
using namespace std;
void Swap(int &,int &);
int main()
{
int Num1,Num2;
cout<< Enter two Numbers :;
cin>>Num1>>Num2;
Swap(Num1,Num2);
cout<< After swap in main;
cout<< 1st Num= <<Num1<< ; 2nd Num=<<Num2;
return 0;
}
void Swap(int &a,int &b)
{
int c=a;
a=b;
b=c;
cout<< After swap in swap;
cout<< 1st Num= <<a<< ; 2nd Num=<<b;
}
Output :
Enter two Numbers: 20 30
After swap in swap 1st Num= 30; 2nd Num=20;
After swap in main 1st Num= 30; 2nd Num=20;
The call by pointer method of passing arguments to a function copies the address of an argument
into the formal parameter. Inside the function, the address is used to access the actual argument
used in the call. This means that changes made to the parameter affect the passed argument.
For example the function definition to swap the values.
void swap(int *x, int *y)
{
int temp;
temp = *x; /* save the value at address x */
*x = *y; /* put y into x */
*y = temp; /* put x into y */
return;
}
Pre-Defined Functions
In C++ language there are many pre-defined functions available which are grouped in different
libraries that can be included in the C++ program, e.g.
>> Math functions are declared in <math.h>
>> Character-manipulation functions are declared in <ctype.h>
>> The string function are declared in <cstring.h>
Some of the math and character functions are listed below:
Pointers in C++
Objective
Concept of Pointers
Declaration of Pointer
Pointer Arithmetic
Concept of Pointers
When we declare a variable such as
char Grade='A';
A memory location is allocated to the program which is reffered by a name Grade, and value stored
in the memory location is the charecter A.
The value of the variable can be accessed by some other way, with the help of the address of the
variable, using pointer.
A pointer is a special type of variable that can store other variable's address. An address of a
variable can be extracted by ampersand (&) operator
Declaration of Pointers
char *Ptr; // A pointer declared that can store
// address of a char type variable
Ptr = &Grade; // Pointer Ptr is now
//pointing (storing the address of ) variable Grade
cout<< Grade; // Prints A, accessing value of variable Grade
Pointer Arithmetic
It is possible to perform certain arithmetic operations on pointers.
Consider a pointer declaration:
char *Ptr=&x;
It is possible to add and subtract numbers from the pointer as below:
Ptr = Ptr + 1 ; // Ptr now pointing
//value present in next address
Ptr--;
*Ptr++
++*Ptr
int *ptr2=&var2;
int sum=ptr1* ptr2 , will produce compilation error.
NOT operation.
ptr=NULL:
Pointer To Pointer
We can create a pointer for any variable we define. We can create a pointer to an int,to a char, or to
any structure we create. Similarly. We can create a pointer to a pointer.
Pointer is a variable which holds the address of some other variable .A pointer to a pointer is a form
of multiple indirection or a chain of pointers.
When we define a pointer to a pointer, the first pointer contains the address of the second pointer,
which points to the location that contains the actual value as shown below.
Declaration of a pointer to pointer
int **ptr;
int *ptr1, int var1;
ptr1=&var1;
ptr=&ptr1;
To understand what is good programming practise and what is the use of practising the
same
1.2 Introduction
Good programming practices are techniques that a programmer can follow to create the best code
or program. Some rules need be followed to facilitate both initial development and subsequent
maintenance and enhancement of a software by people other than the original authors.
Good programming practices are programming practices, that cover everything from making a code
more readable, modification in code becomes easy.
In industries, software engineering teams often follow a style guide to maintain a consistency among
software projects to enforce a discipline which improves the quality of software, reusability , fewer
bugs and easier to use and maintain.
The attributes associated with good software are:
Maintainability
Dependability
Efficiency
Usability
Comment your code such that it is clear what the code does.
You should be able to figure out your code years after its written.
A good programmer should be able to figure out what your code does from your comments.
You should also include notes on what a particular chunk of code does if it may be confusing
to a reader.
To implement this GPP, we should include contract, purpose, example and assumptions and
test cases in functions or procedures.
For example:
/* Contract:summationOfThreeNumbers:number number number----->number
Purpose : To find the summation of three numbers.
Example : summationoOfThreeNumbers(20,10,30)---->expected output is 60
Assumption: The input numbers should be positive and less than equal to 100.
In case of invalid input, the function will return -1.
Header : summationOfThreeNumbers(int number1,int number2,int number3)....
Test cases: summationOfThreeNumbers(10,20,30)------>expected output 60
summationOfThreeNumbers(-10,20,30)------>expected output -1
summationOfThreeNumbers(200,10,20) ----->expected output -1
*/
Naming convention
While naming an identifier (variable,function, constsnt etc...).
Use a consistent style regarding lower and upper case letters.
1) In case of variables ,functions and procedures , the name should be in lower case and in case a
variable name has more than one word, the first letter of the second word should be in upper case.
For example: score. personAge, employeeBasicSalary
2) Class name should start with a upper case letter and should be a noun phrase
Example : Person, Student, StudentRegister
3) Function or procedure name and the names of methods in a class should be a verb phrase.
Example: findSum,calculateSalary,registerEmployee etc..
4) In case of OOP, the file name having a class declaration or definition should reflect the class
name. While the class name typically starts with a capital letter, the header file and source files
typically begin with lower case letters.
For example, file classBase.h will contain the declaration of the class ClassBase{} and
classBase.cpp will contain the definition to it's functions.
5) Initialize variables at the time of declaration.
6) Remove any unused variables in the program.
Use variable names that have substantive meaning.
Should select a variable name so that it communicate the named object's purpose to the reader.
Should avoid one character identifier.
For Example, to store the age of a person, personAge instead of a or ag .
Clarity
To enhance the readability of the code proper indentation is must.
For clarity,
Indent each level of code.
Use appropriate white-space in programs, and do so in a consistent fashion to make them easy to
read.
Use proper indentation for loops so that reader can easily read it.
Where ever required, use paranthesis.
For Example:
When referring to an include file within either another include file or source file, do not nclude
the full path to avoids portability problems created by operating system dependent methods
of referencing directory paths. Use compiler command line flags to include the path. (i.e.
-I/path-name)
Split classes into a header file(.h) and source file(.cpp). Header file contains the class
declaration, along with the declarations of its member functions, without the implementations
of those functions. Put the implementations into a separate .cpp file which can be compiled
and linked separately. .
Divide the program into sub programs or functions and each sub program should perform
only one task.
1.3.5 Simplicity
The code that a programmer writes should be simple. Complicated logic for achieving a simple thing
should be kept to a minimum since the code might be modified by another programmer in the future.
The logic one programmer implemented may not make perfect sense to another. So, always keep
the code as simple as possible.
Register : When we need variables for quick access , this storage class is used. Register storage
class is used to define local variables that should be stored in a register instead of RAM. As registers
are faster than RAM, the access to these variables will be as fast as possible. The keyword register
is used to declare a register variable and these variables are like automatic variables, local to the
function in which they are declared. Defining certain variables to be register variables does not,
however, guarantee that they will actually be treated as register variables. Registers will be assigned
to these variables by compiler so long as they are available. If a register declaration cannot be
fulfilled, the variables will be treated as automatic variables.
For example: register int counter=0;
Static : If we want to declare a variable whose lifetime schould be the lifetime of the program, we
should use static storage class. static is the keyword used to declare a static variable.
The static storage class instructs the compiler to keep a local variable in existence during the lifetime
of the program instead of creating and destroying it each time it comes into and goes out of scope.
Therefore, making local variables static allows them to maintain their values between function calls.
Static variables are local variables that retain their values throughout the lifetime of the program. In
other words, their same (or the latest) values are still available when the function is re-invoked later.
Their values can be utilized within the function in the same manner as other variables, but they
cannot be accessed from outside of their defined function. If the static modifier is be applied to global
variables, it causes that variables scope to be restricted to the file in which it is declared.In C++,
when static is used on a class data member, it causes only one copy of that member to be shared by
all objects of its class.
For example:
Let us consider a code snippet as follows:
#include <iostream.h>
void addOne();
void main()
{
addOne();
addOne();
addOne();
}
void addOne ()
{
static int number= 0;
number++;
Error
An error typically refers to a problem that exists in a program when it is written and compiled. It could
be a logic error that will result in incorrect results. In this case, the code is correct but the algorithm
has an error.
Exception
Exceptions are errors or anomalies that occur during the execution of a program. They can be the
result of unavailability of system resources, such as memory, file space, channels or from data
dependent conditions such as a divide by zero, or numerical overflow. Exceptions tend to be rare
events but are predicable.
Exception Handling
Given that exceptions are somewhat predicable, next question is how should our programs handle
them?
Broadly, there are three types of responses we can take
Not handle the exception. Allow the program to die or core dump.
Issue a warning. Print out some type of error message, probably at the spot in the code
where the exception occurred and then exit.
Next question we may have is should the same section of code be raising the exception and
handling the exception?
Suppose an exception occurs in allocating memory. Possibilities can be,
Should the function or method that attempted the allocation be the one to handle it? Can it?
Probably some other, higher level, section of code will have the information necessary to
decide how to handle the exception.
May be different programs using the same classes and methods will handle exceptions
differently.
This points to a separation of the creation of an exception and its handling. The method in which an
exception occurs could just alert its caller. This allows code that raises exceptions to be developed
separately from code that handles them. If we pass exceptions up to calling routines, it is necessary
to have a way to bundle information.
The C++ exception mechanism handles both these features.
Any object, including class objects may be passed back to the handler of an exception.
These objects can contain data and methods to assist in handling the exception.
The section of code that causes or detects a run-time abnormality (divide by zero, out of
memory) will "throw" an exception. The exception is the object that is thrown.
The exception is "caught" by another section of code. The exception object, itself, is used to
convey information from the section of code that throws the object to the section of code that
catches the object.
throw: A program throws an exception when a problem shows up.This is done using a
throwkeyword.
catch: A program catches an exception with an exception handler at the place in a program
where you want to handle the problem. The catch keyword indicates the catching of an
exception.
try: A try block identifies a block of code for which particular exceptions will be activated. It's
followed by one or more catch blocks.
Assuming a block will raise an exception, a method catches an exception using a combination of
thetry and catch keywords. A try/catch block is placed around the code that might generate an
exception. Code within a try/catch block is referred to as protected code, and the syntax for using
try/catch looks like the following:
For example :
The exception thrown in this example is of type int and the catch block contains logic to decode this
value and print an appropriate error message.
This is bad design because it requires the catch block and its programmer to implement possibly
complex logic and to be aware of possible exception codes.
An exception can be any type of object. Since we can throw any type of object, let's try throwing the
error message string itself, rather than an exception code.
For Example,
This is a better approach . The catch block no longer needs detailed knowledge about the
exception. The piece of code that throws the exception is passing details of the exception also, in
this case an error message. Now suppose that we need to bundle a message, and exception code,
and the values of some of the variables within the exception. A user-defined exception class can be
used in this case.
Using a class object as an exception is standard for C++. Let's see how it's done.
#include <iostream>
#include <string>
using namespace std;
//Exception class
class DivideByZero {
public:
DivideByZero(int n, int d) : num(n), denom(d), message("Divide by zero") {}
~DivideByZero() {}
int getNumerator() {return num;}
int getDenominator() {return denom;}
string getMessage() {return message;}
private:
int num;
int denom;
string message;
};
//main () from where exception is thrown
int main()
{
int x = 5;
int y = 0;
int result;
try {
if (y == 0) {
throw DivideByZero(x, y);
}
result = x/y;
}
catch (DivideByZero e) {
cout << e.getMessage() << endl;
cout << "Numerator: " << e.getNumerator() << endl;
cout << "Denominator: " << e.getDenominator() << endl;
}
cout << "Goodbye" << endl;
return 0;
int main()
{
int x = 5; int y = 0;
int result;
try {
if (y == 0) {
throw DivideByZero(x, y);
}
result = x/y;
}
catch (DivideByZero e) {
cout << e.getMessage() << endl;
cout << "Numerator: " << e.getNumerator() << endl;
cout << "Denominator: " << e.getDenominator() << endl;
}
cout << "Goodbye" << endl;
return 0;
}
Another Example Stack Class
In order to further demonstrate the use of exceptions in C++, we will develop and use a simple stack
class. Data is "pushed" onto the stack and "popped" off.
Our stack will have the following limitations.
It will be of fixed size.
It will throw a stack overflow exception if an attempt is made to push data onto a
full stack.
It will throw a stack empty exception if an attempt is made to pop data off an empty stack.
#include <iostream>
#include <string>
int pop()
{
if (index < 0)
{
throw StackEmptyException();
}
int val = data[index];
index--;
return val;
}
private:
int data[20];
int index;
};
int divide(int num, int den)
{
if (den == 0)
{
throw DivideByZero(num,den);
}
return num/den;
}
int main()
{
CrudeStack stack;
int num; int den; int val;
cout << "Enter num: ";
cin >> num;
cout << "Enter den: ";
cin >> den;
try {
stack.push(num);
stack.push(den);
divide(num, den);
val = stack.pop();
cout << "popped " << val << endl;
val = stack.pop();
cout << "popped " << val << endl;
val = stack.pop();
cout << "popped " << val << endl;
}
catch (StackOverflowException e) {
e.getMessage();
}
catch (StackEmptyException e) {
e.getMessage();
}
catch (DivideByZero e) {
e.getMessage();
}
catch (...) {
In the code main calls functionA and that functionA calls functionB.
FunctionB will throw two exceptions, ExceptionType1 and ExceptionType2.
The flow is as follows
Since functionB is passed a value less that zero, an exception of type ExceptionType1 is
thrown.
Since no exceptions are caught in functionB, execution jumps out of functionB back to
functionA.
FunctionB's variables are removed from the stack and any destructors for local objects are
called. This is unwinding the stack.
We are now in functionA. Again, it does not catch the exception, so its variables are removed
from the program stack.Any destructors for local objects are called.
The stack is further unwound. Now, we have reached main. Here, the exception is caught
and handled.
What would happen if main didn't catch the exception? This is the case with ExceptionType2.
Main's variables would be removed from the stack and any destructors would be called.
Since no handler is found, the terminate() system function is called and the program aborts.
This default is undesirable. Attempts should be made to catch and handle all exceptions.
A list is given as
Then, at each step, the insertion sort takes the first item of the unsorted region and places
it into its correct position in the sorted region.
Using linear search, find the location in the sorted portion where the 1st element of the
unsorted portion should be inserted .
Move all the elements after the insertion location up one position to make space for the
new element
A list is given as
5 2 4 6 1 3
At each iteration, the list is divided in two sub-lists:
The approach is
Start at first item
Check if it is the item looked for
If not go to next item
Repeat until found or all items checked
For example, When you pick-up a telephone directory to find the name "Vijay", open it to the first
page of names, then look at the first name. Is it "Vijay"? Probably not (it's probably a name that
begins with 'A'). Now look at the next name. Is it "Vijay"? Probably not. Keep looking at the next
name until you find "Vijay".
Note : If the list of items is not sorted or is not sortable this approach is necessary.
Advantages:
The advantage of linear search is
Simple
Easy to understand.
Easy to implement.
Does not require the list to be in order.
Disadvantage: Inefficient (slow), for a list of N elements, examines N/2 elements on average for
value that is found in the list, N elements for value that is not in the array.
To analyse the efficiency of any algorithms, we need to decide on a basic unit of computation, that
is , the common step that must be repeated in order to solve the problem. For searching, it is the
count of comparisons performed. Each comparison may or may not discover the item looked for. In
addition, another assumption is, the list of items is not ordered in any way. The items have been
placed randomly into the list. In other words, the probability that the item looked for , is in any
particular position, is exactly the same for each position of the list.
1.2.2.2 Introduction To Binary Search
Binary search or half-interval search algorithm locates the position of an item in a sorted list of
items .
Binary search works as follows:
It requires the list to be in order .
The algorithm starts searching with the middle element.
If the item searched for is less than the middle element, it starts over searching the first half of the
list.
If the item searched for is greater than the middle element, the search starts over starting in the
second half of the list.
It then continues halving the list until the item is found.
Advantage : Much more efficient than linear search. For list of N elements, performs at most log2N
comparisons
Disadvantage : Requires that list of elements be sorted
Hardware Gives, just a bunch of uniform, individually addressable storage elements. How to bridge
the gap between the abstractions? Answer is ,use Data Structure.
Data structure is an agreement about:
Thus , data structure is the way how your data will be organized and arranged in your computer's
memory.
There are many data structure techniques that can be used such as
Arrays,
Linked Lists,
stacks,
queues,
trees,
graphs etc.
However,all the above data structure techniques have different reasons of use. Some common
example of applications of Data Structure are:
How does Google quickly find web pages that contain a search term?
How can a sub sequence of DNA be quickly found within the genome?
How does your operating system track which memory (disk or RAM) is free?
In the game Half-Life, how can the computer determine which parts of the scene are
visible?
1.2.2 Array
Array represents a
Arrays are used when the amount of memory to be allocated is already known in advance as arrays
are always statically allocated and also contagiously allocated in memory.
Advantages of using array are:
A list with zero nodes is an empty list and the head pointer points to NULL.
Advantages of a linked list are :
Dynamic structure.
Insertion deletion is easy.
Allocates memory dynamically.
Limitations of a linked list are:
Accessing node is difficult.
Extra space is required for references or links.
Representation of Linked list in memory
consists of memory blocks (representing nodes) that are located at random memory blocks.
blocks/nodes are connected through pointers.
a block/node is represented through structure.
nodes are created by allocating memory to structures
Representation Of A Node:
a) As a structure :
structure Node { data type data;
struct Node *next;
};
e.g struct Student{ int rollNumber;
char name[10];
struct Student *next;
};
b) As a class : class Node{ data type data/element;
Node next;
};
e.g class Student{ int rollNumber;
string name;
Student nextStudent ;
};
Real Example of Use of Linked list
Create another node and the address of this node is assigned to the next field of the previously
created node. Assign NULL to the field next of the new node.
List As a Class:
Knowing responsibilities:
- Knows the head
- Knows the size
Doing responsibilities:
- Insert node
- Find node
- Delete node
- Find list size
Check list is empty or not
class LinkedList
{
Node head;
// head node of the list
long size;
// number of nodes in the list
// Default constructor that creates an empty list
public :
LinkedList()
{
head = NULL;
size = 0;
}
// Other Methods
.
..
};
Traversing A List
head points to the first node of the list.
- follow the pointers.
- display the contents of the nodes as they are traversed.
- stop when the next pointer points to NULL.
Inserting a node
To insert at the beginning
The next pointer of the item immediately preceding the one to be deleted is altered, and
made to point to the item following the deleted item.
};//end of class
int
A doubly linked list with nodes to store strings. can be defined as:
class DList
{
int size;// number of elements
Node head, tail;
public:
void addFirst(Node n);
void addLast(Node n);
Node deleteFirst();
Node deleteLast();
void delete(Node n);
}
Effeciency of different operations on a doubly linked list :
addFirst()
O(1) time
addLast()
O(1) time
deleteFirst() O(1) time
deleteLast() O(1) time
delete()
O(1) time
get(i)
O(i) time
1.2.3.1.1 Traversal In a Doubly Linked List
When traversing a doubly-linked list to prepare for insertion or deletion, there is no need to use both
a current and previous reference, each node has a built-in reference to the previous element.
1.2.3.1.2 Insertion Of a Node in a Doubly Linked list
1.2.3.1.3 Insert at the head
Original Doubly linked list:
After inserting a new node (E) at the head i.e. before A node:
As seen above, highlighted arrow between Head and A show the original
i.e. before adding E node.
As seen above, highlighted arrow between B and C shows the original link between B and C (i.e.
before adding O node).
to
Set next of new node point to what the node after which new node is to be insert eds next points
Set previous of the node that will be next to the new node to new node
Set previous of new node point to the node after which it I to be inserted
Set next of the node which precedes the new node point to new node.
As seen above, highlighted arrow between B and tail shows the original link between B and tail (i.e.
before adding O node).
As seen above, highlighted arrow between Head and A and A and B shows the original link
between head, A and B (i.e. before deleting A).
Set the next of the head to the node, the next of the node heads next points to.
Set the previous of the node which point to the node heads next points to, to the head
Set next of the node which is pointed by the previous of the node tails previous points to .
Set previous of the tail to the node , previous of the node tails previous points to.
As seen above, highlighted arrow between A and B and B and C shows the original link between
A,B and C (i.e. before adding B node).
Set next of the node pointed by the previous of the node to be deleted to the node the next of the
node to be deleted points to.
Set the previous of the node which point the node to be deleted to the node pointed by the
previous of the node to be deleted.
1.2.3.3 Circular linked list
In a circular linked list the pointer from the last node in the list points back to the first node.
Circular linked lists can be used to help the traverse the same list again and again if required.
The definition of the structure or class to represent a node is same as linear list. Primitive functions
in circular lists like insert , delete are are almost the same as linear list.
Basic operations in a circular linked list are:
Initialize list (to an empty state)
Find if list is empty
Destroy list,
Print list
Find the list length
Search for a given element
Insert item
Delete item,
Copy the list
Stack
Stack is a specialized data storage structure of Abstract data type.
In stack data is added and removed at only one end called the top.
It has two functions push ,to add an item to the stack and pop, to remove an item from the stack.
The last element that is pushed into the stack, is the first element to be popped out of the stack.
i.e., Last In First Out (LIFO).
Capacity of a stack stands for the maximum number of elements stack can hold.
Size of a stack stands for the current size of the stack .
Elements in the array / list of elements.
Application Of Stack
a) Real life applications
Pile of books, pile of plates etc.
Queue
A queue is an ordered list in which all insertions take place at one end, the rear, while all deletions
take place at the other end, the front.
Applications Of Queue
a) Real-world Applications:
Check-out lines.
Escalators.
Coin dispensers.
Vending machines.
Call center phone systems.
b) Application in Computer Science:
In operating systems, for controlling access to shared system resources such as printers, files,
communication lines, disks and tapes.
Buffers on MP3 players and portable CD players, iPod playlist.
Programming a real-time system.
Representation of Queue
a) Array representation of Queue
An array to store the queue elements
queueFront: keeps track of the first element
queueRear: keeps track of the last element
maxQueueSize: specifies the maximum size of the queues
Items are deleted at one end called front end of the queue.
Stack
-------
It allows access to only one data item: the last item inserted.
Items are inserted & deleted at one end called Top of the stack.
All the data items are put on top of the stack and taken off the top
The top node in the tree is called the root and all other nodes branch off from this one.
Every node in the tree can have some number of children. Each child node can in turn be the
parent node to its children and so on.
Child nodes can have links only from a single parent.
Any node higher up than the parent is called an ancestor node.
Nodes having no children are called leaves.
Any node which is neither a root, nor a leaf is called an interior node.
The height of a tree is defined to be the length of the longest path from the root to a leaf in that
tree ( including the path to root)
A common example of a tree structure is the binary tree.
Binary tree : A binary tree is a tree in which each node can have maximum two children. Thus
each node can have no child, one child or two children. The pointers help us to identify whether it is
a left child or a right child.
A binary tree consists of
a node (called the root node) and
left and right sub-trees . Both the trees are themselves binary trees.