AbstractClass
1. Make Polygon as abstract class. Now override the virtual method printArea() in Rectangle class, but not in Triangle class. In main function create objects of Polygon, Rectangle and Triangle. What do you observe? Why?
polygon.h class polygon { protected: int num_sides; public: polygon(int nsides=3); ~polygon(); virtual void printArea()=0; }; Rectangle.h #include"polygon.h" class Rectangle : public polygon { int wid,len; public: Rectangle(int w=1,int l=1); ~Rectangle(); void printArea(); }; triangle.h #include<iostream> #include"polygon.h" class triangle:public polygon { int base,height; public: triangle(int b=1,int h=1):base(b),height(h){} }; main.cpp #include <iostream> using namespace std; #include"polygon.h" #include "Rectangle.h" #include "triangle.h" int main(int argc, char **argv) { polygon p; Rectangle r; triangle t; } Note :Rectangle.cpp file not shown here. The program gives error Can not declare variable p of abstract class polygon Can not declare variable t of abstract class triangle Since polygon has a pure virtual function, it is an abstract class and objects can not be created from it. Triangle class is inheriting this pure virtual function and is not overriding it. So triangle class is also an abstract class.
2. Make the destructor of Polygon pure virtual, instead of printArea method? Is it possible?
It is possible and it is advisable to make destructor of a class virtual if the class has dynamic memory in it. polygon.h class polygon { protected: int num_sides; public: polygon(int nsides=3); virtual ~polygon()=0; virtual void printArea(); };
Classes and Objects
3. Write a class student with data members name and id. Write 4 methods getName(), setName(char*), getId() and setId(int). The default constructor must take default values 0 for id, "noname" for name. Write main function which creates 4 different student objects and prints them.
Student.h #ifndef STUDENT_H #define STUDENT_H class Student { char name[30]; int id; public: Student(); Student(char *name,int id); ~Student(); char* get_name(); int get_id(); void set_name(char *n); void set_id(int n); }; #endif // STUDENT_H Student.cpp #include<iostream> #include "Student.h" #include<cstring> using std::strcpy; using std::cout; Student::Student():id(0) { strcpy(name,"noname"); cout<<"Default constructor\n"; } Student::~Student() { cout<<"destrutor\n"; } Student::Student(char *name,int id2):id(id2) { strcpy(this->name,name); cout<<"2 param constructor\n"; } void Student::set_name(char *name ) { strcpy(this->name,name); } void Student::set_id( int id) { this->id = id; } char * Student::get_name() { return name; } int Student::get_id() { return id; } main.cpp #include <iostream> #include"Student.h" using namespace std; void print_details(Student s) { cout<<"Name "<<s.get_name()<<"\n"; cout<<"Id "<<s.get_id()<<"\n"; } int main( ) { Student s1; cout<<"name of student"; string name; cin>>name; cout<<"id ="; int id; cin>>id; Student s2((char*)name.c_str(),id); print_details(s1); print_details(s2); return 0; }
Observe how many times destructor is being called? Why?
4. Write a class point with x and y co-ordinates, constructor, default constructor, getters and setters. Write a non-member function which finds the length of the straight line with the given end points.
point.h #include<fstream> using std::ostream; using std::istream; class point { float x; float y; public: point(float m ,float n ); point(); float getx() ; float gety() ; void setx(const float & a); void sety(const float & b); }; point.cpp #include"point.h" /*para ctor*/ point::point(float a,float b):x(a),y(b) { } /*default ctor*/ point::point() { x = y = 0; } /*setters*/ void point::setx(const float &a) { x = a; } void point::sety(const float &b) { y = b; } /*getters*/ float point::getx() { return x; } float point::gety() { return y; } main.cpp #include<iostream> #include<cmath> #include"point.h" using namespace std; float lineLength(point p1,point p2) { float xdiff = p2.getx()-p1.getx(); float ydiff = p2.gety() -p1.gety(); float dist = sqrt(xdiff*xdiff + ydiff*ydiff); return dist; } int main() { point p1; point p2; cout<<"Enter first point"; float a,b; cin>>a>>b; p1.setx(a); p1.sety(b); cout<<"Enter second point"; cin>>a>>b; p2.setx(a); p2.sety(b); cout<<"Length of straight line betn the points is "<<lineLength(p1,p2); return 0; }
5. Write a class to implement a singly linked list of integers. The class must have append, insert(pos,val), size(), delete(val), search(val), iterate() functions.
#include<iostream> using std::cout; class node { public: int n; class node *next; }; class sll { node *head; public: sll(); sll(int val); void append(int num); void insert(int num,int pos); void iter(); node *getLastNode(); ~sll(); }; node *createNode(int n) { node * temp = new node; temp->n = n; temp->next = NULL; return temp; } sll::sll() { head = NULL; } sll::sll(int val) { node *nd = createNode(val); head = nd; } node* sll::getLastNode() { node*temp = head; while(temp && temp->next!=NULL) temp = temp->next; return temp; } void sll::append(int num) { node *nd = createNode(num); node* lastnode = getLastNode(); if(lastnode!=NULL) { lastnode->next = nd; } else { head = nd; } } void sll::insert(int num,int pos) { node *nd = createNode(num); //go to node pos-1 node *temp = head; node * prevnd; for (int i=1;temp&&i<=pos;i++,temp=temp->next ) prevnd = temp; if(temp==NULL) { delete nd; append(num); } nd->next = prevnd->next; prevnd->next = nd; } void sll::iter() { node *temp = head; while(temp->next) { cout<<temp->n<<"=>"; temp = temp->next; } if(temp) cout<<temp->n; } sll::~sll() { //delete all the nodes node *temp = head; while(temp) { node *nextnode = temp->next; cout<<"Deleting the node"<<temp->n<<"\n"; delete temp; temp = nextnode; } head = NULL; } int main() { sll obj; for(int i=1;i<10;i++) { obj.append(i*i); } obj.insert(2000,3); obj.iter(); }
Note that destructor deletes all the nodes of singly linked list
6. Write a class pen with price as data member and constructor. Create a static member function which prints "Pen is mightier than sword". Can this function print price of the pen?
#include<iostream> using std::cout; class Pen { float price; public: Pen(float p=10); static void printMighty(); }; Pen::Pen(float p ):price(p){} void Pen::printMighty() { cout<<"Pen is mightier than sword"; } int main() { Pen obj(5); obj.printMighty(); }
No. Because a static function can access only static data members of the class.
7. Write a class Student with an id and name as data members. name should be a char pointer. Write constructors and destructors and a function which finds if the name of the student is Kumar. What happens when you do not define copy constructor?
#include<iostream> #include<cstring> using std::cout; using std::cin; class Student { int id; char *name; public: Student( char *s,int id); Student(const Student & sobj);//copy constructor char *getName(); int getId(); void setName(char *s); void setId(int n); ~Student(); Student & operator = (const Student & other);//assignment operator }; Student::Student(char *s,int id=0) { this->id = id; int len = strlen(s); name = new char[len]; strcpy(name,s); } Student::~Student() { delete[] name; } Student::Student(const Student& sobj) { id = sobj.id; name = new char[strlen(sobj.name)]; strcpy(name,sobj.name); } Student & Student::operator =(const Student &other) { if (this!=&other)//not self assignment { delete []name; id = other.id; name = new char[strlen(other.name)]; strcpy(name,other.name); } return *this; } char *Student::getName() { return name; } int Student::getId() { return id; } void Student::setId(int n) { id = n; } void Student::setName(char *s) { delete name; name = new char[strlen(s)]; strcpy(name,s); } bool isNameKumar(Student sobj) { if(strcmp(sobj.getName(),"Kumar")==0) return true; return false; } int main() { Student s1("Hari",1); Student s2("Kumar",2); if(isNameKumar(s2)) { cout<<"this student is Kumar"; } }
8. Create 2 pointers to Point class. Set x and y values to these points and print their distances from origin.
main.cpp #include<iostream> #include<cmath> #include"point.h" using namespace std; float dist(const point * p1) { float sum = p1->gety()*p1->gety()+p1->getx()*p1->getx(); return sqrt(sum); } int main() { point *p1 = new point(11,22); point *p2 = new point(1,223); cout<<"Distance of first point from origin is "<<dist(p1)<<endl; cout<<"Distance of second point from origin is "<<dist(p2)<<endl; delete p1; delete p2; }
Note that the pointers should be explicitly released using delete.
9. Create an array of points using new operator. Now print the total number of points in each of the quadrants. Do not forget to release the memory at the end.
main.cpp #include<iostream> #include<cmath> #include"point2.h" using namespace std; void readPoints(point *parr,int len) { for(int i=0;i<len;i++) { float a,b; cout<<"Enter x and y of point "<<i+1<<":"; cin>>a>>b; parr[i].setx(a); parr[i].sety(b); } } void countQuadrants(point *parr,int len, int&q1,int&q2,int&q3,int&q4) { for(int i=0;i<len;i++) { float x = parr[i].getx(); float y = parr[i].gety(); if(x>0 &&y>0) q1++; else if(x<0 &&y>0) q2++; else if(x<0 &&y<0) q3++; else if(x>0 &&y<0) q4++; } } int main() { point *parr = new point[6]; readPoints(parr,6); int quad1,quad2,quad3,quad4; quad1 = quad2 = quad3 = quad4 = 0; countQuadrants(parr,6,quad1,quad2,quad3,quad4); cout<<"Points in first quadrant are "<<quad1<<endl; cout<<"Points in sedond quadrant are "<<quad2<<endl; cout<<"Points in third quadrant are "<<quad3<<endl; cout<<"Points in fourth quadrant are "<<quad4<<endl; delete []parr; }
10. Write a class for Stack in C++. Implement the methods, push, pop and isEmpty methods along with constructor and destructor.
Stack.h #include<vector> class VecStack { std::vector<int> elements; public: VecStack(); ~VecStack(); void push(int value); int pop(); bool empty(); }; #define ERR_CODE -1000 Stack.cpp #include "VecStack.h" VecStack::VecStack() { } VecStack::~VecStack() { elements.clear(); } void VecStack::push(int value) { elements.push_back(value); } int VecStack::pop() { if(empty()) { return ERR_CODE; } int size = elements.size(); int val = elements[size-1]; elements.pop_back(); return val; } bool VecStack::empty() { return !elements.size(); } main.cpp #include <iostream> using std::cin; using std::cout; #include"VecStack.h" int main(int argc, char **argv) { VecStack stack; for(int i=0;i<5;i++) { int val; cout<<"value:"; cin>>val; stack.push(val); } while(!stack.empty()) { cout<<stack.pop(); } return 0; }
Here stack is implemented using STL vector instead of arrays or linked lists.
Composition
11. Write a class Vehicle which has an object of Engine class in it.
#include<iostream> using namespace std; class Engine { float capacity; public: Engine(float c):capacity(c) { cout<<"Engine constructor"; } ~Engine( ) { cout<<"Engine destructor"; } }; class Vehicle { Engine e1; public: Vehicle(float cap):e1(cap) { cout<<"Vehicle constructor"; } ~Vehicle() { cout<<"Engine constructor"; } }; int main() { Vehicle v1(1.25); }
Const
12. Write a function which takes two constant reference parameters x and y. Now increment both of them and return their product. What is the result? Why?
#include <iostream> using namespace std; int product(const int &n1, const int &n2) { n1++; n2++; return n1*n2; } int main() { int a= 10; int b = 100; cout<<product(a,b); }
The program gives 2 compiler errors - increment of read only reference n1 and error - increment of read only reference n2.
A constant reference can not be modified.
13. Can a class have const data members? If yes, how are they initialized? Write a class Student with name as constant data member. Create 3 objects of this class and print the names.
Yes Constant data memebers are initialized using member initializer lists in constructor. Student.h #ifndef STUDENT_H #define STUDENT_H #include<iostream> using std::string; class Student { const string name; int id; public: Student(); Student(string name,int id); ~Student(); string get_name(); int get_id(); void set_name(string n); void set_id(int n); }; #endif // STUDENT_H Student.cpp #include<iostream> #include "Student.h" #include<cstring> using std::strcpy; using std::cout; using std::string; Student::Student():id(0),name("noname") { cout<<"Default constructor\n"; } Student::~Student() { cout<<"destrutor\n"; } Student::Student(string n,int id2):id(id2), name(n) { cout<<"2 param constructor\n"; } void Student::set_name(string name ) { // this->name = name; } void Student::set_id( int id) { this->id = id; } string Student::get_name() { return name; } int Student::get_id() { return id; } main.cpp #include <iostream> #include"Student.h" using namespace std; void print_details(Student s) { cout<<"Name "<<s.get_name()<<"\n"; cout<<"Id "<<s.get_id()<<"\n"; } int main( ) { Student s1; cout<<"name of student"; string name; cin>>name; cout<<"id ="; int id; cin>>id; Student s2(name ,id); print_details(s1); print_details(s2); return 0; }
14. Write a function printNumber which prints the data of Number object. The parameter to the function must be constant reference. But the object must remember how many times it has been printed so far.
A.h class Number { char num; mutable int numTimesPrinted; public: Number(char n); Number(const Number &obj); ~Number(); void setNum(char m); char getNum(); void printNum() const; }; A.cpp #include "A.h" #include<iostream> using std::cout; Number::Number(char n) { this->num = n; numTimesPrinted = 0; } Number::~Number() { std::cout<<"Destructor of "<<num<<std::endl; } Number::Number(const Number &obj) { this->num = obj.num; std::cout<<"copy constructor is called"; numTimesPrinted = 0; } void Number::setNum(char m) { num = m; } char Number::getNum() { return num; } void Number::printNum() const { cout<<"The number is "<<(int)num; numTimesPrinted++; cout<<"The object is calling printNum function "<<numTimesPrinted<<" times\n"; } main.cpp #include <iostream> #include"A.h" using namespace std; void globPrint(const Number &obj) { obj.printNum(); obj.printNum(); } int main() { Number obj1('a'); obj1.printNum(); obj1.printNum(); Number obj2('b'); obj2.printNum(); globPrint(obj1); return 0; }
There are two aspects to the mutable data - numTimesPrinted. This basically tells you how many times printNum is called on the given object.
Do not confuse it with static data member. numTimesPrinted does not tell you how many times printNum is called for all the objects.
See the speciality of this data member.
1) Even in const function we are able to modify this data member.
2) The global function - globPrint() which receives a constant reference is able to modify this mutable data member through the printNum function
15. Use the Point class written earlier. Send a constant reference to a function. Now change the x and y of the first object to 10 and 30 respectively using setters. Will the program compile? Why? Now can the constant object call this getx() function? Why?
Use previous point.h and point.cpp main.cpp #include<iostream> using namespace std; #include"point.h" void foobar(const point &p1) { p1.setx(10);//error p1.sety(30);//error cout<<p1.getx();//error } int main() { point p1; foobar(p1); }
The constant object is unable to call setx() or sety() because, we can not change the state of a constant object.
The object can not call getx() or gety() also because they are const function. So they are not promising that they won't change the state of the object.
A constant object can call only const function.
16. In the point class make getx and gety and constant functions. Now create 2 constant Points. Can we display x and y of the points now in main function? How? Why?
point.h #include<fstream> using std::ostream; using std::istream; class point { float x; float y; public: point(float m =0,float n=0 ); ~point(); float getx() const; float gety() const ; void setx(const float & a); void sety(const float & b); }; point.cpp #include"point.h" #include<iostream> using std::cout; point::point(float a,float b):x(a),y(b) { cout<<"Constructor is called\n"; } void point::setx(const float &a) { x = a; } void point::sety(const float &b) { y = b; } float point::getx() const { return x; } float point::gety() const { return y; } point::~point() { cout<<"Destructor is called\n"; } main.cpp #include<iostream> #include<cmath> #include"point2.h" using namespace std; void foobar(const point &p1) { /* p1.setx(10);//error p1.sety(30);//error*/ cout<<p1.getx();//error } int main() { point p1; foobar(p1); }
The program works fine because a constant object can call constant function. getx() is a constant function.
Constructor
17. Write a constructor to the class Point which has two data members x and y. If the parameters are not given, x and y should have the value 0 and 0
class Point { float x,y; public: Point(float a=0,float b=0); }; Point::Point(float a,float b):x(a),y(b){}
Constructor is using default arguments for all its parameters. So it can be used even without any argument.
That is to say it is a default constructor also.
And the constructor uses member initializer list to set values to x and y
18. Write a class RealNumber with one data which is double. Write a constructor for this class which also works as default constructor. Create an object of this class called rObj. Now assign rObj to a double variable a.
#include<iostream> using std::cout; class RealNumber { double num; public: RealNumber(double m=0):num(m){std::cout<<"ctor";} }; int main( ) { RealNumber nobj(11); double d1 = 1.2; nobj = d1; }
The constructor is called twice even though only one object is created.
When there is conversion from basic data type to object, it will use the constructor with that type as single parameter. In this case conversion from double to RealNumber object uses the constructor.
If you do not want this implicit conversion, you should add "explicit" word before constructor.
19. Write a class Point with only one constructor with two float parameters for x and y. Now create an array of 10 points in main(). Will the program compile? Why? Now comment the constructor and compile the program again. Now will the program compile? Why?
Point.h class Point { float x,y; public: Point(float a,b):x(a),y(b){} float getx(); float gety(); }; Point.cpp #include"Point.h" float Point::getx() { return x; } float Point::gety() { return y; } main.cpp #include<iostream> #include"Point.h" using std::cout; int main() { Point pobj_arr[10]; }
The program does not compile because array creation calls implicitly the constructor for each array element which requires a default constructor. Since Point class has no default constructor, there is compilation error.
When we comment out the constructor, the compiler provides a default constructor for the class. Because compiler provides a default constructor only when the class has no user defined constructor. That is the reason why the program will compile now.
20. Write a copy constructor for class MyArray which is a dynamic array of integers. Creates an object. Create second object as a copy of first object. What happens when you comment out the copy ctor? Why?
MyArray.h #ifndef MYARRAY_H #define MYARRAY_H class MyArray { int *elements; int len; public: MyArray(int len=5); ~MyArray(); MyArray(const MyArray & obj1); }; #endif // MYARRAY_H MyArray.cpp #include "MyArray.h" MyArray::MyArray(int len) { this->len = len; elements = new int[len]; for(int i=0;i<len;i++) elements[i]=0; } /* copy ctor*/ MyArray::MyArray(const MyArray &obj1) { this->len = obj1.len; elements = new int[len]; for(int i=0;i<len;i++) elements[i]=obj1.elements[i]; } MyArray::~MyArray() { delete []elements; } main.cpp#include <iostream> #include"MyArray.h" using namespace std; int main() { MyArray obj(10); MyArray obj2 = obj; }
If copy ctor is not present - that is , when the program uses compiler provided copy constructor, the program crashes. Because, elements is dynamically created array and compiler provided copy ctor does shallow copy that is it just copies the pointer value to elements without actually creating a new block of memory.
When obj2 is destroyed, memory block is released. But elements of obj1 also points to this memory. During destruction of obj1, the program tries to release a dangling pointer. And it crashes.
21. Write a class Number with a byte sized number as data. Now write a ctor and copy ctor to this class. Show the different situations when this copy ctor is called.
A.h class Number { char num; public: Number(char n); Number(const Number &obj); ~Number(); void setNum(char m); char getNum(); }; A.cpp #include "A.h" #include<iostream> Number::Number(char n) { this->num = n; } Number::~Number() { std::cout<<"Destructor of "<<num<<std::endl; } Number::Number(const Number &obj) { this->num = obj.num; std::cout<<"copy constructor is called"; } void Number::setNum(char m) { num = m; } char Number::getNum() { return num; } main.cpp #include <iostream> #include"A.h" using namespace std; Number print_diff(Number obj1,Number &obj2) { int m = obj1.getNum() - obj2.getNum(); cout<<"Difference is "<<m<<"\n"; cout<<"Returning an object"; return Number(m); } int main() { Number obj1('a'); cout<<"copy creation\n"; Number obj2 = obj1; obj1.setNum('\01'); cout<<"obj1 is "<<(int)(obj1.getNum())<<endl; cout<<"Assignment\n"; obj2 = obj1; obj1.setNum(104); obj2.setNum(66); cout<<"function call with 2 Number parameters - first value, second reference\n"; print_diff(obj1,obj2); return 0; }
22. To a class Point, add a destructor which just prints the message "destructor is called" Create a function which prints the length of the straight line joining these two points . Points should be parameters to the function. Now observe the destructor calls. Can you explain the reason for anamoly.
point.h class point { float x; float y; public: point(float m =0,float n=0 ); ~point(); float getx() ; float gety() ; void setx(const float & a); void sety(const float & b); }; point.cpp #include"point.h" #include<iostream> using std::cout; point::point(float a,float b):x(a),y(b) { cout<<"Constructor is called\n"; } /*setters*/ void point::setx(const float &a) { x = a; } void point::sety(const float &b) { y = b; } /*getters*/ float point::getx() { return x; } float point::gety() { return y; } point::~point() { cout<<"Destructor is called\n"; } main.cpp #include<iostream> #include<cmath> #include"point.h" using namespace std; float lineLength(point p1,point p2) { float xdiff = p2.getx()-p1.getx(); float ydiff = p2.gety() -p1.gety(); float dist = sqrt(abs(xdiff*xdiff + ydiff*ydiff)); return dist; } int main() { point p1; point p2; cout<<"Enter first point"; float a,b; cin>>a>>b; p1.setx(a); p1.sety(b); cout<<"Enter second point"; cin>>a>>b; p2.setx(a); p2.sety(b); cout<<"Length of straight line betn the points is "<<lineLength(p1,p2); return 0; }
The program calls point destructor 4 times and constructor 2 times.
The reason is the parameters to the function are value parameters of point class. They are copied to the function using copy constructor - which is compiler provided. And when the function exits, these objects are destroyed using the destructor.
23. How many constructors can a class have? How many destructors can it have? Write a class A with constructor and destructor. Now create a local object, a global object, and an object within a block. When are the constructors of these objects called? When are destructors called?
A class can have multiple constructors. That is to say constructors of a class can be overloaded. But class can have only one destructor. Because destructor does not take parameters, there is no way in which it can be overloaded. A.h class A { char name[30]; public: A(char *n); A(); ~A(); }; A.cpp #include "A.h" #include<iostream> #include<cstring> A::A() { std::strcpy("noname",name); std::cout<<"Default constructor"<<std::endl; } A::A(char *n) { std::strcpy(name,n); std::cout<<"Constructor of "<<name<<std::endl; } A::~A() { std::cout<<"Destructor of "<<name<<std::endl; } main.cpp #include <iostream> #include"A.h" using namespace std; void some_function() { A obj("function object"); } A obj1("global"); int main() { cout<<"We are in the main function\n"; A obj2("local1"); some_function(); A obj3("local2"); }
Constructor of global object is called before main. Destructor of global object is called when the program ends. Local object constructor is called when it is defined. Its destructor is called when its block exits.
DynamicMemory
24. Write a program to create an array of doubles. The array should be created using dynamic memory allocation. Print the product of all the elements of the array.
#include <iostream> using namespace std; void print_array(int *arr,int len) { for(int i=0;i<len;i++) { cout<<arr[i]; if(i<len-1) cout<<","; } } void read_array(float *arr,int len) { for(int i=0;i<len;i++) { cout<<"arr["<<i<<"]="; cin>>arr[i]; } } float find_product(float *arr,int len) { float product = arr[0]; for(int i=0;i<len;i++) { product *=arr[i]; } return product; } int main() { float *arr = new float[5]; read_array(arr,5); float product = find_product(arr,5); cout<<"Product of elements is "<<product; delete []arr; return 0; }
ExceptionHandling
25. Write a program with a function to give quotient of two numbers. When denominator is zero the program should throw an integer exception. Handle the exception in the function.
#include <iostream> using namespace std; #define ERR_CODE -1000 float quotient(int n1,int n2) { try{ if(n2==0) throw int(10); float ans = (float)n1/n2; return ans; } catch(int error1) { cout<<"Attempt to divide by 0"; return ERR_CODE; } } int main() { int m; int n; cout<<"Enter 2 integers "; cin>>m>>n; float ans = quotient(m,n); if(ans!=ERR_CODE) cout<<"Answer is"<<ans; }
26. Write a program with div function to return quotient of two numbers. When denominator is zero the program should throw an integer exception. Handle the exception in main function.
#include <iostream> using namespace std; #define ERR_CODE -1000 float div(int n1,int n2) { if(n2==0) throw int(10); float ans = (float)n1/n2; return ans; } int main() { int m; int n; cout<<"Enter 2 integers "; cin>>m>>n; try{ float ans = div(m,n); cout<<"Quotient is"<<ans; } catch(int error1) { cout<<"Attempt to divide by 0"; } } The function exits and passes on the exception to main function. In main(), the exception is handled. If main could not handle the exception, then the program crashes.
27. Modify the program to demonstrate stack unwinding during exception handling. Create two objects of some class in the function. and observe the destructors being called.
class A { public: A(){cout<<"A constructor";} ~A(){cout<<"A destructor";} }; class DivError {}; float div(int n1,int n2) { A obj1; A obj2; if(n2==0) throw DivError(); float ans = (float)n1/n2; return ans; } int main() { int m; int n; cout<<"Enter 2 integers "; cin>>m>>n; try{ float ans = div(m,n); cout<<"Quotient is"<<ans; } catch(DivError error1) { cout<<"Attempt to divide by 0"; } }
obj1 and obj2 destructors are called after the exception is thrown. So any local objects are destructed(!), when exception is transferred to caller function.
Also note that in this program, the exception thrown is an object, not POD
28. Modify the above program so that the catch block catches only float exception. What happens to program? Are the destructors of objects being called?
#include <iostream> using namespace std; #define ERR_CODE -1000 class A { public: A(){cout<<"A constructor";} ~A(){cout<<"A destructor";} }; class DivError {}; float div(int n1,int n2) { A obj1; if(n2==0) throw DivError(); float ans = (float)n1/n2; return ans; } int main() { int m; int n; cout<<"Enter 2 integers "; cin>>m>>n; try{ float ans = div(m,n); cout<<"Quotient is"<<ans; } catch(float error1) { cout<<"Attempt to divide by 0"; } } The program crashes because the exception is not handled. No. The local objects are not cleaned up.
29. Write a function foo which prints ith element of the array. foo() calls bar() which returns arr[i]. bar throws an exception if i is out of range. Call foo in main with in a loop with different values of index and observe behaviour.
#include <iostream> using namespace std; #define ERR_CODE -1000 int bar(int *arr,int len,int index) { cout<<"in bar function"; if(index<0) throw float(1.2); if(index>=len) throw int(11); return arr[index]; } int foo(int *arr,int len,int index) { cout<<"in foo function"; return bar(arr,len,index); } int main() { int arr[] = {11,22,33,44,55,66,77,88}; for(int i=0;i<5;i++){ int n; cout<<"Which element:"; cin>>n; try{ int el = foo(arr,8,n); cout<<"Element is "<<el<<endl; } catch(float error1) { cout<<"subscript can not be negative"<<endl; } catch (int error1){ cout<<"Array index out of range"<<endl; } } }
30. Modify the above program where bar has exception specification. bar() can throw only int exceptions. Run the program. Now specify that bar() can not throw any exception. Is it possible to specify that bar() can throw any type of exception
#include <iostream> using namespace std; #define ERR_CODE -1000 int bar(int *arr,int len,int index) throw (int) { cout<<"in bar function"; if(index<0) throw float(1.2); if(index>len) throw int(11); return arr[index]; } int foo(int *arr,int len,int index) { cout<<"in foo function"; return bar(arr,len,index); } int main() { int arr[] = {11,22,33,44,55,66,77,88}; for(int i=0;i<5;i++){ int n; cout<<"Which element:"; cin>>n; try{ int el = foo(arr,8,n); cout<<"Element is "<<el<<endl; } catch(float error1) { cout<<"subscript can not be negative"<<endl; } catch (int error1){ cout<<"Array index out of range"<<endl; } } } To specify that the function can not throw any exception, throw specifier should be empty int bar(int *arr,int len, int index) throw ()
31. Write a program which prints a/b and throws a double exception if b is zero. Write a catch block with int and another with catch all.
#include <iostream> using namespace std; #define ERR_CODE -1000 class A { public: A(){cout<<"A constructor";} ~A(){cout<<"A destructor";} }; class DivError {}; float div(int n1,int n2) { A obj1; if(n2==0) throw double(12); float ans = (float)n1/n2; return ans; } int main() { int m; int n; cout<<"Enter 2 integers "; cin>>m>>n; try{ float ans = div(m,n); cout<<"Quotient is"<<ans; } catch(int error1) { cout<<"caught an int error"; } catch(...) { cout<<"there was an error"; } } catch(...) catches all exceptions. If used, it must be last catch block.
FileHandling
32. Write a program to write cubes of first 10 integers to a binary file. Now read back these numbers from the file and print the cube roots of values in file.
#include<iostream> #include<fstream> #include<cmath> using namespace std; bool writeNumsTofile(char *filename) { ofstream outfile(filename,ios::out|ios::binary); if(!outfile) { return false; } for(int i=1;i<=10;i++) { int cube = i*i*i; outfile.write((char*)&cube,sizeof(cube)); } outfile.close(); return true; } bool readNumFromFile(char *filename) { ifstream infile(filename,ios::binary); if(!infile) { return false; } int num; while(infile.read((char*)&num,sizeof(num))) { double root = pow(num,(1.0/3)); cout<<"num"<<num<<"cube root:"<<root<<"\n"; } infile.close(); } int main() { char *filename=new char[40]; cout<<"File="; cin>>filename; if(writeNumsTofile(filename)) readNumFromFile(filename); else cout<<"file create error"; return 0; }
33. Write a program to read a c++ program file and print the total number of characters in the file. The program should also print the names of header files used in the program file.
#include<iostream> #include<fstream> #include<string> using namespace std; int getNumChars(string filename) { ifstream infile(filename.c_str()); if(!infile) { cout<<"Error opening the file"; return -1; } infile.seekg(0,ios::end); int temp = infile.tellg(); return temp; } bool non_blank(string line,int pos) { for(int i=0;i<pos;i++) { if(line[i]!=' ' && line[i]!='\t') return true; } return false; } void printIncludes(string filename) { ifstream infile(filename.c_str()); if(!infile) { cout<<"Error opening the file"; return; } while(infile) { string line; getline(infile,line); if(infile.fail()) break; int pos = line.find("#include"); if(pos!=string::npos) { if(non_blank(line,pos)) continue; string s1 = line.substr(pos+8,100); cout<< s1<<endl; } } } int main() { string filename; cout<<"File name"; cin>>filename; int count = getNumChars(filename); cout<<"size of the file is "<<count<<endl; printIncludes(filename); }
string::find function searches for substring in a string. If found, it returns the first index. If not found, it returns string::npos.
non_blank function is used to remove lines which contain #include within quoted strings.
34. Write a program to write a simple Hello world program to a file. The program should be complete and should be compilable.
#include<fstream> using namespace std; void write_to_file(char *filename) { fstream outfile(filename,ios::out); if(!outfile) { cout<<"Error opening the file"; return; } outfile<<"#include<iostream>"<<endl; outfile<<"using std::cout;"<<endl; outfile<<"int main()"<<endl; outfile<<"{"<<endl<<"cout<<\"Hello world\"; "<<endl; outfile<<"}"; outfile.close(); } int main() { char *filename = new char[30]; cin>>filename; write_to_file(filename); return 0; }
35. A file a.txt contains 5 Points in the format (x,y),(x1,y1) etc. Read this file and find out if these points are collinear.
#include<iostream> #include<fstream> using std::cin; using std::cout; using std::ifstream; class point { float x; float y; public: point(float m=0,float n=0); float getx() const; float gety() const; void setx(const float & a); void sety(const float & b); }; point::point(float a,float b):x(a),y(b) { } float point::getx() const { return x; } float point::gety() const { return y; } void point::setx(const float &a) { x = a; } void point::sety(const float &b) { y = b; } bool collinear(point*pobj,int len) { float prevSlope = pobj[0].gety()/pobj[0].getx(); for(int i=1;i<len;i++) { float slope = pobj[i].gety()/pobj[i].getx(); if(prevSlope!=slope) return false; prevSlope= slope; } return true; } bool readFile(char *filename,point pobj[]) { ifstream infile(filename); if(!infile) { cout<<"File open error"; return false; } int i=0; while(infile) { float m1,m2; infile.ignore(100,'('); infile>>m1; infile.ignore(100,','); infile>>m2; infile.ignore(100,')'); infile.ignore(100,','); pobj[i].setx(m1); pobj[i].sety(m2); i++; } infile.close(); } int main() { point pobj[5]; readFile("./a.txt",pobj); for(int i=0;i<5;i++) { cout<<"("<<pobj[i].getx()<<","<<pobj[i].gety()<<")\n"; } if(collinear(pobj,5)){ cout<<"The points are collinear"; }else{ cout<<"The points are not collinear"; } return 0; }
36. Write a program to write 4 Points to a binary file. Next read back these Point objects and print the point which is farthest from the origin.
#include<iostream> #include<fstream> #include<cmath> using std::cin; using std::cout; using std::ofstream; using std::ifstream; class point { float x; float y; public: point(float m=0,float n=0); float getx() const; float gety() const; void setx(const float & a); void sety(const float & b); }; point::point(float a,float b):x(a),y(b) { } float point::getx() const { return x; } float point::gety() const { return y; } void point::setx(const float &a) { x = a; } void point::sety(const float &b) { y = b; } void writeToFile(char* filename,point*pobjarr,int len) { ofstream file(filename); if(!file) { cout<<"File opening error."; return; } for(int i=0;i<len;i++) { file.write((char*)&pobjarr[i],sizeof(pobjarr[i])); } file.close(); } void readFromFile(char* filename,point*pobjarr,int len) { ifstream file(filename); if(!file) { cout<<"File opening error."; return; } for(int i=0;i<len;i++) { file.read((char*)&pobjarr[i],sizeof(pobjarr[i])); } file.close(); } int main() { point pobj[4]; for(int i=0;i<4;i++) { cout<<"Enter x and y of point"<<i<<":"; float x1,y1; cin>>x1>>y1; pobj[i].setx(x1); pobj[i].sety(y1); } writeToFile("a.1",pobj,4); point pobjarr[4]; readFromFile("a.1",pobjarr,4); /*find farthest point*/ float largest_dist = -1; int index = -1; for(int i=0;i<4;i++) { float squared_dist = pobj[i].getx()*pobjarr[i].getx() + pobjarr[i].gety()*pobjarr[i].gety(); float dist_from_origin = sqrt(squared_dist); if(dist_from_origin>largest_dist) { largest_dist = dist_from_origin; index = i; } } cout<<"The farthest point is ("<<pobjarr[index].getx()<<","<<pobjarr[index].gety()<<")"; return 0; }
37. Overload >> and << for files for the class Point. Now open a file for both reading and writing and save 5 points to the file. Now read the last point and change it to 0,0 and write it back.
point2.h #include<fstream> using namespace std; class point { float x; float y; public: point(float m =0,float n=0 ); ~point(); float getx() const; float gety() const ; void setx(const float & a); void sety(const float & b); friend fstream & operator <<(fstream &file,const point &p1); friend fstream & operator >>(fstream &file, point &p1); }; point2.cpp #include"point2.h" #include<iostream> using std::cout; /*para ctor*/ point::point(float a,float b):x(a),y(b) { } /*setters*/ void point::setx(const float &a) { x = a; } void point::sety(const float &b) { y = b; } /*getters*/ float point::getx() const { return x; } float point::gety() const { return y; } point::~point() { } main.cpp #include<iostream> #include<fstream> #include"point2.h" using namespace std; fstream &operator<<(fstream&file,const point &p) { file<<p.x<<" "<<p.y<<endl; return file; } fstream &operator>>(fstream&file, point &p) { string str; file>>p.x>> p.y; return file; } istream &operator>>(istream&file, point &p) { float a,b; file>>a>>b; p.setx(a); p.sety(b); return file; } int main() { fstream file("d:/cpp/a.txt",ios::in|ios::out|ios::trunc); for(int i=0;i<5;i++) { point p; cout<<"Enter the point:"; cin>>p; file<<p; } file.seekg(0,ios::beg); point p; file>>p; p.setx(0); p.sety(0); file.seekg(0,ios::beg); file<<p; }
Friend
38. Write a friend function which takes a point as parameter and returns distance of the point from origin
point.h class point { float x; float y; public: point(float m =0,float n=0 ); ~point(); float getx() const; float gety() const ; void setx(const float & a); void sety(const float & b); friend float dist (const point& p1); }; main.cpp #include<iostream> #include<cmath> #include"point.h" using namespace std; float dist(const point & p1) { float sum = p1.y*p1.y+p1.x*p1.x; return sqrt(sum); } int main() { point p(3,4); cout<<"DIstance from origin is "<<dist(p); }
Note that the class must declare the function to be a friend function within the class body.
A friend function can acces even the private members of the class.
FunctionOverloading
39. Implement an overloaded set of max() functions to accept (a) two integers, (b) two floats, (c) two strings, (d) an array of floats and an integer indicating the size of the array. Write a main() function.
#include<cstring> using std::cout; using std::strcmp; using std::endl; int max(int a,int b) { return a>b?a:b; } float max(float a,float b) { return a>b?a:b; } char * max(char *a,char *b) { if(strcmp(a,b)>0) return a; else return b; } int max(int a,int b,int c) { return a>b?(a>c?a:c):b>c?b:c; } float max(float arr[],int len) { float max = arr[0]; for(int i=1;i<len;i++) { if(arr[i]>max) max = arr[i]; } return max; } int main() { cout<<"max of 11 and 1239 is"<<max(11,1239)<<endl; cout<<"max(1.8,-99.2) is"<<max(1.8f,-99.2f)<<endl; cout<<"max(\"hello\",\"world\") is"<<max("hello","world")<<endl; float arr[] = {1,22,45.6,112.8}; cout<<"max(arr,4) is "<<max(arr,4)<<endl; cout<<"max(11,22111,333) is "<<max(11,22111,333)<<endl; return 0; }
Notes: 1) using namespace std may cause program to use libaray max function. Either use using std::cout etc. or change the name of fn to max1
2) Sending 1.8,-99.2 as parameters to float version of max function causes ambiguity error. Hence use float instead of double
40. Write a function which can find the product of 2 or 3 or 4 float values.
#include <iostream> using namespace std; float product(float a,float b,float c=1,float d=1) { return a*b*c*d ; } int main() { float m,n,x,y,z; cout<<"Enter 4 numbers"; cin>>m>>n>>x>>y; cout<<"Prodcut of "<<x<<" and "<<y<<" is"<<product(x,y)<<endl; cout<<"Prodcut of "<<m<<" and "<<n<<" and "<<x<<" is"<<product(m,n,x)<<endl; cout<<"Prodcut of "<<m<<" and "<<n<<" and "<<x<<" and "<<y<<" is"<<product(m,n,x,y)<<endl; return 0; }
41. Write a function to initialize the elements of the array. The function must take array as first argument and size as second argument and initial value to be set as third. If value is not given, array elements must be initialzed to 0.
#include <iostream> using namespace std; void init_array(int *arr,int len,int value=0) { for(int i=0;i<len;i++) { arr[i]=value; } } void print_array(int *arr,int len) { for(int i=0;i<len;i++) { cout<<arr[i]; if(i<len-1) cout<<","; } cout<<endl; } int main() { int *arr = new int[10]; init_array(arr,10,1); print_array(arr,10); int *arr2 = new int[5]; init_array(arr2,5); print_array(arr2,5); }
42. Write a function to find the product of any where from 2 to 5 floats.
#include<iostream> using std::cout; float product(float a,float b,float c=1,float d=1,float e = 1) { return a*b*c*d*e; } int main() { cout<<"Product of 11.2 and 22.4 is "<<product(11.2,22.4)<<"\n"; cout<<"Product of 8, 7.9 and 4.3 is "<<product(8,7.9,4.3)<<"\n"; cout<<"Product of 3,4,5 and 6 is "<<product(3,4,5,6)<<"\n"; cout<<"Product of 11,22,33,44 and 55 is "<<product(11,22,33,44,55)<<"\n"; return 0; }
As the function has default values of 1 for 3rd to 5th parameters, it is able to work with 2 or 3 or 4 or 5 parameters
Inheritance
43. Write a class Widge. Now write two derived classes of Widget- Button and Label with data member text.
class Widget { float x,y; }; class Button:public Widget { string text; }; class Label:public Widget { string text; int color; };
44. In the class Widget, write a constructor with 2 parameters x and y. Now can you create objects of derived classes Button and Label? How do you fix this?
No. The program does not compile. To fix the error, we have to write constructors for Button and Label classes which call Widget constructor in their initializer list. #include <iostream> using namespace std; class Widget { float x,y; public: Widget(float a,float b):x(a),y(b) { cout<<"Widget constructor"; } }; class Button:public Widget { string text; public: Button(float a,float b,string str); }; Button::Button(float a,float b,string str):Widget(a,b),text(str) { cout<<"Button constructor"; } class Label:public Widget { string text; int color; public: Label(float a,float b, string str); }; Label::Label(float a,float b,string str):Widget(a,b),text(str) { cout<<"Label constructor"; } int main() { Button b1(0,0,"hi"); Label l1(0,0,"label"); }
A derived class constructor always calls base class constructor.
If the base class has no default constructor, then base class ctor can not be called implicitly. So we must explicitly call base class ctor in member initializer list of derived class ctor.
45. In the polygon class, write a function printArea takes area as a parameter and prints it. Now write an area function in Rectangle class which has no parameters and pritns the area as length*width. Can a rectangle object call one parameter printArea() function?
polygon.h class polygon { int num_sides; public: polygon(int nsides); ~polygon(); void printArea(int area); }; polygon.cpp - partial #include "polygon.h" #include<iostream> void polygon::printArea(int area) { std::cout<<"Area is "<<area<<std::endl; } Rectangle.h class Rectangle : public polygon { int wid,len; public: Rectangle(int w=1,int l=1); ~Rectangle(); void printArea(); }; Rectangle.cpp - partial void Rectangle::printArea() { std::cout<<"Area is "<<len*wid<<std::endl; } main.cpp #include <iostream> using namespace std; #include"polygon.h" #include "Rectangle.h" int main(int argc, char **argv) { polygon p(3); p.printArea(100); Rectangle r(11,22); r.printArea(); //r.printArea(10); }
It is not possible to call base class printArea() function by Rectangle object. Because it is hidden by the overridden function.
But you can still call that function using base class name and ::
r.polygon::printArea();
46. Create two objects. obj1 a polygon and obj2 a rectangle. Can obj1 be assigned to obj2? Why? Can obj2 be assigned to obj1? Why?
#include"polygon.h" #include "Rectangle.h" int main(int argc, char **argv) { polygon p(3); Rectangle r(11,22); p = r; r = p;/*invalid*/ } r = p gives an error because polygon is not a Rectangle. So a base class object can not be assigned to a derived class object. Derived class object is more specialized object. Base class object can be always be assinged to derived class object.
47. Make x and y as private members in the Widget class in previous example. Write a method setxy in Button class which modifies x and y. Will the program compile? What are the two solutions to fix this?
1) Make x and y as protected members. class Widget { protexted: float x,y; public: Widget(float a,float b):x(a),y(b) { cout<<"Widget constructor"; } }; class Button:public Widget { string text; public: Button(float a,float b,string str); void setxy(float a, float b); }; void Button::setxy(float a,float b) { x = a; y = b; } 2) Write public setters and getters for Widget class x and y. Use these in setxy class Widget { float x,y; public: Widget(float a,float b):x(a),y(b) { cout<<"Widget constructor"; } void setx(float a) { x = a; } void sety(float b) { y = b; } }; class Button:public Widget { string text; public: Button(float a,float b,string str); void setxy(float a, float b); }; void Button::setxy(float a,float b) { setx(a); sety(b); } int main() { Button b1(0,0,"hi"); Label l1(0,0,"label"); b1.setxy(10,10); }
48. Can a class Checkbox be inherited using private inheritance from Widget class? What are the effects of this inheritance?
Yes. class Checkbox:private Widget { /*code*/ } or class Checkbox:private Widget { /*code*/ } Now all members of polygon including public members become private members in derived class.
Introduction
49. Write a function printArray to print the contents of an integer array with the string ", " between elements(but not after the last element). Yourfunction should return nothing.
#include <iostream> using namespace std; void print_array(int *arr,int len) { for(int i=0;i<len;i++) { cout<<arr[i]; if(i<len-1) cout<<","; } } int main() { int arr[4]={11,22,33,44}; print_array(arr,4); return 0; }
50. Write a function to implement binary search of an array
#include<iostream> using namespace std; int binarySearch(int *arr,int start,int end,int searchvalue) { if(start>end) { return -1; } int mid = (start+end)/2; if(arr[mid]==searchvalue) { return mid; } if(arr[mid]>searchvalue) { return binarySearch(arr,start,mid-1,searchvalue); } else { return binarySearch(arr,mid+1,end,searchvalue); } } int main() { int arr[10]; cout<<"Enter sorted array elements"; for(int i=0;i<10;i++) { cout<<"arr["<<i<<"]="; cin>>arr[i]; } int searchvalue; cout<<"Search value="; cin>>searchvalue; int index = binarySearch(arr,0,9,searchvalue); if(index==-1) cout<<"Search value is not found in array"; else cout<<index<<" element is the Searchvalue"; return 0; }
51. Write a function which takes two integers and finds the sum of all numbers between these two integers.
#include <iostream> using namespace std; int sum_of_numbers(int a,int b) { if(b>a) { int temp = a; a = b; b = temp; } int sum=0; for(int i=b;i<=a;i++) { sum+=i; } return sum; } int main() { int m,n; cout<<"Enter two numbers:"; cin>>m>>n; int total = sum_of_numbers(m,n); cout<<"Sum of numbers between "<<m<<"and "<<n<<" is "<<total; return 0; }
52. Write a program to read three numbers and print their product in decimal, octal and hexadecimal.
#include <iostream> using namespace std; int main() { int m,n,p; cout<<"Enter three numbers:"; cin>>m>>n>>p; int product = m*n*p; cout<<"Product is "<<product<<oct<<"\nProduct in Octal is "<<product<<"\nProduct in hexadecimal is"<<hex<<product; return 0; }
MultipleInheritance
53. Write a class MI which inherits both classes A - data members n1 and n2, B - with data members n1 and n11. Now create an object MI and set n1 to 10. Does the program compile? Why?
mi.h class A { public: int n1; int n2; }; class B { public: int n1; int n11; }; class MI:public A, public B { int m; }; main.cpp #include <iostream> #include"aaaa.h" using namespace std; int main(int argc, char **argv) { MI obj1; obj1.n1 = 10; cout<<obj1.n1; } The program does not compile. obj of MI class has four members n1, n2 and n1 and n11. That is there are 2 members with name n1. The problem can be solved by using base class name and :: int main(int argc, char **argv) { MI obj1; obj1.A::n1 = 10; cout<<obj1.A::n1; }
54. class B inherits from class A. class C also inherits from class A. class D is a derived class of both A and B. A has data memeber n1 and setter and getter to it. Write code so that accessing n1 through does not create compilation error.
multiinh2.h class A { int n; public: void setn(int m){n = m;} int getn(){return n;} }; class B:virtual public A { }; class C:virtual public A { }; class D:public C, public B { }; main.cpp #include <iostream> #include"multiinh2.h" using std::cout; int main(int argc, char **argv) { D obj1; obj1.setn(100); cout<<obj1.getn(); }
If the classes B and C are not using virtual inheritance, D object will have 2 sub-objects of A class. Accessing any member of A will cause ambiguity error in D class.
Virtual inheritace ensures that the base class A object is included only once in derived class irrespective of how many times A is used as base class directly or indirectly.
OperatorOverloading
55. Write a program with date class which has dd,mm and yy as int members. Provide constructors. And overload ++ operator to increment date by d days.
date.h #ifndef DATE_H #define DATE_H class Date { int dd,mm,yy; public: Date(); Date(int d,int m,int y); ~Date(); void setDay(int d); void setMonth(int m); void setYear(int y); int getDay(); int getMonth(); int getYear(); Date operator +(int n); bool leapYear(); }; #endif // DATE_H date.cpp #include "Date.h" Date::Date() { dd = 1; mm = 1; yy = 2000; } Date::~Date() { } Date::Date(int d,int m,int y):dd(d),mm(m),yy(y) { } void Date::setDay(int d) { dd =d; } void Date::setMonth(int m) { mm = m; } void Date::setYear(int y) { yy = y; } int Date::getDay() { return dd; } int Date::getMonth() { return mm; } int Date::getYear() { return yy; } Date Date::operator +(int n) { Date temp = *this; static int month_days[] = {31,28,31,30,31,30,31,31,30,31,30,31}; temp.yy+=n/365; n = n%365; int incr_dd = temp.dd+n; int mn_days = month_days[temp.mm-1]; if(temp.mm==2&&leapYear()) { mn_days=29; } while(incr_dd>mn_days) { incr_dd -= mn_days; temp.mm++; if(temp.mm>12) { temp.mm-=12; temp.yy++; } mn_days = month_days[temp.mm-1]; if(temp.mm==2&&leapYear()) { mn_days=29; } } temp.dd = incr_dd; return temp; } bool Date::leapYear() { int rem = yy%4; int rem2 = yy%100; int rem3 = yy%400; if(rem3==0 ) { return true; } if(rem2==0) return false; if(rem==0) return true; return false; } main.cpp #include <iostream> #include"Date.h" using namespace std; int main() { Date d1; int a,b,c; cout<<"Enter dd mm yy:"; cin>>a>>b>>c; d1.setDay(a); d1.setMonth(b); d1.setYear(c); cout<<"Enter days to be added:"; int n; cin>>n; Date d2 = d1+n; cout<<"date is "<<d2.getDay()<<"-"<<d2.getMonth()<<"-"<<d2.getYear(); return 0; }
56. Write a program to overload () in matrix class to return ith row jth column element of matrx
matrix.h #ifndef MATRIX_H #define MATRIX_H class matrix { int *elements; int nr,nc; public: matrix(); ~matrix(); int getNrows(){return nr;} int getNcols(){return nc;} matrix(int nr,int nc); int & operator() (int row,int col); }; #endif // MATRIX_H matrix.cpp #include "matrix.h" matrix::matrix() { nr = nc = 2; this->elements = new int[nr*nc]; for(int i=0;i<nr*nc;i++) { elements[i]=0; } } matrix::~matrix() { } matrix::matrix(int nr,int nc) { this->nr = nr; this->nc = nc; this->elements = new int[nr*nc]; for(int i=0;i<nr*nc;i++) { elements[i]=0; } } int& matrix::operator()(int row,int col) { int index = row*nc; index+=col; return elements[index]; } main.cpp #include <iostream> #include"matrix.h" using namespace std; int main( ) { matrix m(3,3); for(int i=0;i<3;i++) for(int j=0;j<3;j++) { int temp; cout<<"Value:"; cin>>temp; m(i,j)=temp; } for(int i=0;i<m.getNrows();i++) { for(int j=0;j<m.getNcols();j++) { cout<<m(i,j)<<" "; } cout<<endl; } }
57. Make a friend function that implements a + operator for Stacks. The behavior of the + operator should be such that when you write a+b, you get a new stack containing a’s items followed by b’s items
Stack.h struct node { int num; struct node *next; }; class Stack { node *topnode; public: Stack(); bool empty(); void push(int data); int pop(); int & top(); friend Stack operator +( Stack &a, Stack &b); }; main.cpp #include <iostream> #include"Stack.h" using namespace std; Stack operator +( Stack &s1, Stack &s2) { int count = 0; while(!s2.empty()) { int num = s2.pop(); s1.push(num); count++; } return s1; } int main(int argc, char **argv) { Stack s1; for(int i=0;i<10;i++) { int m; cout<<"num"; cin>>m; s1.push(m); } Stack s2; for(int i=1;i<3;i++) { s2.push(i*100); } s1=s1+s2; while(!s1.empty()) { int a; a = s1.pop(); cout<<"Popped value is "<<a<<"\n"; } } Stack ::Stack() { topnode = 0;/*initialize*/ } bool Stack ::empty() { return topnode==0; } void Stack::push(int data) { node *newnode = new node ; newnode->num = data; if(topnode){ newnode->next = topnode; }else{ newnode->next = 0; } topnode = newnode; } int Stack ::pop( ) { if(!empty()) { node * temp = topnode; topnode = topnode->next; int num = temp->num; delete temp; return num; } else { return 0; } } int& Stack ::top( ) { if(!empty()) { int num = topnode->num; return num; } else { int m = 0; return m; } }
58. Overload == and > operators for the date class
date.h class Date { int dd,mm,yy; public: Date(); Date(int d,int m,int y); ~Date(); void setDay(int d); void setMonth(int m); void setYear(int y); int getDay(); int getMonth(); int getYear(); Date operator +(int n); bool leapYear(); bool operator ==(const Date& d); bool operator >(const Date& d); } partial date.cpp bool Date::operator==(const Date &dt2) { if (dd==dt2.dd && mm==dt2.mm && yy == dt2.yy) return true; return false; } bool Date::operator>(const Date &dt2) { if(yy>dt2.yy) return true; if(yy<dt2.yy) return false; if(mm>dt2.mm) return true; if(mm<dt2.mm) return false; if(dd>dt2.dd) return true; return false; } main.cpp #include <iostream> #include"Date.h" using namespace std; int main() { int a,b,c; cout<<"Enter first date in the form dd mm yy:"; cin>>a>>b>>c; Date d1(a,b,c); cout<<"Enter second date in the form dd mm yy:"; cin>>a>>b>>c; Date d2(a,b,c); if(d1>d2) { cout<<"First date is larger"; } else if(d1==d2) { cout<<"dates equal"; } else { cout<<"second date is larger"; } return 0; }
59. Create a class Number which is one byte in size. Write a constructor, destructor. Write overloaded functions +,-,* and / to this class.
A.h class Number { char num; public: Number(int n=0); Number(const Number &obj); ~Number(); void setNum(char m); int getNum(); Number operator +(const Number & obj); Number operator -(const Number & obj); int operator *(const Number & obj); float operator /(const Number & obj); }; #define ERROR_DIVISION 1289 A.cpp #include "A.h" #include<iostream> using std::cout; Number::Number(int n) { this->num =(char) n; } Number::~Number() { // std::cout<<"Destructor of "<<(int)num<<std::endl; } Number::Number(const Number &obj) { this->num = obj.num; // std::cout<<"copy constructor is called"; } void Number::setNum(char m) { num = m; } int Number::getNum() { return num; } Number Number::operator +(const Number & obj) { return Number(num+obj.num); } Number Number::operator -(const Number & obj) { Number temp = *this; temp.num -=obj.num; return temp; } int Number::operator *(const Number & obj) { int temp(this->num*obj.num); return temp; } float Number::operator /(const Number & obj) { if(obj.num==0) { cout<<"Denominator is 0"; return ERROR_DIVISION; } return (float)num/obj.num; } main.cpp #include <iostream> #include"A.h" using namespace std; int main() { Number obj1(12); Number obj2(25); Number obj3 ; obj3 = obj1+obj2; cout<<"sum is "<<obj3.getNum()<<endl; obj3 = obj1 - obj2; cout<<"difference is "<<obj3.getNum()<<endl; int product = obj1 * obj2; cout<<"product is "<<product<<endl; float quotient = obj1 / obj2; if(quotient!=ERROR_DIVISION){ cout<<"quotient is "<<quotient<<endl; } }
60. To the Number class add the overloaded operators +=, -= which take a Number as second argument. Overload *= and /= with integer as second argument. Also overload assignment operator
A.h class Number { unsigned char num; public: Number(int n=0); Number(const Number &obj); ~Number(); void setNum(char m); int getNum(); Number operator +(const Number & obj); Number operator -(const Number & obj); int operator *(const Number & obj); float operator /(const Number & obj); void operator +=(const Number &obj); void operator -=(const Number &obj); void operator *=(int n); void operator /=( int n); Number & operator=(const Number &other); }; #define ERROR_DIVISION 1289 A.cpp #include "A.h" #include<iostream> using std::cout; Number::Number(int n) { this->num =(char) n; } Number::~Number() { // std::cout<<"Destructor of "<<(int)num<<std::endl; } Number::Number(const Number &obj) { this->num = obj.num; // std::cout<<"copy constructor is called"; } void Number::setNum(char m) { num = m; } int Number::getNum() { return num; } Number Number::operator +(const Number & obj) { return Number(num+obj.num); } Number Number::operator -(const Number & obj) { Number temp = *this; temp.num -=obj.num; return temp; } int Number::operator *(const Number & obj) { int temp(this->num*obj.num); return temp; } float Number::operator /(const Number & obj) { if(obj.num==0) { cout<<"Denominator is 0"; return ERROR_DIVISION; } return (float)num/obj.num; } void Number::operator -=(const Number & obj) { num -=obj.num; } void Number::operator +=(const Number & obj) { num +=obj.num; } void Number::operator *=( int n) { num *=n; } void Number::operator /=( int n) { num/=n; } Number & Number::operator=(const Number&other) { num = other.num; /*no need to check for self assignment as no pointers involved*/ return *this; } main.cpp #include <iostream> #include"A.h" using namespace std; int main() { Number obj1(12); Number obj2(25); obj1 +=obj2; cout<<"After +=obj2, obj1 is "<<obj1.getNum()<<endl; obj1 -= obj2; cout<<"After -=obj2 obj1 is "<<obj1.getNum()<<endl; obj1*=20; cout<<"After *=20, obj1 is "<<obj1.getNum()<<endl; obj1/=20; cout<<"After /=20, obj1 is "<<obj1.getNum()<<endl; }
61. Write a class MyArray with float array and length of the array. Now overload subscript operator for this class for accessing and modifying array elements
Array.h class Array1 { int *arr; int size; public: Array1(int n=3,int val=0); int& operator [](int index); int operator [](int index) const; }; Array.cpp #include"Array.h" Array1::Array1(int n,int val):size(n) { arr = new int[n]; for(int i=0;i<n;i++) arr[i]=val; } int &Array1::operator [](int index) { return arr[index]; } int Array1::operator [](int index) const { return arr[index]; } main.cpp #include <iostream> #include"Array.h" using namespace std; int main() { Array1 obj(10); for(int i=0;i<10;i++) obj[i] = i; const Array1 obj2(3,99); cout<<"Object 2 is "; for(int i=0;i<3;i++) cout<<obj2[i]<<" "; cout<<"\nObject is "; for(int i=0;i<10;i++) cout<<obj[i]<<" "; }
62. Overload both pre-decrement and post-decrement operator for TinyInteger class.
A.h class Number { unsigned char num; public: Number(int n=0); Number(const Number &obj); ~Number(); void setNum(char m); int getNum(); Number & operator ++(); Number operator ++(int dummy); }; A.cpp #include "A.h" #include<iostream> using std::cout; Number::Number(int n) { this->num =(char) n; } Number::~Number() { // std::cout<<"Destructor of "<<(int)num<<std::endl; } Number::Number(const Number &obj) { this->num = obj.num; // std::cout<<"copy constructor is called"; } void Number::setNum(char m) { num = m; } int Number::getNum() { return num; } Number & Number::operator++() { num++; return *this; } Number Number::operator++(int dummy) { Number temp(num); num++; return temp; } main.cpp #include <iostream> #include"A.h" using namespace std; int main() { Number obj1(12); Number obj2(25); ++obj1; cout<<"After pre-increment, obj1 is "<<obj1.getNum()<<endl; Number obj3(7); obj3 = obj1++; cout<<"After post-increment, obj1 and obj3 are "<<obj1.getNum()<<" "<<obj3.getNum()<<endl; }
63. Write a functor which finds the square root of a perfect square.
#include <iostream> using namespace std; class SquareRoot { public: int operator ()(unsigned int num); }; int SquareRoot::operator()(unsigned int num) { for(int i=0;i<num;i++) { if(i*i==num) return i; } return -1;/*error*/ } int main() { int m; cout<<"Enter a perfect square "; cin>>m; SquareRoot sqrtObj; int sr = sqrtObj(m); if(sr==-1) cout<<"The number must be a perfect square"; else cout<<"Square root of "<<m <<"is "<<sr; }
64. Overload insertion operator and extraction operator for Point class.
point.h #include<fstream> using std::ostream; using std::istream; class point { float x; float y; public: point(float m=0,float n=0):x(m),y(n){} float getx() const {return x;} float gety() const {return y;} void setx(const float & a){x=a;} void sety(const float & b){y=b;} friend istream &operator>>(istream&out, point &p); friend ostream &operator<<(ostream&out, point &p); }; main.cpp #include<iostream> #include<fstream> #include"point2.h" using namespace std; ostream & operator <<(ostream &out,point &p) { out<<p.x<<","<<p.y<<"\n"; return out; } istream & operator >>(istream &in, point &p) { in>>p.x>>p.y; return in; } int main() { point pobj[5]; for(int i=0;i<5;i++) { cout<<"Enter point:"; cin>>pobj[i]; } for(int i=0;i<5;i++) { cout<<pobj[i]; } return 0; }
Polymorphism
65. Write a class Shape with printName method which just prints Shape. Now write derived classes Circle and Square. These classes must override printName method to print Circle and Square respectively. Now write an external function pr(Shape s) which calls printName() of its parameter. Can we call pr() function with a circle object and a Square object? Will the function print the correct Shape name? How do you make pr function print correct name?
Make printName() in Shape class as virtual function Make the parameter to pr function as either a reference parameter or a pointer parameter. #include<iostream> using namespace std; class Shape { public: virtual void printName() { cout<<"shape"; } }; class Circle:public Shape { public: void printName() { cout<<"Circle"; } }; class Square:public Shape { public: void printName() { cout<<"Square"; } }; void pr(Shape &s) { s.printName(); } void prPtr(Shape *sptr) { sptr->printName(); } void prVal(Shape s) { s.printName(); } int main() { Shape s; Circle c; Square sq; cout<<"Reference parameters "; pr(s); pr(c); pr(sq); cout<<"\nPointer parameters "; prPtr(&s); prPtr(&c); prPtr(&sq); cout<<"\nValue parameters "; prVal(s); prVal(c); prVal(sq); }
66. In the previous example, what is the size of Shape object, if it no data members? Why?
The size is 4 bytes in case of 4 byte integer. The size is more because of the hidden member vptr which is stored in the object.
Reference
67. Write a function to find the product of two variables and store this product in first variable. The function should return nothing. Do not use pointers.
void product(int &n1,int &n2) { n1 *=n2; }
68. Write a function to swap two variables using references.
#include <iostream> using namespace std; void swap(int &a,int &b) { int temp =a ; a = b; b = temp; } int main() { int m,n; cout<<"Enter 2 numbers m and n:"; cin>>m>>n; swap(m,n); cout<<"m is"<<m<< "\nn is "<<n ; return 0; }
69. Write a function product which takes two integer reference parameters and finds their product. Let the parameters be unchangeable.
#include <iostream> using namespace std; int product(const int &a,const int &b) { // a++; return a*b; } int main() { int m,n; cout<<"Enter 2 numbers m and n:"; cin>>m>>n; cout<<"product is"<<product(m,n) ; return 0; }
Static
70. In the student class, create a data member batch which is common to all students. Now create 5 student objects and print their informations.
#include<iostream> using namespace std; class Student { string name; int id; public: static int batch; Student(string name,int id); string get_name() { return name; } int get_id() { return id; } int get_batch() { return batch; } void set_name(string n); void set_id(int n); }; int Student::batch=2017; Student::Student(string n,int id2):id(id2), name(n) { cout<<" constructor\n"; } void Student::set_name(string name ) { this->name = name; } void Student::set_id( int id) { this->id = id; } void print_details(Student s) { cout<<"Name "<<s.get_name()<<"\n"; cout<<"Id "<<s.get_id()<<"\n"; cout<<"Batch "<<s.get_batch()<<"\n"; } int main( ) { cout<<"name of student"; string name; cin>>name; cout<<"id ="; int id; cin>>id; Student s2(name ,id); print_details(s2); cout<<"All these students are from batch of "<<Student::batch; return 0; }
71. Write a method to class Point which prints a message "Welcome to the world of Points". The message must be printed without creating any object of Point class
class point { float x; float y; public: point(float m =0,float n=0 ); float getx() const { return x; } float gety() const { return y; } void setx(const float & a); { x = a; } void sety(const float & b) { y = b; } static void print_hello(); }; point::point(float a,float b):x(a),y(b) { cout<<"Constructor is called\n"; } void point::print_hello() { cout<<"Welcome to the world of points"; } int main() { point::print_hello(); }
72. In the class point, add a static method printPoint which displays x and y co-ordinates of the point. Will the program compile? Why?
point.cpp /*code*/ void point::print_point() { cout<<x<<","<<y<<endl; } No, the program gives error.
A static member function of a class does not have this pointer. So it can not access non-static members of a class.
A static member function can only access static data members.
Templates
73. Write a template function min to find the minimum of two values. You may have to remove line using namespace std as std already has a min function in it.
#include<iostream> using std::cout; using std::endl; template <class T> T min(T a,T b) { return a<b?a:b; } int main() { int a =10; int b=-100; float x=100.9,y=200; cout<<min(a,b)<<endl; cout<<min(x,y)<<endl; return 0; }
74. Using templates, implement a Stack class that can be used to store items of any type. Your class should support the following 4 public functions bool Stack::empty() void Stack::push(const T &item) T &Stack::top() – returns a reference to the most-recently-added item void Stack::pop() – removes the most-recently-added item from the stack
Stack.h template <class T> struct node { T num; struct node *next; }; template <class T> class Stack { node <T>*topnode; public: Stack(); bool empty(); void push(T data); T pop(); T & top(); }; template <class T> Stack<T>::Stack() { topnode = 0;/*initialize*/ } template <class T> bool Stack<T>::empty() { return topnode==0; } template<class T> void Stack<T>::push(T data) { node <T>*newnode = new node<T>; newnode->num = data; if(topnode){ newnode->next = topnode; }else{ newnode->next = 0; } topnode = newnode; } template<class T> T Stack<T>::pop( ) { if(!empty()) { node<T> * temp = topnode; topnode = topnode->next; T num = temp->num; delete temp; return num; } else { return (T)0; } } template<class T> T& Stack<T>::top( ) { if(!empty()) { T num = topnode->num; return num; } else { return (T)0; } } main.cpp #include <iostream> #include"Stack.hpp" using namespace std; int main(int argc, char **argv) { Stack<int> s1; for(int i=0;i<10;i++) { int m; cin>>m; s1.push(m); } while(!s1.empty()) { int a; a = s1.pop(); cout<<"Popped value is "<<a<<"\n"; } Stack<char> s2; s2.push('c'); s2.push('+'); s2.push('+'); while(!s2.empty()) { char a; a = s2.pop(); cout<< a<<"\n"; } }
Note that in case of template classes, both class definition and methods definition should be in the same .h file.
75. Write a template function to find largest element of an array.
#include<iostream> using namespace std; template <class T > T largest(T arr[],int size) { T lr = arr[0]; for(int i=0;i<size;i++) if(arr[i]>lr) lr = arr[i]; return lr; } int main() { float arr1[]={1.2,-3.4,12,-4.5}; double arr2[]={11,22,33,44,55,-66}; char arr3[]={'a','b','c','d','8','A','Z'}; cout<<"Largest of float array is"<<largest(arr1,4)<<endl; cout<<"Largest of double array is"<<largest(arr2,6)<<endl; cout<<"Largest of char array is"<<largest(arr3,7)<<endl; }
76. Write a template class List which is singly linked list. Implement the following methods insert(T data,int pos), delete(T data), append(T& data) and isEmpty() and print().
List1.h #include<iostream> using std::cout; template <class T> struct node { T num; struct node<T> *next; }; template <class T> class List { node<T> *first; public: List(); ~List(); void append(T data); void insert(int pos,T data); void print(); void delete_node(T data); node<T>* find_node(T data); node<T>* create_node(T data); node<T>* find_last_node(); node<T>* find_ith_node(int i); node<T>* find_previous_node(node<T> *nn); }; template <class T> List<T>::List() { first = 0;/* initialize first node*/ } template <class T> List<T>::~List() { while(first) { node <T>*temp = first; first = first->next; delete temp; } } template <class T> node<T> * List<T>::create_node(T data) { node<T> * newnode = new node<T>; newnode->num = data; newnode->next = 0; return newnode; } template <class T> node<T> *List<T>::find_last_node() { node<T> *temp = first; while(temp && temp->next) temp = temp->next; return temp; } template <class T> void List<T>::append(T data) { node<T> *newnode = create_node(data); node<T> *last_node = find_last_node(); if(!last_node) { first = newnode; } else{ last_node->next = newnode; } } template <class T> node<T> * List<T>::find_previous_node(node<T> * nn) { node<T> * temp = first; while(temp && temp->next!=nn) temp = temp->next; return temp; } template <class T> node<T> * List<T>::find_ith_node(int pos) { node<T> *temp = first; int i = 0; while(temp&&i!=pos) { temp = temp->next; i++; } return temp; } template <class T> void List<T>::insert(int pos,T data) { node<T> * newnode = create_node(data); node<T> * ithnode = find_ith_node(pos); if(ithnode) { node<T> *prevnode = find_previous_node(ithnode); if(prevnode) { node<T> * nextnode = prevnode->next; prevnode->next = newnode; newnode->next = nextnode; } else { /*i must be 0*/ newnode->next = first; first= newnode; } } else/*no ith node. append*/ { node<T> * last_node = find_last_node(); if(last_node) last_node->next = newnode; else first = newnode; } } template <class T> void List<T>::print() { node<T> * temp = first; while(temp) { cout<<temp->num; if(temp->next) cout<<"==>"; temp = temp->next; } cout<<std::endl; } template <class T> node<T> * List<T>::find_node(T data) { node<T> * temp = first; while(temp && temp->num!=data) temp = temp->next; return temp; } template <class T> void List<T>::delete_node(T data) { node<T> * temp = find_node(data); if(!temp) { cout<<"Value not found"; return; } else { node<T> *prevnode = find_previous_node(temp); if(!prevnode) { /*we are deleting the first node*/ first = first->next; delete temp; } else{ prevnode->next = temp->next; /*link previous node to next node*/ delete temp; } } } main.cpp #include <iostream> using std::cout; using std::cin; using std::string; #include"List1.h" int main(int argc, char **argv) { List<int> list; for(int i=0;i<5;i++) { int n; cout<<"NUmber"; cin>>n; list.append(n); } list.print(); List<string> list2; list2.append("hello"); list2.append("hi"); list2.append("bye"); list2.append("morning"); list2.print(); list2.delete_node("hi"); list2.print(); list2.insert(0,string("list of words")); list2.print(); }