Sei sulla pagina 1di 79

Pakistan Navy Engineering College /

National University of Sciences


& Technology

Object Oriented Programming

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

3. Arrays and Vectors 3,4

4. Pointers and Pointer-based strings 5

5. Stream Input / Output 6

6. Class String and String Stream Processing 7

7. Bits, Characters, C-Strings and structs 8

8. Classes: A Deeper Look 9

9. Operator Overloading: String and array Objects 10,11

10. OOP: Inheritance 12

11. OOP: Polymorphism 13

12. Templates and Exception Handling 14

13. File Processing 15


LAB # 1
PRACTICE OF COMPUTER FUNDAMENTAL CONCEPTS

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

#include<iostream>// allows program to output data to the screen

using std::cout; //program uses cout


using std::cin; //program uses cin
using std::endl; //program uses endl

class calc //class definition


{

public: //public access specifier

int add(int a, int b) //functions for implementing calcultor operations


{
c=a+b;
return c;
}

int sub(int a, int b)


{
c=a-b;
return c;
}

int mult(int a, int b)


{
c=a*b;
return c;
}

void div(int a, int b)


{
int d=a/b;
cout<<"\nQuotient: "<< d <<"\t\tRemainder: "<<remainder(a,b)<<"\n\n"; //function div
can access a private fuction

private: //private members only accessible by functions of the class and not by functions outside
the class (like main)
int c;

int remainder(int a, int b)


{
c=a%b;
return c;
}

}; //end of class calc

int factorial (int a); //function prototype

int main() //fuction of main starts


{

calc myCalc; //object of class calc named myCalc, it can have any name
int x,y;
char choice;

cout<<"THIS IS A SIMPLE CALCULATOR\n\n"; //printing text on screen


cout<<"Enter choice of operation\n + for addition\n - for subtraction\n * for multiplication\n /
for division\n f for factorial\n";
cin>>choice;

cout<<"\nEnter First Number: "; //prompting


cin>>x; //and taking input from user

cout<<"\nEnter Second Number: ";


cin>>y; //second input from user

switch(choice) //conditional statement


{
case'+':
cout<<"\nSum: "<<myCalc.add(x,y)<<"\n\n"; //function calling and printing text on screen
break;

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;

default: //exception handling


cout<<"\ninvalid choice";
}
return 0; // indicate successful termination
}

int factorial( int number ) //function definition


{

if ( number <= 1 ) // test for base case


return 1; // base cases: 0! = 1 and 1! = 1
else// recursion step
return number * factorial( number - 1 );

} // end of factorial function


The above program implements the operation of a simple calculator using the following features
of C++ programming:Classes and objects, multi-function, recursion and conditional statements.

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 (;).

Functions of some preprocessor directives are:

1. The #includedirective causes a copy of a specified file to be included in place of the


directive. The two forms of the #include directive are:
#include <filename> (including header file)
#include "filename" (including header file created by the user)

2. The #definepreprocessor directive creates symbolic constants,constants represented as


symbols.

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

3. Conditional compilation enables the programmer to control the execution of


preprocessor directives and the compilation of program code. The conditional
preprocessor construct is much like the if selection structure. For example:

#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.

Here are two codes that manipulate preprocessor directives:

 
//lab2a.cpp
//use of macros

#include<iostream>
#include<stdio.h>
#include<conio.h>

using std::cin;
using std::cout;
using std::endl;

#define SQUARE(X) (X)*(X) //macro to calculate square of a number


#define PR(X) cout<<"The result is: "<<X<<"\n"<<endl; //macro for printing result on screen

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:

#define SQUARE(X) (X)*(X)


It calculates the square of any number placed in place of X, by replacing SQUARE(X) with
(X)*(X) wherever it is used.

//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

#define CAT(x,y) x##y //macro for concatenation (use of ## operator)

using std::cout; //program uses cout


using std::endl; //program used endl

int main(void)
{
int i;
int total = 0;
for (i = 1; i <= LIMIT; i++)
{
total += 2*i*i + 1;
#ifdef JUST_CHECKING //conditional compilation

cout<<"i="<<i<<"\trunning total = "<<total<<"\n"<<endl;

#endif
}

cout<<"Grand total = "<<total<<"\n"<<endl;

cout<<"Now let's try concatenation\n"<<endl;


cout<<CAT(TEXT,BOOK)<<"\n"<<endl; //using macro for concatenation
cout<<CAT(HOME,WORK)<<"\n"<<endl;
cout<<CAT(WORK,BOOK)<<"\n"<<endl;
cout<<CAT("WORK","BOOK")<<"\n"<<endl;

getch();

return 0; // indicate successful termination


}

Here is another code that is helpful in understanding conditional compilation.


JUST_CHECKING is defined in the beginning and the program checks if it is defined or not and
on the basis of that it executes the given instructions. It also shows the use of concatenation
operator ##.The ## operator must have at least two operands as it combines the tokens.

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 ];

where the arraySize must be an integer constant greater than zero.

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

// initialize elements of array n to 0


for ( int i = 0; i < 10; i++ )
{
cout<<"Enter element number "<<i<<endl; //taking user input
cin>>n[ i ]; //storing the value in array
}
cout <<"\nElement"<< setw( 13 ) <<"Value"<< endl;

// output each array element's value


for ( int j = 0; j < 10; j++ )
cout << setw( 7 ) << j << setw( 13 ) << n[ j ] << endl;

return 0; // indicates successful termination


} // end main

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";

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


cout << setw( 3 ) << a[ i ]; //displaying original array elements

cout << endl;

modifyArray( a, arraySize ); // passing array a to modifyArray by reference


cout <<"The values of the modified array are:\n";

for ( int j = 0; j < arraySize; j++ )


cout << setw( 3 ) << a[ j ]; // displaying modified array elements

cout <<"\n\n\nEffects of passing array element by value:"


<<"\n\na[3] before modifyElement: "<< a[ 3 ] << endl;

modifyElement( a[ 3 ] ); // passing array element a[ 3 ] by value


cout <<"a[3] after modifyElement: "<< a[ 3 ] << endl;

return 0; // indicates successful termination


} // end main

// in function modifyArray, "b" points to the original array "a" in memory

void modifyArray( int b[], int sizeOfArray )


{

for ( int k = 0; k < sizeOfArray; k++ )


b[ k ] *= 2; // multiplying each array element by 2
} // end of unction modifyArray

// in function modifyElement, "e" is a local copy of array element a[ 3 ] passed from main

void modifyElement( int e )


{

cout <<"Value of element in modifyElement: "<< ( e *= 2 ) << endl; // multiply parameter by


2
}// end of function modifyElement
 
Passing an array to a function is an important array operation. When passing an array to a
function, the array size is normally passed as well, so the function can process the specific
number of elements in the array. C++ passes arrays to functions by reference; the value of the
name of the array is the address in the computer's memory of the first element of the array.
Because the starting address of the array is passed, the called function knows precisely where the
array is stored in memory. Therefore, when the called function modifies array elements in its
function body, it is modifying the actual elements of the array in their original memory locations.
Individual array elements are passed by value exactly as simple variables are.

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 linearSearch( constint [], int, int ); //function prototype

int main()
{
constint arraySize = 100; // size of array a
int a[ arraySize ]; // creating array a
int searchKey; // value to be located in array a

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


a[ i ] = 2 * i; // inserting data in the array

cout <<"Enter integer search key: ";


cin >> searchKey; // number to be searched in array taken as input

int element = linearSearch( a, searchKey, arraySize ); // attempt to locate searchKey in array a

// display results
if ( element != -1 )
cout <<"Found value in element "<< element << endl;
else
cout <<"Value not found"<< endl;

return 0; // indicates successful termination


} // end main

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

return -1; // key not found


} // end function linearSearch

 
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;

#include<iomanip>//declares the parameterized stream manipulators.

using std::setw;

#include<vector>
using std::vector;

void outputVector( const vector<int>& ); // display the vector


void inputVector( vector<int>& ); // input values into the vector

int main()
{
vector<int> integers1( 7 ); // 7-element vector< int >
vector<int> integers2( 10 ); // 10-element vector< int >

// print integers1 size and contents


cout <<"Size of vector integers1 is "<< integers1.size()
<<"\nvector after initialization:"<< endl;
outputVector( integers1 );

// print integers2 size and contents


cout <<"\nSize of vector integers2 is "<< integers2.size()
<<"\nvector after initialization:"<< endl;
outputVector( integers2 );

// input and print integers1 and integers2


cout <<"\nEnter 17 integers:"<< endl;
inputVector( integers1 );
inputVector( integers2 );

cout <<"\nAfter input, the vectors contain:\n"


<<"integers1:"<< endl;
outputVector( integers1 );
cout <<"integers2:"<< endl;
outputVector( integers2 );

// use inequality (!=) operator with vector objects


cout <<"\nEvaluating: integers1 != integers2"<< endl;

if ( integers1 != integers2 )
cout <<"integers1 and integers2 are not equal"<< endl;

// create vector integers3 using integers1 as an


// initializer; print size and contents
vector<int> integers3( integers1 ); // copy constructor

cout <<"\nSize of vector integers3 is "<< integers3.size()


<<"\nvector after initialization:"<< endl;
outputVector( integers3 );

// use overloaded assignment (=) operator


cout <<"\nAssigning integers2 to integers1:"<< endl;
integers1 = integers2; // integers1 is larger than integers2
cout <<"integers1:"<< endl;
outputVector( integers1 );
cout <<"integers2:"<< endl;
outputVector( integers2 );

// use equality (==) operator with vector objects


cout <<"\nEvaluating: integers1 == integers2"<< endl;

if ( integers1 == integers2 )
cout <<"integers1 and integers2 are equal"<< endl;

// use square brackets to create rvalue


cout <<"\nintegers1[5] is "<< integers1[ 5 ];

// use square brackets to create lvalue


cout <<"\n\nAssigning 1000 to integers1[5]"<< endl;
integers1[ 5 ] = 1000;
cout <<"integers1:"<< endl;
outputVector( integers1 );

// attempt to use out-of-range subscript


// cout << "\nAttempt to assign 1000 to integers1.at( 15 )" << endl;
// integers1.at( 15 ) = 1000; // ERROR: out of range
return 0;
} // end main

// output vector contents


void outputVector( const vector<int>&array )
{
size_t i; // declare control variable
for ( i = 0; i <array.size(); i++ )
{
cout << setw( 12 ) <<array[ i ];

if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output


cout << endl;
} // end for

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

double *xPtr, *yPtr;

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.

The following codes will clarify the use of pointers.

//lab4a.cpp
// Using subscripts and pointer notations with arrays.

#include<iostream>

using std::cout;
using std::endl;
int main()
{

int b[] = { 10, 20, 30, 40 }; // create 4-element array b


int *bPtr = b; // set bPtr to point to array b

cout <<"Array b printed with:\n\nArray subscript notation\n";


for ( int i = 0; i < 4; i++ )
cout <<"b["<< i <<"] = "<< b[ i ] <<'\n'; // output array b using array subscript notation

cout <<"\nPointer/offset notation where "<<"the pointer is the array name\n";

for ( int offset1 = 0; offset1 < 4; offset1++ )


cout <<"*(b + "<< offset1 <<") = "<< *( b + offset1 ) <<'\n'; // output array b using the array
name and pointer/offset notation

cout <<"\nPointer subscript notation\n";

for ( int j = 0; j < 4; j++ )


cout <<"bPtr["<< j <<"] = "<< bPtr[ j ] <<'\n';// output array b using bPtr and array
subscript notation

cout <<"\nPointer/offset notation\n";

for ( int offset2 = 0; offset2 < 4; offset2++ )


cout <<"*(bPtr + "<< offset2 <<") = "<< *( bPtr + offset2 ) <<'\n'; // output array b using
bPtr and pointer/offset notation

} // 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;

void cubeByReference( int * ); // function prototype

int main()

{
int number = 5;

cout <<"The original value of number is "<< number;


cubeByReference( &number ); // passing number address to cubeByReference

cout <<"\nThe new value of number is "<< number <<"\n"<< endl;


return 0; // indicates successful termination

} // 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

char *arrptr1;//declaring character


int i,j;

arrptr1=arr1;//pointer to arr1

cout<<"\nPrinting first array using pointer notation: ";

for(i=0;i<=14;i++)
{
cout<<*(arrptr1+i);
}

cout<<"\nPrinting first array using array notation: ";

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

cout<<arr1[i];
}

cout<<"\nPrinting second string using pointer notation: ";


for(i=0;i<=1;i++)
{
cout<<*(arr2+i)<<" ";
}

cout<<"\nPrinting second string using array notation: ";

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

cout<<arr2[i]<<" ";
}

cout<<"\nPrinting second array using 2D array notation: ";

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. 

The operation on I/O stream is shown in the following programs.

// 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;

cout <<"Enter a decimal number: ";


cin >> number; // input number

// use hex stream manipulator to show hexadecimal number


cout << number <<" in hexadecimal is: "<< hex
<< number << endl;

// use oct stream manipulator to show octal number


cout << dec << number <<" in octal is: "
<< oct << number << endl;

// use setbase stream manipulator to show decimal number


cout << setbase( 10 ) << number <<" in decimal is: "
<< number <<"\n\n"<< endl;

showb(number); //function call


prec();// function call

return 0;
} // end main

void showb (int a) //displaying number with the respective base using stream manipulator
showbase
{

cout <<"Printing number preceded by the base:"<< endl


<< showbase;

cout <<"Decimal: "<< a << endl; // print decimal value


cout <<"Hexadecimal: "<< hex << a << endl; // print hexadecimal value
cout <<"Octal: "<< oct << a <<"\n\n"<< endl; // print octal value

} //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

cout <<"value of square root of 2 with precisions 0-9."<< endl


<<"Precision set by ios_base member function "
<<"precision:"<< endl;

cout << fixed; // use fixed-point notation

// displaying root using ios_base function precision


for ( places = 0; places <= 9; places++ )
{
cout.precision( places );
cout << root << endl;
} // end for

cout <<"\nPrecision set by stream manipulator "


<<"setprecision:"<< endl;

// set precision for each digit, then display root


for ( places = 0; places <= 9; places++ )
cout << setprecision( places ) << root << endl;

} //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;

// display results of cin functions


cout <<"Before a bad input operation:"
<<"\ncin.rdstate(): "<< cin.rdstate()
<<"\n cin.eof(): "<< cin.eof()
<<"\n cin.fail(): "<< cin.fail()
<<"\n cin.bad(): "<< cin.bad()
<<"\n cin.good(): "<< cin.good()
<<"\n\nExpects an integer, but enter a character: ";

cin >> integerValue; // enter character value to have a bad input


cout << endl;

// display results of cin functions after bad input


cout <<"After a bad input operation:"
<<"\ncin.rdstate(): "<< cin.rdstate()
<<"\n cin.eof(): "<< cin.eof()
<<"\n cin.fail(): "<< cin.fail()
<<"\n cin.bad(): "<< cin.bad()
<<"\n cin.good(): "<< cin.good() << endl << endl;

cin.clear(); // clear stream

// display results of cin functions after clearing cin


cout <<"After cin.clear()"<<"\ncin.fail(): "<< cin.fail()
<<"\ncin.good(): "<< cin.good() << endl;

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 eofbit is set for an input stream after end-of-file is encountered.

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.

Following codes demonstrate a few string manipulation techniques.

// 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;

string2 = string1; // assign string1 to string2


string3.assign( string1 ); // assign string1 to string3
cout <<"string1: "<< string1 <<"\nstring2: "<< string2
<<"\nstring3: "<< string3 <<"\n\n";

int result = string1.compare( string2 ); //comparing string1 and string2

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

// modify string2 and string3


string2[ 0 ] = string3[ 2 ] = 'r';

cout <<"After modification of string2 and string3:\n"<<"string1: "


<< string1 <<"\nstring2: "<< string2 <<"\nstring3: ";

// demonstrating member function at


for ( int i = 0; i < string3.length(); i++ )
cout << string3.at( i );

// declare string4 and string5


string string4( string1 + "apult" ); // concatenation
string string5;

// overloaded +=
string3 += "pet"; // create "carpet"
string1.append( "acomb" ); // create "catacomb"

// append subscript locations 4 through end of string1 to


// create string "comb" (string5 was initially empty)
string5.append( string1, 4, string1.length() - 4 );

cout <<"\n\nAfter concatenation:\nstring1: "<< string1


<<"\nstring2: "<< string2 <<"\nstring3: "<< string3
<<"\nstring4: "<< string4 <<"\nstring5: "<< string5 << endl;

// comparing string1 (elements 2-5) and string3 (elements 0-5)


result = string1.compare( 2, 5, string3, 0, 5 );

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

cout <<"\nSubstring of string1: "<<string1.substr( 4, 4 ) <<"\n"<< endl;

//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:

targetString.assign(sourceString, start, numberOfCharacters );

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.

Similarly in result = string1.compare( 2, 5, string3, 0, 5 );the first two arguments (2 and 5)


specify the starting subscript and length of the portion of string1 to compare with string3. The
third argument is the comparison string. The last two arguments (0 and 5) are the starting
subscript and length of the portion of the comparison string being compared.

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.

Class string provides member function ‘swap’ for swapping strings.


//lab6b.cpp
// Demonstrating the string find member functions, string erasing, replacement and insertion

#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;

// find "is" at location 5 and 25


cout <<"Original string:\n"<< string1
<<"\n\n(find) \"is\" was found at: "<< string1.find( "is" )
<<"\n(rfind) \"is\" was found at: "<< string1.rfind( "is" );

// find 'o' at location 1


location = string1.find_first_of( "misop" );
cout <<"\n\n(find_first_of) found '"<< string1[ location ]
<<"' from the group \"misop\" at: "<< location;

// find 'o' at location 29


location = string1.find_last_of( "misop");
cout <<"\n\n(find_last_of) found '"<< string1[ location ]
<<"' from the group \"misop\" at: "<< location;

// find '1' at location 8


location = string1.find_first_not_of( "noi spm" );
cout <<"\n\n(find_first_not_of) '"<< string1[ location ]
<<"' is not contained in \"noi spm\" and was found at:"
<< location;

// find '.' at location 12


location = string1.find_first_not_of( "12noi spm" );
cout <<"\n\n(find_first_not_of) '"<< string1[ location ]
<<"' is not contained in \"12noi spm\" and was "
<<"found at:"<< location << endl;

// search for characters not in string1


location = string1.find_first_not_of(
"noon is 12 pm; midnight is not." );
cout <<"\nfind_first_not_of(\"noon is 12 pm; midnight is not.\")"
<<" returned: "<< location << endl;

//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

// replace all spaces with period


while ( position != string::npos )
{
string1.replace( position, 1, "." );
position = string1.find( " ", position + 1 );
} // end while

cout <<"\n\nAfter replacement: "<<string1<<endl;

//second repalcement
position = string1.find( "." ); // find first period

// replace all periods with two semicolons


// NOTE: this will overwrite characters
while ( position != string::npos )
{
string1.replace( position, 2, "xxxxx;;yyy", 5, 2 );
position = string1.find( ".", position + 1 );
} // end while

cout <<"After second replacement string1: "<< string1 << endl;

//string insertion
string string2( "beginning end" );
string string3( "middle " );

cout <<"\nString insertion\nInitial strings are:\nstring2: "<< string2


<<"\nstring3: "<< string3 <<"\n\n";
// insert "middle" at location 10 in string1
string2.insert( 10, string3 );

cout <<"Strings after insertion:\nstring2: "<< string2


<<"\nstring3: "<< string3 << endl;

return(0);
} // end main

The above code shows the use of string find member functions, string erasing, replacement and
insertion.

Member function rfind searchesstring1 backward (i.e., right-to-left).

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.

In the line,location = string1.find_first_not_of("noon is 12 pm; midnight is not." ); member


function find_first_not_of finds the first character not contained in "noon is 12 pm; midnight is
not." In this case, the string being searched contains every character specified in the string
argument. Because a character was not found, string::npos (which has the value 1 in this case) is
returned.

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

This lab is based on structures and manipulation of individual bits of data.


Structures are like "super array" of aggregate data types,that is, they can be built using elements of
several types. Structures are defined using the keyword struct followed by the structure name.
Structure members can be variables of the fundamental data types (e.g., int, double, etc.) or
aggregates, such as arrays, other structures and or classes and are placed within curly braces.
Each structure definition must end with a semicolon. Structure definition does not reserve any
space in memory; rather, it creates a new data type that is used to declare structure variables.
Structure variables are declared like variables of other types. Structures or their individual
members can also be passed in functions. You can access the individual elements of an array by
using a subscript. Dot (.), the structure member operator is used is the following way:

Structure variable.structure member

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.

The following program demonstrates the use of structures.


 
//lab7a.cpp
//Nested structure

#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" };

struct names { // first template


char first[LEN];
char last[LEN];
};

struct guy { // second template


struct names handle; // nested structure
char favfood[LEN];
char job[LEN];
float income;
};

int main(void)
{
struct guy fellow = { { "Chip", "Vejer" }, "nachos plate", "memory broker", 36827.00 }; //
initialize a variable

cout<<"Dear "<< fellow.handle.first <<"\n\n";


cout<< msgs[0]<< fellow.handle.first <<"\n";
cout<< msgs[1] << fellow.job <<"\n";
cout<< msgs[2]<<"\n";
cout<< msgs[3] << fellow.favfood << msgs[4];
if (fellow.income > 150000.0)
cout<<"!!";
elseif (fellow.income > 75000.0)
cout<<"!";
else cout<<".";
cout<<"\n"<< setw(40)<<"See you soon,";
cout<<"\n"<<setw(34)<<"Shalala\n";
return 0;
}
 

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;

cout<<"Enter first number: "; //taking user input for numbers


cin>>number1;

cout<<"Enter second number: ";


cin>>number2;

// demonstrate & operator

cout <<"\nUsing the bitwise AND operator &\n";


result=number1&number2;
cout <<"number1&number2= "<<result<<"\n\n"<<endl;

// demonstrate bitwise |

cout <<"Using the bitwise OR operator |\n";


result=number1|number2;
cout <<"number1|number2= "<<result<<"\n\n"<<endl;

// demonstrate bitwise exclusive OR

cout <<"Using the bitwise XOR operator ^\n";


result=number1^number2;
cout <<"number1^number2= "<<result<<"\n\n"<<endl;

// demonstrate bitwise right shift


cout <<"Using the bitwise right shift operator >>\n";
result=number1>>1;
cout <<"Shifting first number one bit to right: number1>>1= "<<result<<"\n\n"<<endl;

// demonstrate bitwise left shift

cout <<"Using the bitwise left shift operator >>\n";


result=number2<<1;
cout <<"Shifting second number one bit to left: number2<<1= "<<result<<"\n\n"<<endl;

return 0;
} // end main

The functions of the above used bitwise operators are:

Operator Name Description


& bitwise AND The bits in the result are set to 1 if the corresponding bits in the
two operands are both 1.
| bitwise inclusive The bits in the result are set to 1 if one or both of the
OR corresponding bits in the two operands is1.
^ bitwise exclusive The bits in the result are set to 1 if exactly one of the
OR corresponding bits in the two operands is 1.
<< left shift Shifts the bits of the first operand left by the number of bits
specified by the second operand; fill from right with 0 bits.
>> right shift with Shifts the bits of the first operand right by the number of bits
sign extension specified by the second operand; the method of filling from the
left is machine dependent.
~ bitwise All 0 bits are set to 1 and all 1 bits are set to 0.
complement
 

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

Covering advanced topics based on classes and objects.

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 definition

class Count
{
public:

void setX( int value ) // sets the value of private data member x
{
x = value;
} // end function setX

void print() // prints the value of private data member x

{
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

cout <<"Set x to 1 and print using the object's name: ";


counter.setX( 1 ); // setting data member x to 1
counter.print(); // calling member function print

cout <<"Set x to 2 and print using a reference to an object: ";


counterRef.setX( 2 ); // setting data member x to 2
counterRef.print(); // calling member function print

cout <<"Set x to 3 and print using a pointer to an object: ";


counterPtr->setX( 3 ); // setting data member x to 3
counterPtr->print(); // calling member function print
return 0;
} // end main

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;

#include"lab8b.h"// include CreateAndDestroy class definition


CreateAndDestroy::CreateAndDestroy( int ID, string messageString ) //
constructor

{
objectID = ID; // setting object's ID number
message = messageString; // set object's descriptive message

cout <<"Object "<< objectID <<" constructor runs "


<< message << endl;
} // end CreateAndDestroy constructor

CreateAndDestroy::~CreateAndDestroy() // destructor

{
cout << ( objectID == 1 || objectID == 6 ? "\n" : "" ); // output
newline for certain objects; helps readability

cout <<"Object "<< objectID <<" destructor runs "


<< message << endl;
} // end ~CreateAndDestroy destructor

// lab8b2.cpp
// Demonstrating the order in which constructors and destructors are called.

#include<iostream>
using std::cout;
using std::endl;

#include"lab8b.h"// include CreateAndDestroy class definition

void create( void ); // prototype

CreateAndDestroy first( 1, "(global before main)" ); // global object

int main()
{
cout <<"\nMAIN FUNCTION: EXECUTION BEGINS"<< endl;
CreateAndDestroy second( 2, "(local automatic in main)" );
static CreateAndDestroy third( 3, "(local static in main)" );

create(); // call function to create objects

cout <<"\nMAIN FUNCTION: EXECUTION RESUMES"<< endl;


CreateAndDestroy fourth( 4, "(local automatic in main)" );
cout <<"\nMAIN FUNCTION: EXECUTION ENDS"<< endl;
return 0;
} // end main

// function to create objects


void create( void )
{
cout <<"\nCREATE FUNCTION: EXECUTION BEGINS"<< endl;
CreateAndDestroy fifth( 5, "(local automatic in create)" );
static CreateAndDestroy sixth( 6, "(local static in create)" );
CreateAndDestroy seventh( 7, "(local automatic in create)" );
cout <<"\nCREATE FUNCTION: EXECUTION ENDS"<< endl;
} // end function create

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;

class Count // Count class definition

{
friendvoid setX( Count &, int ); // friend declaration

public:

Count() // constructor
: x( 0 ) // initialize x to 0
{
// empty body
} // end constructor Count

void print() const// output x


{
cout << x << endl;
} // end function print

private:

int x; // private member

}; // end class Count

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

cout <<"counter.x after instantiation: ";


counter.print();

setX( counter, 8 ); // set x using a friend function


cout <<"counter.x after call to setX friend function: ";
counter.print();
return 0;
} // end main

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

Working on operator and function overloading.

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.

Operator is overloaded by writing a non-static member function definition or global function


definition as you normally would, except that the function name now becomes the keyword
operator followed by the symbol for the operator being overloaded.

Operators that can be overloaded


+ - * / % ^ & |

~ ! = < > += -= *=

/= %= ^= &= |= << >> >>=

<<= == != <= >= && || ++

-- ->* , -> [] () new delete

new[] delete[]

Operators that cannot be overloaded


. .* :: ?:
The precedence of an operator cannot be changed by overloading. However, parentheses can be
used to force the order of evaluation of overloaded operators in an expression. Similarly, the
associativity of an operator (i.e., whether the operator is applied right-to-left or left-to-right)
cannot be changed by overloading. It is not possible to change the "arity" of an operator (i.e., the
number of operands an operator takes): Overloaded unary operators remain unary operators;
overloaded binary operators remain binary operators. C++'s only ternary operator (?:) cannot be
overloaded. Operators &, *, + and - all have both unary and binary versions; these unary and
binary versions can each be overloaded.

Operator precedence and associativity chart is as follows. Operators are shown in decreasing
order of precedence from top to bottom.

Operator Type Associativity


:: binary scope resolution left to right
:: unary scope resolution
() parentheses left to right
[] array subscript
. member selection via object
-> member selection via pointer
++ unary postfix increment
-- unary postfix decrement
typeid runtime type information
dynamic_cast< type > runtime type-checked cast
static_cast< type > compile-time type-checked cast
reinterpret_cast< type > cast for nonstandard conversions

const_cast< type > cast away const-ness


++ unary prefix increment right to left
-- unary prefix decrement
+ unary plus
- unary minus
! unary logical negation
~ unary bitwise complement
sizeof determine size in bytes
Operator Type Associativity
& address
* dereference
new dynamic memory allocation
new[] dynamic array allocation
delete dynamic memory deallocation
delete[] dynamic array deallocation
( type ) C-style unary cast right to left
.* pointer to member via object left to right
->* pointer to member via pointer
* multiplication left to right
/ division
% modulus
+ addition left to right
- subtraction
<< bitwise left shift left to right
>> bitwise right shift
< relational less than left to right
<= relational less than or equal to
> relational greater than
>= relational greater than or equal to
== relational is equal to left to right
!= relational is not equal to
& bitwise AND left to right
^ bitwise exclusive OR left to right
| bitwise inclusive OR left to right
&& logical AND left to right
|| logical OR left to right
Operator Type Associativity
?: ternary conditional right to left
= assignment right to left
+= addition assignment
-= subtraction assignment
*= multiplication assignment
/= division assignment
%= modulus assignment
&= bitwise AND assignment
^= bitwise exclusive OR assignment
|= bitwise inclusive OR assignment
<<= bitwise left-shift assignment
>>= bitwise right-shift assignment
, comma left to right

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"

// overloaded stream insertion operator; cannot be


// a member function if we would like to invoke it with
// cout << somePhoneNumber;
ostream &operator<<( ostream &output, const PhoneNumber &number )
{
output <<"("<< number.areaCode <<") "
<< number.exchange <<"-"<< number.line;
return output; // enables cout << a << b << c;
} // end function operator<<

// overloaded stream extraction operator; cannot be


// a member function if we would like to invoke it with
// cin >> somePhoneNumber;
istream &operator>>( istream &input, PhoneNumber &number )
{
input.ignore(); // skip (
input >> setw( 3 ) >> number.areaCode; // input area code
input.ignore( 2 ); // skip ) and space
input >> setw( 3 ) >> number.exchange; // input exchange
input.ignore(); // skip dash (-)
input >> setw( 4 ) >> number.line; // input line
return input; // enables cin >> a >> b >> c;
} // end function operator>>

int main()
{
PhoneNumber phone; // create object phone
cout <<"Enter phone number in the form (123) 456-7890:"<< endl;

// cin >> phone invokes operator>> by implicitly issuing


// the global function call operator>>( cin, phone )
cin >> phone;

cout <<"The phone number entered was: ";

// cout << phone invokes operator<< by implicitly issuing


// the global function call operator<<( cout, phone )
cout << phone << endl;
return 0;
} // end main

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:

operator>>( cin, phone );


When this call executes, reference parameter input becomes an alias for cin and reference
parameter number becomes an alias for phone. The operator function reads as strings the three
parts of the telephone number into the areaCode, exchange and line members of the
PhoneNumber object referenced by parameter number.

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

operator<<( cout, phone );

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:

// member prefix ++x


voidoperator++()
{
int x=5;
cout<<"Initially x="<<x;
cout<<"\tAfter using prefix increment opeartor x="<<++x<<"\n"<<endl;
}
};

class A2 { };

// non-member prefix ++x


voidoperator++(A2&)
{
int x=6;
cout<<"Initially x="<<x;
cout<<"\tAfter using prefix increment opeartor x="<<++x<<"\n"<<endl;
}
class A3 {
public:

// member postfix x++


voidoperator++(int)
{
int x=5;
cout<<"Initially x="<<x;
cout<<"\tAfter using postfix increment opeartor x="<<x++<<"\n"<<endl;
};
};

class A4 { };

// nonmember postfix x++


voidoperator++(A4&, int)
{
int x=5;
cout<<"Initially x="<<x;
cout<<"\tAfter using postfix increment opeartor x="<<x++<<"\n"<<endl;
};

int main()
{
A1 a1;
A2 a2;
A3 a3;
A4 a4;

// calls a1.operator++()
cout<<"Function call ++a1\n";
++a1;

// explicit call, like ++a1


cout<<"Function call a1.operator++()\n";
a1.operator++();

// calls operator++(a2)
cout<<"Function call ++a2\n";
++a2;

// explicit call, like ++a2


cout<<"Function call operator++(a2)\n";
operator++(a2);
// calls a3.operator++(0)
// default argument of zero is supplied by compiler
cout<<"Function call a3++\n";
a3++;

// explicit call to member postfix a3++


cout<<"Function call a3.operator++(0)\n";
a3.operator++(0);

// calls operator++(a4, 0)
cout<<"Function call a4++\n";
a4++;

// explicit call to non-member postfix a4++


cout<<"Function call operator++(a4,0)\n";
operator++(a4, 0);
}

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.

Following is a code based on inheritance.

//lab10.cpp
//Inheritance

#include<iostream>
using std::cin;
using std::cout;
using std::endl;

#include<string>
using std::string;

class emp //base class


{
public:
void get()
{

cout<<"Enter the employee name:"; //user input


cin>>name;
cout<<"Enter the designation:";
cin>>des;

}
protected://protected members of base class that can be accessed by the derived class

string name;
string des;

};

class salary:public emp //derived class (inheritance)


{
float bs,ha,net;

public:
void get1()
{

cout<<"Enter the basic salary: ";


cin>>bs;
}

void calculate() //claculating net salary


{
rate=0.05;
ha=bs*rate;
net=bs+ha;
}

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;
}

private: //private member of the derived class


float rate;
};

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.

Following programs are based on virtual functions and abstract classes.

//lab11a.cpp
//Virtual functions

#include<iostream>
using std::cout;
using std::endl;
class CBox // Base class
{
public:

// Function to show the volume of an object


void ShowVolume() const
{
cout<<Volume();
}

// Function to calculate the volume of a CBox object


virtualdouble Volume() const
{
return m_Length*m_Width*m_Height;
}

// 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;
};

class CGlassBox: public CBox // Derived class


{
public:
// Function to calculate volume of a CGlassBox
// allowing 15% for packing

virtualdouble Volume() const


{
return 0.85*m_Length*m_Width*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

cout<<"Volume of CBox: ";


myBox.ShowVolume(); // Display volume of base box
cout<<endl;

cout<<"Volume of CGlassBox: ";


myGlassBox.ShowVolume(); // Display volume of derived box

cout << endl;


return 0;
}

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:

void set_values (int a, int b)


{
width=a; height=b;
}
virtualint area (void) =0; //pure virtual function
void printarea (void)
{
cout <<this->area() << endl;
}
};

class CRectangle: public CPolygon { //derived class


public:

int area (void)


{
return (width * height);
}

};

class CTriangle: public CPolygon { //derived class


public:

int area (void)


{
return (width * height / 2);
}
};

int main () {
CRectangle rect; //derived class objects
CTriangle trgl;

CPolygon * ppoly1 = &rect; //pointer to derived classes


CPolygon * ppoly2 = &trgl;
ppoly1->set_values (4,5); //accessing base class members
ppoly2->set_values (4,5);

cout<<"Area of rectangle is: ";


ppoly1->printarea(); //Area calculated according to function declaration in the class CRectangle

cout<<"Area of triangle is: ";


ppoly2->printarea(); //Area calculated according to function declaration in the class CTriangle
return 0;
}

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

//function templates and class templates

#include<iostream>

using std::cout;

using std::endl;

template<class T>//class template

class mypair

T a, b; //variables a and b having type T

public:

mypair (T first, T second)//constructor

a=first; //setting the values

b=second;

T getmax ();

};

template<typename T>//function template (we can use the word class instead of typename with
T)

T mypair<T>::getmax ()//function definition


{

T retval; //T type variable

retval = a>b? a : b;//ternary opeartor

return retval;//returning maximum value

int main () {

mypair <int> myobject (75, 100);//T replaced in the class and function with int as declared in
function call

cout <<"The greater number is: "<<myobject.getmax()<<endl;

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

using std::runtime_error; // standard C++ library class runtime_error

#include<iostream>

using std::cin;

using std::cout;

using std::endl;

// DivideByZeroException objects should be thrown by functions

// upon detecting division-by-zero exceptions

class DivideByZeroException : public runtime_error

public:

// constructor specifies default error message

DivideByZeroException::DivideByZeroException()

: runtime_error( "attempted to divide by zero" ) {}

}; // end class DivideByZeroException

// perform division and throw DivideByZeroException object if

// divide-by-zero exception occurs

double quotient( int numerator, int denominator )

// throw DivideByZeroException if trying to divide by zero

if ( denominator == 0 )

throw DivideByZeroException(); // terminate function


// return division result

returnstatic_cast<double>( numerator ) / denominator;

} // end function quotient

int main()

int number1; // user-specified numerator

int number2; // user-specified denominator

double result; // result of division

cout <<"Enter two integers (end-of-file to end): ";

// enable user to enter two integers to divide

while ( cin >> number1 >> number2 )

// try block contains code that might throw exception

// and code that should not execute if an exception occurs

try

result = quotient( number1, number2 );

cout <<"The quotient is: "<< result << endl;

} // end try

// exception handler handles a divide-by-zero exception


catch ( DivideByZeroException &divideByZeroException )

cout <<"Exception occurred: "

<< divideByZeroException.what() << endl;

} // end catch

cout <<"\nEnter two integers (end-of-file to end): ";

} // end while

cout << endl;

return 0; // terminate normally

} // 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.

Firstly, class DivideByZeroException is declared as a derived class of Standard Library class


runtime_error (defined in header file <stdexcept>).A typical exception class that derives from the
runtime_error class defines only a constructor that passes an error-message string to the base-
class runtime_error constructor. Every exception class that derives directly or indirectly from
exception contains the virtual function what, which returns an exception object's error message.

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:

File open modes.


Mode Description
ios::app Append all output to the end of the file.
ios::ate Open a file for output and move to the end of the file
(normally used to append data to a file). Data can be written
anywhere in the file.
ios::in Open a file for input.
ios::out Open a file for output.
ios::trunc Discard the file's contents if they exist (this also is the
default action for ios::out).
ios::binary Open a file for binary (i.e., nontext) input or output.

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:

ios::beg (the default) Positions relative to the beginning of a stream


ios::cur Positions relative to the current position in a stream
ios::end Positions relative to the end of a stream.

Few examples are:

// position to the nth byte of fileObject (assumes ios::beg)


fileObject.seekg( n );

// position n bytes forward in fileObject


fileObject.seekg( n, ios::cur );

// position n bytes back from end of fileObject


fileObject.seekg( n, ios::end );

// position at end of fileObject


fileObject.seekg( 0, ios::end );

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<fstream>// file stream


using std::fstream; // output file stream
#include<iomanip>
using std::setw;
using std::fixed;
using std::showpoint;
using std::setprecision;
using std::right;
using std::left;

#include<cstdlib>
using std::exit; // exit function prototype

int main()
{

fstream ClientFile( "client.txt", ios::in | ios::app); // fstream constructor opens file

// exit program if unable to create file


if ( !ClientFile ) // overloaded ! operator
{
cerr <<"File could not be opened"<< endl;
exit( 1 );
} // end if

cout <<"Enter the account, name, and balance."<< endl


<<"Enter end-of-file to end input.\n? ";

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

ClientFile.seekg( 0,ios::beg ); //repositioning file-position pointer to the beginning of the


file

cout << left << setw( 10 ) <<"Account"<< setw( 13 )


<<"Name"<<"Balance"<< endl << fixed << showpoint;
while ( ClientFile >> account >> name >> balance ) // displaying each record in file
cout << left << setw( 10 ) << account << setw( 13 ) << name
<< setw( 7 ) << setprecision( 2 ) << right << balance << endl;

return 0; // fstream destructor closes the file


} // end main

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.

Potrebbero piacerti anche