CS 212 OOP Lab Manual PDF
CS 212 OOP Lab Manual PDF
CS-212
Lab Manual
(December 2012)
Prepared by
Engr. Sajid Saleem
Assistant Professor
EPE Department
UNIFIED CURRICULA 2012
Object Oriented Programming
CS-212
(December 2012)
List Of Practicals
S Practicals Week
No
1. Practice of Computer Fundamental Concepts 1
2. Preprocessor 2
LAB OBJECTIVE
A quick review of the fundamental programming concepts of C++
OVERVIEW
The first lab focuses on revising the basic concepts of C++ language as studied by the students
previously. A recall is important as the programming skills being taught in this course need a
thorough knowledge of fundamental techniques.
Following is a comprehensive code provided for reviewing previous knowledge and to help in
clearing relevant ambiguities. The code has to be run and understood for further modifications in
it.
//lab1a.cpp
// revising basic concepts using an example of a calculator
private: //private members only accessible by functions of the class and not by functions outside
the class (like main)
int c;
calc myCalc; //object of class calc named myCalc, it can have any name
int x,y;
char choice;
case'-':
cout<<"\nDiffernce: "<<myCalc.sub(x,y)<<"\n\n";
break;
case'*':
cout<<"\nProduct: "<<myCalc.mult(x,y)<<"\n\n";
break;
case'/':
myCalc.div(x,y);
break;
case'f':
cout<<"\nFactorial of first number : "<<factorial(x)<<"\n\n";
cout<<"Factorial of second number : "<<factorial(y)<<"\n\n";
break;
The mathematical operations are implemented using multi-functions. The functions for addition,
subtraction, multiplication and division are defined as public members of the classcalc, hence
they can be accessed by functions outside the class (like main). The function for calculating
remainder after dividing the numbers is a private member of the class and can only be accessed
by the members of class. Similarly, the variable for holding the results is also a private member.
The function for calculating factorial of numbers is not a part of class and is prototyped before
the body of main starts. The logic of this function is based on recursion.
The members of class cannot be accessed without an object, so firstly we create an object of the
class calc named myCalc in the body of main function. The users of the program are given an
option to choose the operation they want to be performed on the two numbers taken as input
from the users. This is implemented in the program using the conditional statement – switch. A
particular function is executed according to the chosen operation.
As we can see that remainder function is a part of division function and it displays both, the
quotient and the remainder.
TASK(S)
1- Recode lab1a.cpp and implement the function of factorial by replacing the recursion with
a loop.
2- Recode lab1a.cpp and replace the switch statement with if-else statements for using
multi-functions.
LAB # 2
PREPROCESSORS
LAB OBJECTIVE
Learning the use of different preprocessor directives and creating macros for small functions.
OVERVIEW
Preprocessing occurs before a program is compiled. Some possible actions are inclusion of other
files in the file being compiled, definition of symbolic constants and macros, conditional
compilation of program code and conditional execution of preprocessor directives. All
preprocessor directives begin with #, and only white-space characters may appear before a
preprocessor directive on a line. Preprocessor directives are not C++ statements, so they do not
end in a semicolon (;).
When this line appears in a file, all subsequent occurrences (except those inside a string)
of identifier in that file will be replaced by replacement-text before the program is
compiled. For example:
#definePI 3.14159
#ifndefNULL
#define NULL 0
#endif
Every #if construct ends with #endif. A multiple-part conditional preprocessor construct
may be tested using the #elif (the equivalent of else if in an if structure) and the #else (the
equivalent of else in an if structure) directives. #ifdef and #undef are also used in
conditional compilation.
//lab2a.cpp
//use of macros
#include<iostream>
#include<stdio.h>
#include<conio.h>
using std::cin;
using std::cout;
using std::endl;
int main(void)
{
int x = 4;
int z;
z = SQUARE(x); //z is equal of square of 4
PR(z);
z = SQUARE(2); //z is equal of square of 2
PR(z);
PR(SQUARE(x+2)); //calculating and printing result without storing result in z
PR(100/SQUARE(2));
cout<<"x is "<<x<<"\n"<<endl;
PR(SQUARE(++x));
cout<<"After incrementing, x is: "<<x<<"\n"<<endl;
getch();
return 0;
}
The above code is a simple program which shows the use of macros in programming. Macros
can replace simple functions as shown in the given example:
//lab2b.cpp
//use of conditional compilation and ## operator
#include<iostream>
#include<stdio.h>//including header files
#include<conio.h>
#define JUST_CHECKING //preprocessor directives
#define LIMIT 4
#define TEXT 1
#define BOOK 2
#define WORK 3
#define HOME 4
#define TEXTBOOK 5
#define WORKBOOK 6
#define HOMEWORK 7
int main(void)
{
int i;
int total = 0;
for (i = 1; i <= LIMIT; i++)
{
total += 2*i*i + 1;
#ifdef JUST_CHECKING //conditional compilation
#endif
}
getch();
TASK(S)
1- Use macros to create a calculator.
2- Recode the program made for task 1 to insert macros for calculating area of a
rectangle and a circle.
3‐ Recode the program made in task 2 to insert macros that indicates the maximum and
minimum number, also to indicate if the numbers are equal.
LAB # 3
ARRAYS AND VECTORS
LAB OBJECTIVE
Manipulating arrays to process grouped data and understanding the use of library class template
vector.
OVERVIEW
An array is a consecutive group of memory locations that all have the same type. The
programmer specifies the type of the elements and the number of elements required by an array
as follows:
typearrayName [ arraySize ];
To refer to a particular location or element in the array, we specify the name of the array and the
position number of the particular element in the array. For example: if the name of the entire
array is c and contains 5 elements then the elements of array c are referred to as c[0], c[1], c[2],
c[3] andc[4].
Class template vector represents a more robust type of array featuring many additional
capabilities. Vectorsuse template notation. It is defined in header <vector> and belongs to
namespace std.
The following codes give a clear idea of the different ways of using arrays and vectors in
programming.
// lab3a.cpp
//storing values in an array and printing them
#include<iostream>
using std::cout;
using std::endl;
using std::cin;
#include<iomanip>
using std::setw;
int main()
{
int n[ 10 ]; // n is an array of 10 integers
The above code is simple program that uses an array named ‘n’having 10 elements. For loop is
used to assign values to its members as taken input from the user. Another for loop is used to
print those values.
//lab3b.cpp
// Passing arrays and individual array elements to functions.
#include<iostream>
using std::cout;
using std::endl;
#include<iomanip>
using std::setw;
void modifyArray( int [], int ); // function having the first argument as an array
void modifyElement( int );
int main()
{
constint arraySize = 5; // size of array a
int a[ arraySize ] = { 0, 1, 2, 3, 4 }; // initializing array a
cout <<"Effects of passing entire array by reference:"
<<"\n\nThe values of the original array are:\n";
// in function modifyElement, "e" is a local copy of array element a[ 3 ] passed from main
The above program shows how a function having an array as an argument is declared,called and
defined. In the function modifyArray, the whole array is processed and all the elements are
multiplied by 2. Whereas,the function modifyElement has only one integer type argument to pass
the value of any individual member of the array. In this code the 4th element of the array is
passed and is multiplied by 2. In both the functions the actual values of the array elements are
modified.
// lab3c.cpp
// Linear search of an array.
#include<iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
constint arraySize = 100; // size of array a
int a[ arraySize ]; // creating array a
int searchKey; // value to be located in array a
// display results
if ( element != -1 )
cout <<"Found value in element "<< element << endl;
else
cout <<"Value not found"<< endl;
int linearSearch( constintarray[], int key, int sizeOfArray ) // function compares key to every
element of array until location is
// found or until end of array is reached;
{
for ( int j = 0; j < sizeOfArray; j++ )
if ( array[ j ] == key ) // if found,
return j; // return location of key
Sometimes when dealing with a large amount of data it may be necessary to determine whether an
array contains a value that matches a certain key value. The process of finding a particular
element of an array is called searching. The above program compares each element of an array
with a search key and displays the results accordingly. The linear searching method works well
for small arrays or for unsorted arrays (i.e., arrays whose elements are in no particular order).
// lab3d.cpp
// Demonstrating C++ Standard Library class template vector.
#include<iostream>
using std::cout;
using std::cin;
using std::endl;
using std::setw;
#include<vector>
using std::vector;
int main()
{
vector<int> integers1( 7 ); // 7-element vector< int >
vector<int> integers2( 10 ); // 10-element vector< int >
if ( integers1 != integers2 )
cout <<"integers1 and integers2 are not equal"<< endl;
if ( integers1 == integers2 )
cout <<"integers1 and integers2 are equal"<< endl;
if ( i % 4 != 0 )
cout << endl;
} // end function outputVector
// input vector contents
void inputVector( vector<int>&array )
{
for ( size_t i = 0; i <array.size(); i++ )
cin >>array[ i ];
} // end function inputVector
The above code is based on the use of vectors. Two vector objects are created that store values of
type int.integers1 contains seven elements, and integers2 contains 10 elements. By default, all
the elements of each vector object are set to 0. Vectors can be defined to store any data type, by
replacing int in vector<int> with the appropriate data type.
Two functions inputVector and outputVector are used in this code for assigning values to the
elements and printing the values respectively. Square brackets ([]) can be used to obtain a vector
element.
The size of a vector is built-in;every vector object "knows" its own size, which can be obtained by
invoking the vector object's size member function).Thus, when we pass a vectorobject into a
function, we will not have to pass the size of the vector as an argument. Member function size of
class template vector returns the number of elements in a vector as a value of type size_t(which
represents the type unsigned int on many systems). In the program, the control variable ‘i’is to be
of type size_t. On some compilers, declaring i as an int causes the compiler to issue a warning
message, since the loop-continuation condition would compare a signed value (i.e., inti) and an
unsigned value (i.e., a value of type size_t returned by function size).
Another point to note is that in the program an error has been mentioned as comments. Since
vector object integers1 has seven elements so trying to access the 15th element would cause a run
time error.
TASK(S):
1- Recode lab3a.cpp to add two arrays to input float values and characters from user and
displaying values of array element on screen.
2- Recode lab3b.cpp and by passing the given array to function, add a function that
indicates the prime numbers.
3- Recode lab3c.cpp to add an array having 10 elements whose values are based on user
input and sort the values in ascending and descending order.
LAB # 4
POINTERS AND POINTER-BASED STRINGS
LAB OBJECTIVE
Manipulating pointers for different data types.
OVERVIEW
A pointer variable contains the memory address of a variable that, in turn, contains a specific
value. In this sense a pointer indirectly references a value. Each variable being declared as a
pointer must be preceded by an asterisk (*). For example, the declaration
indicates that both xPtr and yPtr are pointers to double values. Pointers can be declared to point
to objects of any data type. The statement:
yPtr = &y;
assigns the address of the variable y to pointer variable yPtr. Then variable yPtr is said to "point
to" y. The * operator, commonly referred to as the indirection operator or dereferencing operator,
returns the value of the variable the pointer points to. If y=5 then *yptr would return the value of
y that is 5.
Arrays and pointers are intimately related in C++ and may be used almost interchangeably. An
array name can be thought of as a constant pointer. Pointers can be used to do any operation
involving array subscripting.
//lab4a.cpp
// Using subscripts and pointer notations with arrays.
#include<iostream>
using std::cout;
using std::endl;
int main()
{
} // end main
The first code shows the relationship between arrays and pointers. Pointers can be used to do any
operation involving array subscripting.
As we know that the array name (without a subscript) is a pointer to the first element of the
array so bPtr is set to the address of the first element in array bby declaring bPtr = b; which is
equivalent to bPtr = &b[ 0 ];
Array element b[ x ] (x is the subscript for any element in an array) can alternatively be
referenced with the pointer expression *( bPtr + x ). The x in the preceding expression is the
offset to the pointer, which is identical to the array subscript. Just as the array element can be
referenced with a pointer expression, the address &b[ x ] can be written with the pointer
expression (bPtr + x).
// lab4b.cpp
// Cube a variable using pass-by-reference with a pointer argument.
#include<iostream>
using std::cout;
using std::endl;
int main()
{
int number = 5;
} // end main
void cubeByReference( int *nPtr ) // function calculates cube of *nPtr; modifies variable
number in main
{
*nPtr = *nPtr * *nPtr * *nPtr; // cube *nPtr
} // end function cubeByReference
The above code shows how pointers can be used as arguments for functions. The address of a
variable is passed to a function and the indirection operator (*) can be used in the function to
form a synonym for the name of the variable in order to manipulate the value of the variable at
that location in the caller's memory.
In this program the address of number is passed to the function. Function cubeByReference
specifies parameter nPtr (a pointer to int) to receive its argument. The function dereferences the
pointer and cubes the value to which nPtrpoint . This directly changes the value of number in
main.
//lab4c.cpp
//using pointer for string
#include<iostream>
using std::cin;
using std::cout;
using std::endl;
void main()
{
char arr1[15]={"HAPPY BIRTHDAY"};
char *arr2[]={"HELLO","WORLD"};//two dimensional array
arrptr1=arr1;//pointer to arr1
for(i=0;i<=14;i++)
{
cout<<*(arrptr1+i);
}
for(i=0;i<=14;i++)
{
cout<<arr1[i];
}
for(i=0;i<=1;i++)
{
cout<<arr2[i]<<" ";
}
for(i=0;i<=1;i++)
{
for(j=0;j<=5;j++)
{
cout<<arr2[i][j];
}
cout<<endl;
The above program shows how pointers can be manipulated for string data. It also demonstrates
the use of two dimensional character array or strings and the way of accessing their members
using pointer and array notations.
TASK(S)
1- Recode lab4b.cpp to add a function that displays prime numbers between the two integers
provided by the user. The function should have pointer arguments.
2- Recode task-1 to add a function that sorts those prime numbers in descending order.
3- Recode task-2 to add a function that calculates the factorial of the numbers between the
two integers provided by the user.
4- Recode lab4c.cpp to take three string inputs in a two dimensional array of 3 rows and 15
columns and write a function that prints them.
LAB # 5
STREAM INPUT/OUTPUT
LAB OBJECTIVE
Understanding stream I/O operations and stream manipulation techniques.
OVERVIEW
C++ I/O occurs in streams, which are sequences of bytes. The bytes could represent characters,
raw data, graphics images, digital speech, digital video or any other information an application
may require. The system I/O mechanisms should transfer bytes from devices to memory (and
vice versa).
The C++ iostream library provides hundreds of I/O capabilities. The <iomanip> header declares
services useful for performing formatted I/O with stream manipulators. Stream manipulators
perform formatting tasks. They provide capabilities such as setting field widths, setting
precision, setting and unsetting format state, setting the fill character in fields, flushing streams,
inserting a newline or a null character into the output stream etc.
// lab5a.cpp
// Use of some stream manipulators
#include<iostream>
using std::cin;
using std::cout;
using std::dec;
using std::endl;
using std::hex;
using std::oct;
using std::fixed;
using std::showbase;
#include<iomanip>
using std::setbase;
using std::setprecision;
#include<cmath>
using std::sqrt;
void prec(void);//function prototype
void showb(int);//function prototype
int main()
{
int number;
return 0;
} // end main
void showb (int a) //displaying number with the respective base using stream manipulator
showbase
{
} //function end
void prec(void) //funtion showing the use of stream manipulators setprecision and precision
{
float root = sqrt(2.0); // calculating the value of square root of 2
int places; // precision, decimal places varying from 0-9
} //function end
The above program uses stream manipulators hex, oct and dec to convert the number into
different number systems. The function prec() shows the use of manipulators setprecision and
precision, while the function showb() displays how showbase manipulator works. Some stream
manipulators and their functions are as follows:
Stream Description
Manipulator
skipws Skip white-space characters on an input stream. This setting is reset with
stream manipulator noskipws.
left Left justify output in a field. Padding characters appear to the right if
necessary.
right Right justify output in a field. Padding characters appear to the left if
necessary.
internal Indicate that a number's sign should be left justified in a field and a number's
Stream Description
Manipulator
magnitude should be right justified in that same field (i.e., padding characters
appear between the sign and the number).
dec Specify that integers should be treated as decimal (base 10) values.
oct Specify that integers should be treated as octal (base 8) values.
hex Specify that integers should be treated as hexadecimal (base 16) values.
showbase Specify that the base of a number is to be output ahead of the number (a
leading 0 for octals; a leading 0x or 0X for hexadecimals). This setting is reset
with stream manipulator noshowbase.
showpoint Specify that floating-point numbers should be output with a decimal point.
This is used normally with fixed to guarantee a certain number of digits to the
right of the decimal point, even if they are zeros. This setting is reset with
stream manipulator noshowpoint.
uppercase Specify that uppercase letters (i.e., X and A tHRough F) should be used in a
hexadecimal integer and that uppercase E should be used when representing a
floating-point value in scientific notation. This setting is reset with stream
manipulator nouppercase.
showpos Specify that positive numbers should be preceded by a plus sign (+). This
setting is reset with stream manipulator noshowpos.
scientific Specify output of a floating-point value in scientific notation.
fixed Specify output of a floating-point value in fixed-point notation with a specific
number of digits to the right of the decimal point.
//lab5b.cpp
// Testing error states.
#include<iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
int integerValue;
return 0;
} // end main
The clear member function is used to restore a stream's state to "good," (sets the goodbit) so that
I/O may proceed on that stream.The state of a stream may be tested through bits in class
ios_base.
The rdstate member function returns the error state of the stream. A call to cout.rdstate, for
example, would return the state of the stream, which then could be tested by a switch statement
that examines eofbit, badbit, failbit and goodbit.
The failbit is set for a stream when a format error occurs on the stream, such as when the
program is inputting integers and a nondigit character is encountered in the input stream. Thedata
is not lost when this error occurs
Thebadbit is set for a stream when an error occurs that results in the loss of data.
The goodbit is set for a stream if none of the bits eofbit, failbit or badbit is set for the stream.
TASK(S)
1. Write a code which has two functions for adding and subtracting octal and hexadecimal
numbers (numbers taken input from user in decimal form).
LAB # 6
CLASS STRING AND STRING STREAM PROCESSING
LAB OBJECTIVE
Learning various ways of manipulating strings and string processing.
OVERVIEW
To use strings, header file <string> is included. String can be initialized in multiple ways. Most
string member functions take as arguments a starting subscript location and the number of
characters on which to operate.
// lab6a.cpp
// Demonstrating string assignment, concatenation, comparison and swapping
#include<iostream>
using std::cout;
using std::endl;
#include<string>
using std::string;
int main()
{
string string1( "cat" );
string string2;
string string3;
if ( result == 0 )
cout <<"string1.compare( string2 ) == 0\n\n";
else// result != 0
{
if ( result > 0)
cout <<"string1.compare( string2 ) > 0\n\n";
else// result < 0
cout <<"string1.compare( string2 ) < 0\n\n";
} // end else
// overloaded +=
string3 += "pet"; // create "carpet"
string1.append( "acomb" ); // create "catacomb"
if ( result == 0 )
cout <<"\nstring1.compare( 2, 5, string3, 0, 5 ) == 0\n";
else// result != 0
{
if ( result > 0 )
cout <<"\nstring1.compare( 2, 5, string3, 0, 5 ) > 0\n";
else// result < 0
cout <<"\nstring1.compare( 2, 5, string3, 0, 5 ) < 0\n";
} // end else
//making a substring
// begins at subscript 4 and consists of 4 elements
//string swapping
string4.swap( string5 ); // swap string
cout <<"\n\nAfter swapping:\nString4: "<< string4 <<"\nString5: "<< string5 << endl;
return 0;
} // end main
The above code demonstrates string assignment, concatenation, comparison and swapping.String
assignment has been done using ‘=’ operator, as well as assign function. Member function
‘assign’ copies a specified number of characters. Its format is:
For concatenating addition assignment operator, += and member function ‘append’have been
used.
String member function compare has been used in different ways to compare strings. In the
following line, result = string1.compare( string2 ); Variable result is assigned 0 if the strings are
equivalent, a positive number if string1 is lexicographically (alphabetically) greater than string2
or a negative number if string1 is lexicographically less than string2.
Member function substris used to retrieve a substring from a string. The first argument specifies
the beginning subscript of the desired substring; the second argument specifies the substring's
length.
#include<iostream>
using std::cout;
using std::endl;
#include<string>
using std::string;
int main()
{
string string1( "noon is 12 pm; midnight is not." );
int location;
//string erasing
string1.erase(13); // removes all characters from (and including) location 13 through the
end of string1
cout<<"\nErasing a part of string: "<<string1<<endl;
//string replacement
int position = string1.find( " " ); // find first space
//second repalcement
position = string1.find( "." ); // find first period
//string insertion
string string2( "beginning end" );
string string3( "middle " );
return(0);
} // end main
The above code shows the use of string find member functions, string erasing, replacement and
insertion.
Member function find_first_of locates the first occurrence in string1 of any character in "misop".
The searching is done from the beginning of string1.
Member function find_last_of finds the last occurrence in string1 of any character in "misop".
The searching is done from the end of string1.
Member function find_first_not_of finds the first character in string1 not contained in "noispm".
Searching is done from the beginning of string1.
string1.erase(13); removes all characters from (and including) location 13 through the end of
string1.
First replacement of the string is done by using find to locate each occurrence of the space
character. Each space is then replaced with a period by a call to string member function replace.
Function replace takes three arguments: the subscript of the character in the string at which
replacement should begin, the number of characters to replace and the replacement string. And in
the second repalcement every period and its following character is replaced with two semicolons.
The member function insert can either have two or four arguments. Two arguments are used
when an entire string is to be inserted. First argument is the location of the first string from
where insertion should begin and the second argument is the string to be inserted. When partial
insertion of a string is needed we use four arguments, first is the location of the first string,
second is the string to be copied and the last two arguments specify the starting and last element
of string that should be inserted. Using string::npos causes the entire string to be inserted.
TASK(S):
1. Write a code to take a string as input from user and create your own function for
converting the string to uppercase alphabets.
2. Recode task-1 to add another function that compares two strings.
The functions for both the tasks should not include pre-defined functions for string
manipulation.
LAB # 7
BIT, CHARACTER, C STRINGS AND STRUCT
LAB OBJECTIVE
Working on structures and various bitwise operators.
OVERVIEW
C++ also provides extensive bit-manipulation capabilities for programmers who need to get
down to the binary level. All data is represented internally by computers as sequences of bits.
Each bit can assume the value 0 or the value 1 which are called binary numbers.
The bitwise operators are: bitwise AND (&), bitwise inclusive OR (|), bitwise exclusive OR (^),
left shift (<<), right shift (>>) and bitwise complement (~)also known as the one's complement.
#include<iostream>
using std::cin;
using std::cout;
#include<iomanip>
using std::setw;
#define LEN 20
char * msgs[5] = { " Thank you for the wonderful evening, ", "You certainly prove that a ", "is a
special kind of guy. We must get together", "over a delicious ", " and have a few laughs" };
int main(void)
{
struct guy fellow = { { "Chip", "Vejer" }, "nachos plate", "memory broker", 36827.00 }; //
initialize a variable
The above program is based on nested structures, which means a structure containing another
structure. The template or structure definition of both the structures has been mentioned before
the body of main.In this example the structure called ‘names’ is nested within the one called
‘guy’. The guy structure contains the structure variable of type names called ‘handle’. The
variable of guy type called ‘fellow’ is declared and initialized in the body of main function and
the structure members are printed along with the messages.
As we can see, the members of the structure ‘names’ have to be accessed by using the dot
operator twice, since it is nested within another structure. For instance,fellow.handle.first
instructs the program to find fellow, then find the handle member of fellow, and then find the
first member of handle.
// lab7b.cpp
// Using the bitwise AND, bitwise inclusive OR, bitwise
// exclusive OR, right shift and left shift operators.
#include<iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
int number1,number2, result;
// demonstrate bitwise |
return 0;
} // end main
TASK(S):
1. Recode lab7a.cpp to create an array of structure to input three records from the user and
display them on screen.
2. Recode lab7b.cpp to add a function that displays binary equivalent of decimal numbers.
LAB # 8
CLASSES: A DEEPER LOOK
LAB OBJECTIVE
OVERVIEW
The lab focuses on the basic terms and concepts of C++ objectoriented programming which
includes in-depth discussion on class, class scope and the relationships among members of a
class. Constructors, destructors and friend functions are very commonly used with classes and
are discussed in detail.
Class members are immediately accessible by all of that class's member functions and can be
referenced by name. Outside a class's scope, public class members are referenced through one of
the handles on an object: an object name, a reference to an object or a pointer to an object. The
dot member selection operator (.) is preceded by an object's name or with a reference to an object
to access the object's members. The arrow member selection operator (->) is preceded by a
pointer to an object to access the object's members.
A constructor can be used to initialize an object of the class when the object is created. A
constructor is a special member function that must be defined with the same name as the class, so
that the compiler can distinguish it from the class's other member functions. An important
difference between constructors and other functions is that constructors cannot return values and
cannot specify a return type (not even void). Normally, constructors are declared public. A
constructor that defaults all its arguments is also a default constructor i.e., a constructor that can
be invoked with no arguments. There can be a maximum of one default constructor per class.
A destructor is another type of special member function. The name of the destructor for a class is
the tilde character (~) followed by the class name. A class's destructor is called implicitly when
an object is destroyed. The destructor itself does not actually release the object's memory but it
performs termination housekeeping before the system reclaims the object's memory, so the
memory may be reused to hold new objects. A destructor receives no parameters and returns no
value. Constructors and destructors are called implicitly by the compiler. The order in which
these function calls occur depends on the order in which execution enters and leaves the scopes
where the objects are instantiated. Generally, destructor calls are made in the reverse order of the
corresponding constructor calls.
A friend function of a class is defined outside that class's scope, yet has the right to access the
non-public (and public) members of the class. To declare a function as a friend of a class,
precede the function prototype in the class definition with keyword friend.
The following programs will help clearing the above mentioned concepts.
// lab8a.cpp
// Demonstrating the class member access operators . and ->
#include<iostream>
using std::cout;
using std::endl;
class Count
{
public:
void setX( int value ) // sets the value of private data member x
{
x = value;
} // end function setX
{
cout << x << endl;
} // end function print
private:
int x;
}; // end class Count
int main()
{
Count counter; // creating counter object
Count *counterPtr = &counter; // creating pointer to counter
Count &counterRef = counter; // creating reference to counter
This above mentioned code simply demonstrates the ways of accessing members of a class called
Countthat has a private data member x of type int ,public member function setX and public
member function print. The object for the class has been named ‘counter’ and variable
counterRef refers to counter, and variable counterPtr points to counter. Program can invoke
member functions setX and print by using the dot (.) member selection operator preceded by
either the name of the object (counter) or a reference to the object. Same can be done by using a
pointer (countPtr) and the arrow (->) member selection operator.
The following program which demonstrates the operation of constructors and destructors
consists of three files: a header file and two .cpp files
//lab8b.h
// Definition of class CreateAndDestroy.
// Member functions defined in lab8b1.cpp.
#include<string>
using std::string;
#ifndef CREATE_H
#define CREATE_H
class CreateAndDestroy
{
public:
CreateAndDestroy( int, string ); // constructor
~CreateAndDestroy(); // destructor
private:
int objectID; // ID number for object
string message; // message describing object
}; // end class CreateAndDestroy
#endif
// lab8b1.cpp
// Member-function definitions for class CreateAndDestroy.
#include<iostream>
using std::cout;
using std::endl;
{
objectID = ID; // setting object's ID number
message = messageString; // set object's descriptive message
CreateAndDestroy::~CreateAndDestroy() // destructor
{
cout << ( objectID == 1 || objectID == 6 ? "\n" : "" ); // output
newline for certain objects; helps readability
// lab8b2.cpp
// Demonstrating the order in which constructors and destructors are called.
#include<iostream>
using std::cout;
using std::endl;
int main()
{
cout <<"\nMAIN FUNCTION: EXECUTION BEGINS"<< endl;
CreateAndDestroy second( 2, "(local automatic in main)" );
static CreateAndDestroy third( 3, "(local static in main)" );
The above mentioned program demonstrates the order in which constructors and destructors are
called for objects of class CreateAndDestroyof various storage classes in several scopes. Each
object of class CreateAndDestroy contains an integer (objectID) and a string (message)that are
used in the program's output to identify the object. The destructor determines whether the object
being destroyed has an objectID value 1 or 6 and, if so, outputs a newline character.
The object first has global scope. Its constructor is actually called before any statements in main
execute and its destructor is called at program termination after the destructors for all other
objects have run. Function main declares three objects. Objects second and fourth are local
automatic objects, and object third is a static local object. The constructor for each of these
objects is called when execution reaches the point where that object is declared. The destructors
for objects fourth and then second are called (i.e., the reverse of the order in which their
constructors were called) when execution reaches the end of main. Because object third is static,
it exists until program termination. The destructor for object third is called before the destructor
for global object first, but after all other objects are destroyed.
Function ‘create’ declares three objects fifth and seventh as local automatic objects, and sixth as
a static local object. The destructors for objects seventh and then fifth are called (i.e., the reverse
of the order in which their constructors were called) when create terminates. Because sixth is
static, it exists until program termination. The destructor for sixth is called before the destructors
for third and first, but after all other objects are destroyed.
// lab8c.cpp
// Friend functions
#include<iostream>
using std::cout;
using std::endl;
{
friendvoid setX( Count &, int ); // friend declaration
public:
Count() // constructor
: x( 0 ) // initialize x to 0
{
// empty body
} // end constructor Count
private:
void setX( Count &c, int val ) // function setX can modify private data of Count
// because setX is
declared as a friend of Count
{
c.x = val;
} // end function setX
int main()
{
Count counter; // create Count object
In this program function setX is a stand-alone function and not a member function of class
Count. For this reason, when setX is invoked for object counter it passes counter as an argument
to setX rather than using a handle (such as the name of the object) to call the function. And we
can clearly see that the function setX can access the private member of the class. This is because
the function is declared as the friend function of the class, had it not been so an error would have
been generated.
TASK(S):
1- Using constructor, destructor and friend functions, create a record for three employees
that includes employee name, department, designation and salary.
LAB # 9
OPERATOR OVERLOADING: STRING AND ARRAY OBJECTS
LAB OBJECTIVE
OVERVIEW
Many common manipulations are performed with operators (e.g., input and output). Hence C++
enables operators to work with objects, and this process is called operator overloading. The jobs
performed by overloaded operators can also be performed by explicit function calls, but operator
notation is often clearer and more familiar to programmers. Programmers can use operators with
user-defined types as well. Although C++ does not allow new operators to be created, it does
allow most existing operators to be overloaded.
One example of an overloaded operator built into C++ is <<, which is used both as the stream
insertion operator and as the bitwise left-shift operator. Similarly, >> is also overloaded; it is
used both as the stream extraction operator and as the bitwise right-shift operator.
~ ! = < > += -= *=
new[] delete[]
Operator precedence and associativity chart is as follows. Operators are shown in decreasing
order of precedence from top to bottom.
C++ also enables the programmers to overload functions. Several functions of the same name
can be defined, as long as these functions have different sets of parameters (at least as far as the
parameter types or the number of parameters or the order of the parameter types are concerned).
This capability is called function overloading. When an overloaded function is called, the C++
compiler selects the proper function by examining the number, types and order of the arguments
in the call. Function overloading is commonly used to create several functions of the same name
that perform similar tasks, but on different data types.
However, you cannot declare multiple functions with the same name if they only differ in their
types, for example you cannot declare intf(), double f() in the same scope. Similarly, function
declarations that have equivalent parameter declarations are not allowed.
The following codes demonstrate the use of operator and function overloading.
//lab9a.h
//header file
#ifndef PHONENUMBER_H
#define PHONENUMBER_H
#include<iostream>
using std::ostream;
using std::istream;
#include<string>
using std::string;
class PhoneNumber
{
friend ostream &operator<<( ostream &, const PhoneNumber & );
friend istream &operator>>( istream &, PhoneNumber & );
private:
string areaCode; // 3-digit area code
string exchange; // 3-digit exchange
string line; // 4-digit line
}; // end class PhoneNumber
#endif
// lab9a.cpp
// Overloaded stream insertion and stream extraction operators
// for class PhoneNumber.
#include<iostream>
using std::cout;
using std::cin;
using std::endl;
#include<iomanip>
using std::setw;
#include"lab9a.h"
int main()
{
PhoneNumber phone; // create object phone
cout <<"Enter phone number in the form (123) 456-7890:"<< endl;
The above program consists of a header file and one .cpp file. In the above example of operator
overloading the stream insertion and stream extraction operators have been overloaded to
perform input and output for user-defined types. The code demonstrates overloading these
operators to handle data of a user-defined telephone number class called PhoneNumber.
The stream extraction operator function operator>> takes istream reference input and
PhoneNumber reference num as arguments and returns an istream reference. When the compiler
sees the expression cin>> phone, it generates the global function call:
Similarly, the stream insertion operator function takes an ostream reference (output) and a
constPhoneNumber reference (number) as arguments and returns an ostream reference. And
when the compiler sees the expression cout<< phone, it generates the global function call
Function operator<< displays the parts of the telephone number as strings, because they are
stored as string objects.
//lab9b.cpp
//operator overloading on prefix and postfix increment operator.
#include<iostream>
using std::cout;
using std::endl;
class A1 {
public:
class A2 { };
class A4 { };
int main()
{
A1 a1;
A2 a2;
A3 a3;
A4 a4;
// calls a1.operator++()
cout<<"Function call ++a1\n";
++a1;
// calls operator++(a2)
cout<<"Function call ++a2\n";
++a2;
// calls operator++(a4, 0)
cout<<"Function call a4++\n";
a4++;
The above code demonstrates the overloading of prefix and postfix increment operator.
The prefix increment operator ++ is overloaded with either a nonmember function operator that
has one argument of class type (in this case: class type A2) or a reference to class type, or with a
member function operator that has no arguments (in this case: member of class A1). Function for
overloaded operator is called using both the ways in the code.
Whereas, the postfix increment operator ++ can be overloaded for a class type by declaring a
nonmember function operator operator++() with two arguments (in this case: class type A4), the
first having class type and the second having type int. Alternatively, you can declare a member
function operator operator++() with one argument having type int (in this case: class member of
class A3). The compiler uses the intargument to distinguish between the prefix and postfix
increment operators. For implicit calls, the default value is zero.
//lab9c.cpp
//function overloading
#include<iostream>
usingnamespace std;
void print(int i) {
cout <<" Here is int "<< i << endl;
}
void print(double f) {
cout <<" Here is float "<< f << endl;
}
void print(char* c) {
cout <<" Here is char* "<< c << endl;
}
int main() {
print(10);
print(10.10);
print("ten");
}
In the above example of function overloading the function ‘print’ is overloaded to display
different data types. Three functions are declared with the same name, each performing a similar
operation on an int value, a double value and a string respectively. The compiler encodes each
function identifier with the number and types of its parameters to enable type-safe linkage. Type-
safe linkage ensures that the proper overloaded function is called and that the types of the
arguments conform to the types of the parameters.
TASK(S):
1- Recode lab9b.cpp for overloading prefix and postfix decrement operator.
2- Write a code that uses function overloading such that the length of two string inputs is
calculated in one function, strings are compared in another and the third function should
display 1 if compared successfully and 0 if not.
(HINT: first function would be having one argument, second would be having two and
third function would be having one int argument).
LAB # 10
INHERITANCE
LAB OBJECTIVE
Using classes with multiple inheritances.
OVERVIEW
Inheritance is a form of software reuse in which the programmer creates a class that absorbs an
existing class's data and behaviors and enhances them with new capabilities. A new class can be
designated that should inherit the members of an existing class. This existing class is called the
base class, and the new class is referred to as the derived class. Every derived-class object is an
object of its base class, and one base class can have many derived classes. Although classes can
exist independently, once they are employed in inheritance relationships, they become affiliated
with other classes. A class becomes either a base class supplying members to other classes, a
derived classinheriting its members from other classes, or both.
A base class's private members are accessible only within the body of that base class and the
friends of that base class. So we can use the access specifier ‘protected’, when dealing with
inheritance. A base class's protected members can be accessed within the body of that base class,
by members and friends of that base class, and by members and friends of any classes derived
from that base class.
//lab10.cpp
//Inheritance
#include<iostream>
using std::cin;
using std::cout;
using std::endl;
#include<string>
using std::string;
}
protected://protected members of base class that can be accessed by the derived class
string name;
string des;
};
public:
void get1()
{
void display()
{
cout<<"\n\nEmployee name: "<<name<<endl;
cout<<"Designation: "<<des<<endl;
cout<<"Basic salary: "<<bs<<endl;
cout<<"Health allowance: "<<ha<<endl;
cout<<"Net salary: "<<net<<endl;
}
void main()
{
emp X; //object of base class
salary Y;//object of derived class
X.get();
Y.get1();
Y.calculate();
Y.display();
The above code demonstrates a single inheritance. The class ‘emp’ is the base class having a
function that takes employee’s name and designation as input from the user. The strings storing
the input are declared as protected members of the class so that the derived class can access
them. The derived class is named as ‘salary’ and inherits the members and data of the base class.
The derived class consists of three member functions: one for taking basic salary as input, second
for calculating net salary by adding health allowance to the basic salary and third function for
displaying the information.
TASK(S)
1- Recode lab10.cpp to add two more derived classes based on inheritance. First class
should include a function that asks for employee’s age and the other class should
determine the gratuity for the employee based on their age.
Below 50 years - no gratuity
Between 50-60 years - single gratuity
Above 60 years - double gratuity
LAB # 11
POLYMORPHISM
LAB OBJECTIVE
Exploring some areas of polymorphism.
OVERVIEW
Polymorphism enables us to "program in the general" rather than "program in the specific." With
polymorphism, we can design and implement systems that are easily extensible new classes can
be added with little or no modification to the general portions of the program, as long as the new
classes are part of the inheritance hierarchy. Virtual functions and abstract classes are an
important part of polymorphism and are discussed as follows.
A virtual function is a function in a base class that is declared using the keyword virtual. If you
specify a function in a base class as virtual and there is another definition of the function in a
derived class, it signals to the compiler that you don’t want static binding for this function but the
selection of the function to be called at any given point in the program to be based on the kind of
object for which it is called or in other words the function in the base class is over-ridden in the
derived class. Choosing the appropriate function to call at execution time (rather than at compile
time) is known as dynamic binding or late binding. For a function to behave as virtual, it must
have the same name, parameter list, and return type in any derived class as the function has in the
base class, and if the base class function is const, the derived class function must be const as
well.
Virtual functions can also be ‘pure’, called as pure virtual functions. A pure virtual function is
specified by placing "= 0" in its declaration. The difference between a virtual function and a pure
virtual function is that a virtual function has an implementation and gives the derived class the
option of overriding the function; by contrast, a pure virtual function does not provide an
implementation and requires the derived class to override the function. Pure virtual functions are
used when it does not make sense for the base class to have an implementation of a function but
the programmer wants derived classes to implement the function. Pure virtual functions usually
work with abstract classes.
There are some situations in which it is useful to define classes from which the programmer
never intends to instantiate any objects. Such classes are called abstract classes. The purpose of
an abstract class is to provide an appropriate base class from which other classes can inherit.
Normally abstract classes are used as base classes in inheritance hierarchies; referred as abstract
base classes. These classes cannot be used to instantiate objects and derived classes must define
the "missing pieces." The derived classes used for this purpose are called concrete classes.A
class is made abstract by declaring one or more of its virtual function as pure virtual function; as
pure virtual functions are not implemented in the base class.
Abstract base class can be used to declare pointers and references that can refer to objects of any
concrete classes derived from the abstract class.
//lab11a.cpp
//Virtual functions
#include<iostream>
using std::cout;
using std::endl;
class CBox // Base class
{
public:
// Constructor
CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0)
:m_Length(lv), m_Width(wv), m_Height(hv) {}
protected:
double m_Length;
double m_Width;
double m_Height;
};
// Constructor
CGlassBox(double lv, double wv, double hv): CBox(lv, wv, hv){}
};
int main()
{
CBox myBox(2.0, 3.0, 4.0); // Declaring a base box
CGlassBox myGlassBox(2.0, 3.0, 4.0); // Declaring derived box
In this code CBox is the base class containing the virtual function Volume(). The derived class
CGlassBox overrides the function definition of the virtual function for some modification.
Although the keyword virtual is used in the derived class definition of the function Volume(), it’s
not essential to do so.
The first call to the function ShowVolume() with the CBox object myBox calls the CBox class
version of Volume(). The second call with the CGlassBox object myGlassBox calls the version
defined in the derived class.
//lab11b.cpp
//Abstract classes
#include<iostream>
usingnamespace std;
class CPolygon //Abstract base class
{
protected:
int width, height;
public:
};
int main () {
CRectangle rect; //derived class objects
CTriangle trgl;
In the above code CPolygon is the base abstract class that contains the pure virtual function
area(). CRectangle and CTriangle are two derived classes having different definitions for the
function area() and are concrete classes. Pointers are used for derived class through which
member functions are called for displaying and calculating the area. Based on the pointer
declaration, functions are executed for their respective classes.
TASK(S)
1. By using virtual functions or abstract class or both, create a program that calculates the
square of a number and xy (numbers x and y to be taken as input).
LAB # 12
TEMPLATES AND EXCEPTION HANDLING
LAB OBJECTIVE
Working on function and class templates and learning different techniques for exception
handling.
OVERVIEW
This lab is based on two different topics, templates and exception handling. First let’s discuss templates.
When identical operations are to be performed on different data types, they can be expressed more
compactly and conveniently using function templates. For example, we might write a single function
template for an array‐sort function, and then have different function calls for sorting int arrays, float
arrays, string arrays and so on.
All function‐template definitions begin with keyword template followed by a list of template parameters
to the function template enclosed in angle brackets (< and >); each template parameter that represents
a type must be preceded by either of the interchangeable keywords class or typename, as in
template<typename T > or
template< class ElementType>or
template<typenameBorderType, typenameFillType>
When the function is called for a particular data type the template parameters are replaced by the
data type and the arguments sent through function calling.
A class template is similar to function template; we determine the class that we want to be
generated by specifying our choice of type for the parameter that appears between the angled
brackets in the template. Doing this generates a particular class referred to as an instance of the
class template. The process of creating a class from a template is described as instantiating the
template.An appropriate class definition is generated when we instantiate an object of a template
class for a particular type, so any number of different classes can be generated from one class
template.
The other topic covered in this lab is exception handling. An exception is an indication of a
problem that occurs during a program's execution. Exception handling enables programmers to
create applications that can resolve (or handle) exceptions and to writefault-tolerant programs
that are able to deal with problems that may arise and continue executing or terminate gracefully.
//lab12a.cpp
#include<iostream>
using std::cout;
using std::endl;
class mypair
public:
b=second;
T getmax ();
};
template<typename T>//function template (we can use the word class instead of typename with
T)
int main () {
mypair <int> myobject (75, 100);//T replaced in the class and function with int as declared in
function call
return 0;
The above program compares two numbers and displays the greater one by using a class
template and a function template.
To indicate that we are defining a template rather than a straightforward class, we insert the
keywordtemplate and the type parameter, which is T in this case, between angled brackets, just
before the keyword class (keyword typename can also be used in place of class). The parameter
T is the type variable that is replaced by a specific type when a class object is declared.
Wherever the parameter T appears in the class definition, it is replaced by the type that
isspecified in the object declaration; this creates a class definition corresponding to this type.
In the code the object of the class mypair specifies the type as int and values of the two numbers
are initialized using a constructor. The class contains a member function getmax() which is
declared as a function template for type T. The type parameter T is again replaced by int when
the function is called. The function returns the greater number of the two by using ternary
operator.
// lab12b.cpp
//Exception handling.
#include<stdexcept>// stdexcept header file contains runtime_error
#include<iostream>
using std::cin;
using std::cout;
using std::endl;
public:
DivideByZeroException::DivideByZeroException()
if ( denominator == 0 )
int main()
try
} // end try
} // end catch
} // end while
} // end main
The above code is an example of exception handling. The purpose of this program is to prevent a
common arithmetic problem, that is, division by zero.The function quotient tests its second
parameter that is denominator, to ensure that it is not zero before allowing the division to
proceed. If the second parameter is zero, the function uses an exception to indicate to the caller
that a problem occurred.
Try block enables exception handling. A try block consists of keyword try followed by braces
({}) that define a block of code in which exceptions might occur. The try block encloses
statements that might cause exceptions and statements that should be skipped if an exception
occurs. If the user inputs a 0 value as the denominator, function quotient throws an exception. As
the invocation to function quotient can throw an exception, we enclose this function invocation
in a try block and output will occur only when the function returns a value.
Exceptions are processed by catch handlers (also called exception handlers), which catch and
handle exceptions. At least one catch handler must immediately follow each try block. Each
catch handler begins with the keyword catch and specifies in parentheses an exception parameter
that represents the type of exception the catch handler can process (DivideByZeroException in
this case). A catch handler typically reports the error to the user, logs it to a file, terminates the
program gracefully or tries an alternate strategy to accomplish the failed task when an exception
occurs in the try block. In this example, the catch handler simply reports that the user attempted
to divide by zero. Then the program prompts the user to enter two new integer values.
TASK(S)
1. Create a program using function templates that takes 10 int and char values from the user
and stores them in array; it should also display the values by differentiating them as odd
and even.
LAB # 13
FILE PROCESSING
LAB OBJECTIVE
Working on files using console programming.
OVERVIEW
C++ views each file as a sequence of bytes. Each file ends either with an end-of-file marker or at
a specific byte number recorded in a system-maintained, administrative data structure. When a
file is opened, an object is created, and a stream is associated with the object. The streams
associated with these objects provide communication channels between a program and a
particular file or device.
Files are opened by creating ifstream, ofstream or fstream objects. ifstream object is created
when file is to be opened for input, ofstream is for output file and fstream object is created for
file which is to be opened for both input and output. Two arguments are passed to the object's
constructor the filename and the file-open mode. The file open modes are follows:
To retrieve data sequentially from a file, programs normally start reading from the beginning of
the file and read all the data consecutively until the desired data is found. It might be necessary
to process the file sequentially several times (from the beginning of the file) during the execution
of a program. Both istream and ostream provide member functions for repositioning the file-
position pointer (the byte number of the next byte in the file to be read or written). These
member functions are seekg ("seek get") for istream and seekp ("seek put") for ostream. The
argument to seekg or seekp normally is a long integer. A second argument can be specified to
indicate the seek direction. Seek directions are as follows:
The same operations can be performed using ostream member function seekp. Member functions
tellg and tellp are provided to return the current locations of the "get" and "put" pointers,
respectively.
// lab13.cpp
// writing to and reading from a sequential file
#include<iostream>
using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::ios;
#include<cstdlib>
using std::exit; // exit function prototype
int main()
{
int account;
char name[ 30 ];
double balance;
// reading account, name and balance from cin, then placing in file
while ( cin >> account >> name >> balance )
{
ClientFile << account <<' '<< name <<' '<< balance << endl;
cout <<"? ";
} // end while
In this program the file client.txt is opened using fstream having object ClientFile. The modes
are declared for both, reading from and writing to the file as ios::in and ios::app. After creating
an fstream object and attempting to open it, the program tests whether the open operation was
successful. Error message is displayed in case of an unsuccessful attempt. After the file is opened
successfully, the program begins processing data and prompts the user to enter either the various
fields for each record or the end-of-file indicator when data entry is complete. The end-of-file
key combination for Microsoft windows is <ctrl-z> (sometimes followed by pressing Enter). The
data entered by the user is inserted in the file by using the stream insertion operator << and the
ClientFile object.
In order to check the contents of the file it is then read. Since the file is to be read from the
beginning, the file-position pointer is brought to the beginning of the file by using the function
seekg. File contents are then read by using the stream extraction operator >> and the ClientFile
object and displayed on the screen. When the end of file has been reached the fstream destructor
function closes the file and the program terminates. The programmer also can close the object
explicitly, using member function close as: fileobjectname.close(). In this code it would be:
ClientFile.close().
TASK(S):
1- Recode lab13.cpp to take user input which is to be inserted in the middle of the file, such
that the file, if it exists, does not lose its contents when opened.