dhanalakshmi college of engineering, … college of engineering, chennai ... anna university 2 &...

33
DHANALAKSHMI COLLEGE OF ENGINEERING, CHENNAI Department of Computer Science and Engineering CS6301 PROGRAMMING AND DATA STRUCTURES-II Anna University 2 & 16 Mark Questions & Answers Year / Semester: II / III Regulation: 2013 Academic year: 2017 - 2018

Upload: phungtuyen

Post on 29-Jun-2018

223 views

Category:

Documents


0 download

TRANSCRIPT

DHANALAKSHMI COLLEGE OF ENGINEERING,

CHENNAI

Department of Computer Science and Engineering

CS6301 PROGRAMMING AND DATA STRUCTURES-II

Anna University 2 & 16 Mark Questions & Answers

Year / Semester: II / III

Regulation: 2013

Academic year: 2017 - 2018

PART A

1. How does a C string differs from a C++ type string? [M/J – 16] [N/D-15]

In C, strings are just char arrays which, by convention, end with a NUL byte. In terms of

dynamic memory management, you can simply malloc the space for them (including the extra

byte). Memory management when modifying strings is your responsibility:

char *s = strdup ("Hello");

char *s2 = malloc (strlen (s) + 6);

strcpy (s2, s);

strcat (s2, ", Pax");

free (s);

s = s2;

In C++, strings (std::string) are objects with all the associated automated memory management

and control which makes them a lot safer and easier to use, especially for the novice. For

dynamic allocation, use something like:

std::string s = "Hello";

s += ", Pax";

2. Distinguish the term overloading and overriding. [M/J – 16]

Overloading occurs when two or more methods in one class have the same method name but

different parameters. Overriding means having two methods with the same method name and

parameters (i.e., method signature). One of the methods is in the parent class and the other is in

the child class.

3. Give the list of operators that cannot be overloaded.

?: (conditional)

. ( member selection)

.* (member selection with pointer-to-member)

:: (scope resolution)

sizeof (object size information)

typeid (object type information)

4. Differentiate compile and runtime polymorphism.

Compile time Polymorphism, call is resolved by

the compiler.

In Run time Polymorphism, call is not resolved by

the compiler.

It is also known as Static binding, Early

bindingand overloading as well.

It is also known as Dynamic binding, Late

bindingand overriding as well.

Overloading is compile time polymorphism where Overriding is run time polymorphism having

more than one methods share the same name with

different parameters or signature and different

return type.

same method with same parameters or signature,

but associated in a class & its subclass.

It is achieved by function overloading

andoperator overloading.

It is achieved by virtual functions and pointers.

It provides fast execution because known early at

compile time.

It provides slow execution as compare to early

binding because it is known at runtime.

Compile time polymorphism is less flexible as all

things execute at compile time.

Run time polymorphism is more flexible as all

things execute at run time.

5. Define copy constructor and its use.

The copy constructor is a constructor which creates an object by initializing it with an object

of the same class, which has been created previously. The copy constructor is used to: Initialize

one object from another of the same type. Copy an object to pass it as an argument to a function.

6. What are the special properties of virtual functions?

Dynamic binding: virtual functions are resolved during run time or dynamic binding.

Virtual functions are member functions of a class.

Virtual functions are declared with the keyword virtual.

Virtual function takes a different functionality in the derived class.

8. What is dynamic initialization of objects?

Dynamic initialization of object refers to initializing the objects at run time i.e. the initial value

of an object is to be provided during run time. Dynamic initialization can be achieved using

constructors and passing parameters values to the constructors. This type of initialization is

required to initialize the class variables during run time.

10. What are pure virtual functions? Give example.

A pure virtual function or pure virtual method is a virtual function that is required to be

implemented by a derived class if the derived class is not abstract. Classes containing pure

virtual methods are termed "abstract" and they cannot be instantiated directly.

class Animal {

public:

void /*non-virtual*/ move(void) {

std::cout << "This animal moves in some way" << std::endl;

}

virtual void eat(void) = 0;

};

// The class "Animal" may possess a definition for eat() if desired.

class Llama : public Animal {

public:

// The non virtual function move() is inherited but not overridden

void eat(void) override {

std::cout << "Llamas eat grass!" << std::endl;

}

};

Part B

12. (a) (i) Write a C++ program to overload the decrement operator with prefix and postfix

forms.

#include<iostream>

using namespace std;

class pp

{

int a,b;

public:

pp()

{

a=5;

b=-5;

}

void show()

{

cout<<" a="<<a<<" and b="<<b;

}

void operator --()

{

--a;

--b;

}

void operator --(int)

{

a--;

b--;

}

};

int main()

{

pp p,p1;

cout<<"Before prefix decrement";

p.show();

--p;

cout<<"\nAfter prefix decrement";

p.show();

cout<<"\nBefore postfix decrement";

p1.show();

p1--;

cout<<"\nAfter postfix decrement";

p1.show();

}

(ii) Explain any two types of inheritance supported in C++ with suitable examples.

C++ Multilevel Inheritance

In C++ programming, not only you can derive a class from the base class but you can also derive

a class from the derived class. This form of inheritance is known as multilevel inheritance.

class A

{

... .. ...

};

class B: public A

{

... .. ...

};

class C: public B

{

... ... ...

};

Here, class B is derived from the base class A and the class C is derived from the derived

class B.

Example 1: C++ Multilevel Inheritance

#include <iostream>

using namespace std;

class A

{

public:

void display()

{

cout<<"Base class content.";

}

};

class B : public A

{

};

class C : public B

{

};

int main()

{

C obj;

obj.display();

return 0;

}

Output

Base class content.

In this program, class C is derived from class B (which is derived from base class A).

The obj object of class C is defined in the main() function.

When the display() function is called, display() in class A is executed. It's because there is

no display() function in class C and class B.

The compiler first looks for the display() function in class C. Since the function doesn't exist

there, it looks for the function in class B (as C is derived from B).

The function also doesn't exist in class B, so the compiler looks for it in classA (as B is derived

from A).

If display() function exists in C, the compiler overrides display() of class A(because of member

function overriding).

C++ Multiple Inheritance

In C++ programming, a class can be derived from more than one parents. For example: A

class Bat is derived from base classes Mammal and WingedAnimal. It makes sense because bat

is a mammal as well as a winged animal.

Example 2: Multiple Inheritance in C++ Programming

This program calculates the area and perimeter of an rectangle but, to perform this program,

multiple inheritance is used.

#include <iostream>

using namespace std;

class Mammal {

public:

Mammal()

{

cout << "Mammals can give direct birth." << endl;

}

};

class WingedAnimal {

public:

WingedAnimal()

{

cout << "Winged animal can flap." << endl;

}

};

class Bat: public Mammal, public WingedAnimal {

};

int main()

{

Bat b1;

return 0;

}

Output

Mammals can give direct birth.

Winged animal can flap.

12. (a) Describe in detail dynamic memory allocation in C++ with examples. (13) [N/D-

16] [M/J – 15]

C++ Dynamic Memory

A good understanding of how dynamic memory really works in C++ is essential to becoming a

good C++ programmer. Memory in your C++ program is divided into two parts:

The stack: All variables declared inside the function will take up memory from the

stack.

The heap: This is unused memory of the program and can be used to allocate the

memory dynamically when program runs.

Many times, you are not aware in advance how much memory you will need to store particular

information in a defined variable and the size of required memory can be determined at run

time.

You can allocate memory at run time within the heap for the variable of a given type using a

special operator in C++ which returns the address of the space allocated. This operator is

callednew operator.

If you are not in need of dynamically allocated memory anymore, you can use delete operator,

which de-allocates memory previously allocated by new operator.

The new and delete operators

There is following generic syntax to use new operator to allocate memory dynamically for any

data-type.

new data-type;

Here, data-type could be any built-in data type including an array or any user defined data

types include class or structure. Let us start with built-in data types. For example we can define

a pointer to type double and then request that the memory be allocated at execution time. We

can do this using the new operator with the following statements:

double* pvalue = NULL; // Pointer initialized with null

pvalue = new double; // Request memory for the variable

The memory may not have been allocated successfully, if the free store had been used up. So it

is good practice to check if new operator is returning NULL pointer and take appropriate action

as below:

double* pvalue = NULL;

if( !(pvalue = new double )) {

cout << "Error: out of memory." <<endl;

exit(1);

}

The malloc() function from C, still exists in C++, but it is recommended to avoid using malloc()

function. The main advantage of new over malloc() is that new doesn't just allocate memory, it

constructs objects which is prime purpose of C++.

At any point, when you feel a variable that has been dynamically allocated is not anymore

required, you can free up the memory that it occupies in the free store with the delete operator

as follows:

delete pvalue; // Release memory pointed to by pvalue

Let us put above concepts and form the following example to show how new and delete work:

#include <iostream>

using namespace std;

int main () {

double* pvalue = NULL; // Pointer initialized with null

pvalue = new double; // Request memory for the variable

*pvalue = 29494.99; // Store value at allocated address

cout << "Value of pvalue : " << *pvalue << endl;

delete pvalue; // free up the memory.

return 0;

}

If we compile and run above code, this would produce the following result:

Value of pvalue : 29495

Dynamic Memory Allocation for Arrays

Consider you want to allocate memory for an array of characters, i.e., string of 20 characters.

Using the same syntax what we have used above we can allocate memory dynamically as

shown below.

char* pvalue = NULL; // Pointer initialized with null

pvalue = new char[20]; // Request memory for the variable

To remove the array that we have just created the statement would look like this:

delete [] pvalue; // Delete array pointed to by pvalue

Following is the syntax of new operator for a multi-dimensional array as follows:

int ROW = 2;

int COL = 3;

double **pvalue = new double* [ROW]; // Allocate memory for rows

// Now allocate memory for columns

for(int i = 0; i < COL; i++) {

pvalue[i] = new double[COL];

}

The syntax to release the memory for multi-dimensional will be as follows:

for(int i = 0; i < ROW; i++) {

delete[] pvalue[i];

}

delete [] pvalue;

Dynamic Memory Allocation for Objects

Objects are no different from simple data types. For example, consider the following code

where we are going to use an array of objects to clarify the concept:

#include <iostream>

using namespace std;

class Box {

public:

Box() {

cout << "Constructor called!" <<endl;

}

~Box() {

cout << "Destructor called!" <<endl;

}

};

int main( ) {

Box* myBoxArray = new Box[4];

delete [] myBoxArray; // Delete array

return 0;

}

If you were to allocate an array of four Box objects, the Simple constructor would be called four

times and similarly while deleting these objects, destructor will also be called same number of

times.

If we compile and run above code, this would produce the following result:

Constructor called!

Constructor called!

Constructor called!

Constructor called!

Destructor called!

Destructor called!

Destructor called!

Destructor called!

(b) Explain the types of inheritance in detail. [N/D-16] [N/D-15]

Inheritance is a mechanism of acquiring the features and behaviors of a class by another class.

The class whose members are inherited is called the base class, and the class that inherits those

members is called the derived class. Inheritance implements the IS-A relationship.

For example, mammal IS-A animal, dog IS-A mammal; Hence dog IS-A animal as well.

Types of Inheritance

In C++, we have 5 different types of Inheritance. Namely,

1. Single Inheritance

2. Multiple Inheritance

3. Hierarchical Inheritance

4. Multilevel Inheritance

5. Hybrid Inheritance (also known as Virtual Inheritance)

Single Inheritance

In this type of inheritance one derived class inherits from only one base class. It is the most

simplest form of Inheritance.

//Base Class

class A

{

public void fooA()

{

//TO DO:

}

}

//Derived Class

class B : A

{

public void fooB()

{

//TO DO:

}

}

Multiple Inheritance

In this type of inheritance a single derived class may inherit from two or more than two base

classes.

//Base Class

class A

{

public void fooA()

{

//TO DO:

}

}

//Base Class

class B

{

public void fooB()

{

//TO DO:

}

}

//Derived Class

class C : A, B

{

public void fooC()

{

//TO DO:

}

}

Hierarchical Inheritance

In this type of inheritance, multiple derived classes inherits from a single base class.

//Base Class

class A

{

public void fooA()

{

//TO DO:

}

}

//Derived Class

class B : A

{

public void fooB()

{

//TO DO:

}

}

//Derived Class

class C : A

{

public void fooC()

{

//TO DO:

}

}

//Derived Class

class D : C

{

public void fooD()

{

//TO DO:

}

}

//Derived Class

class E : C

{

public void fooE()

{

//TO DO:

}

}

//Derived Class

class F : B

{

public void fooF()

{

//TO DO:

}

}

//Derived Class

class G :B

{

public void fooG()

{

//TO DO:

}

}

Multilevel Inheritance

In this type of inheritance the derived class inherits from a class, which in turn inherits from

some other class. The Super class for one, is sub class for the other.

//Base Class

class A

{

public void fooA()

{

//TO DO:

}

}

//Derived Class

class B : A

{

public void fooB()

{

//TO DO:

}

}

//Derived Class

class C : B

{

public void fooC()

{

//TO DO:

}

}

Hybrid (Virtual) Inheritance

Hybrid Inheritance is combination of Hierarchical and Mutilevel Inheritance.

//Base Class

class A

{

public void fooA()

{

//TO DO:

}

}

//Base Class

class F

{

public void fooF()

{

//TO DO:

}

}

//Derived Class

class B : A, F

{

public void fooB()

{

//TO DO:

}

}

//Derived Class

class C : A

{

public void fooC()

{

//TO DO:

}

}

//Derived Class

class D : C

{

public void fooD()

{

//TO DO:

}

}

//Derived Class

class E : C

{

public void fooE()

{

//TO DO:

}

}

(ii) List the rules associated with operator overloading? What are the operators that cannot be

overloaded? Write a program to overload any one of the binary operators? (8) [M/J – 15]

Rules for Overloading Operators

Only existing operators can be overloaded. New operators cannot be created.

The overloaded operator must have atleast one operand that is of user defined type.

The basic meaning of an operator cannot be changed. That is the plus operator cannot be

used to subtract one value from the other.

Overloaded operator follow the syntax rules of the original operators. They cannot be

overridden.

There are some operators that cannot be overloaded. They are Size of, . ,: :,?:.

Friend function cannot be used to overload certain operators ( = ,( ) ,[ ] ,->).However

member functions can be used to overload them.

Unary operators, overload by means of a member function, take no explicit arguments

and return no explicit values,but,those overloaded by means of a friend function, take one

reference argument.

Binary operators overloaded through a member function take one explicit argument and

those which are overloaded through a friend function take two explicit arguments.

When using binary operator overloaded through a member function, the left hand

operand must be an object of the relevant class.

Binary arithmetic operators such as +,-,*,and / must explicitly return a value. They must

not attempt to change their own arguments.

List of operators that cannot be overloaded.

?: (conditional)

. ( member selection)

.* (member selection with pointer-to-member)

:: (scope resolution)

sizeof (object size information)

typeid (object type information)

#include<iostream.h>

#include<conio.h>

class complex

{

int a,b;

public:

void getvalue()

{

cout<<"Enter the value of Complex Numbers a,b:";

cin>>a>>b;

}

complex operator+(complex ob)

{

complex t;

t.a=a+ob.a;

t.b=b+ob.b;

return(t);

}

complex operator-(complex ob)

{

complex t;

t.a=a-ob.a;

t.b=b-ob.b;

return(t);

}

void display()

{

cout<<a<<"+"<<b<<"i"<<"\n";

}

};

void main()

{

clrscr();

complex obj1,obj2,result,result1;

obj1.getvalue();

obj2.getvalue();

result = obj1+obj2;

result1=obj1-obj2;

cout<<"Input Values:\n";

obj1.display();

obj2.display();

cout<<"Result:";

result.display();

result1.display();

getch();

}

Output:

Enter the value of Complex Numbers a, b

4 5

Enter the value of Complex Numbers a, b

2 2

Input Values

4 + 5i

2 + 2i

Result

6 + 7i

2 + 3i

(ii) Define a class Area to identify the area of square and rectangle using constructor and

destructor. Use the parameters length(l) and breadth (b) for the constructor functions.

// using C++ class instead of struct with constructor and destructor

#include <iostream>

using namespace std;

// A simple class declaration

class rectangle

{

// private access by default, access only through the method or interface

int height;

int width;

// public

public:

// constructor, initial object construction, allocating storage, initial value etc.

rectangle(void);

// methods, access something, do something

int area(void);

void initialize(int, int);

// destructor, destroy all the object, return resources such as memory etc. to the system

~rectangle(void);

};

// class implementation

// constructor implementation

rectangle::rectangle(void)

{

// give initial values

height = 6;

width = 6;

}

int rectangle::area(void)

{

// just return the area

return (height * width);

}

void rectangle::initialize(int initial_height, int initial_width)

{

// give initial values

height = initial_height;

width = initial_width;

}

// destructor implementation

rectangle::~rectangle(void)

{

// destroy all the object an return the resources to the system

height = 0;

width = 0;

}

// normal structure - compare with class usage

struct pole

{

int length;

int depth;

};

// comes the main()

void main(void)

{

// class object instantiations

rectangle wall, square;

// normal struct

pole lamp_pole;

cout<<"Check the size of rectangle = "<<sizeof(rectangle)<<" bytes"<<endl;

cout<<"Check the size of pole = "<<sizeof(pole)<<" bytes"<<endl<<endl;

cout<<"Using class instead of struct, using DEFAULT VALUE"<<endl;

cout<<"supplied by constructor, access through area() method"<<endl;

cout<<"----------------------------------------------------"<<endl<<endl;

cout<<"Area of the wall, wall.area() = "<<wall.area()<<endl;

cout<<"Area of the square, square.area() = "<<square.area()<<endl<<endl;

// we can override the constructor values

wall.initialize(12, 10);

square.initialize(8,8);

cout<<"Using class instead of struct, USING ASSIGNED VALUE, access through area()

method"<<endl;

cout<<"---------------------------------------------------------------------------------"<<endl;

cout<<"Area of the wall, wall.area() = "<<wall.area()<<endl;

cout<<"Area of the square, square.area()= "<<square.area()<<endl<<endl;

lamp_pole.length = 50;

lamp_pole.depth = 6;

cout<<"Just a comparison to the class, the following is a struct"<<endl;

cout<<"The length of the lamp pole is = "<<lamp_pole.length*lamp_pole.depth<<endl<<endl;

}

Output example:

Check the size of rectangle = 8 bytes

Check the size of pole = 8 bytes

Using class instead of struct, using DEFAULT VALUE

supplied by constructor, access through area() method

----------------------------------------------------

Area of the wall, wall.area() = 36

Area of the square, square.area() = 36

Using class instead of struct, USING ASSIGNED VALUE, access through area() method

---------------------------------------------------------------------------------

Area of the wall, wall.area() = 120

Area of the square, square.area()= 64

Just a comparison to the class, the following is a struct

The length of the lamp pole is = 300

(ii) Distinguish the term overloading and overriding. (4) [N/D-15]

Overriding Overloading

Methods name and signatures must be same. Having same method name with different

Signatures.

Overriding is the concept of runtime

polymorphism

Overloading is the concept of compile time

polymorphism

When a function of base class is re-defined in

the derived class called as Overriding

Two functions having same name and return

type, but with different type and/or number of

arguments is called as Overloading

It needs inheritance. It doesn't need inheritance.

Method should have same data type. Method can have different data types

Method should be public. Method can be different access specifies

Example

Overriding

public class MyBaseClass

{

public virtual void MyMethod()

{

Console.Write("My BaseClass Method");

}

}

public class MyDerivedClass : MyBaseClass

{

public override void MyMethod()

{

Console.Write("My DerivedClass Method");

}

}

Overloading

int add(int a, int b)

int add(float a , float b) Overloading is defining functions that have similar signatures, yet have

different parameters.

Overriding is only pertinent to derived classes, where the parent class has defined a method and

the derived class wishes to override that function.

Example

Overriding

public class MyBaseClass

{

public virtual void MyMethod()

{

Console.Write("My BaseClass Method");

}

}

public class MyDerivedClass : MyBaseClass

{

public override void MyMethod()

{

Console.Write("My DerivedClass Method");

}

}

Overloading

int add(int a, int b)

int add(float a , float b)

(b) (i) Write a C++ program to explain how the run time polymorphism is achieved.

#include<iostream>

using namespace std;

class B // Base class

{

public:

virtual void Display(void) // virtual function

{

cout << "\n The member function Display( ) " ;

cout << "of the \"Base Class B\" is invoked \n" ;

}

};

class D1 : public B // First derived class

{

public:

void Display(void)

{

cout << "\n The member function Display( ) " ;

cout << "of the \"Derived Class D1\" is invoked \n" ;

}

};

class D2 : public B // Second derived class

{

public:

void Display(void)

{

cout << "\n The member function Display() " ;

cout << "of the \"Derived Class D2\" is invoked " ;

}

};

int main()

{

B* base_ptr ; // Pointer to the object of the base class

D1 der1_obj ; // Object of the first derived class D1

base_ptr = &der1_obj ; /* The address of the object der1_obj of the

first derived class D1 is assigned to the

pointer base_ptr of the base class B */

base_ptr->Display( ); // Accessing the member function Display( )

D2 der2_obj ; // Object of the second derived class D2

base_ptr = &der2_obj ; /* The address of the object der2_obj of the

second derived class D2 is assigned to the

pointer base_ptr of the base class B */

base_ptr->Display( ); // Accessing the member function Display( )

return 0;

}

12. (a) (i) Write a program to perform string copy operation using dynamic

constructor.

(6) [N/D-14]

# include <iostream.h>

# include <conio.h>

# include <string.h>

class str

{

char *name;

int len;

public:

str()

{

len=0;

name=newchar[len+1];

}

str(char *s)

{

len=strlen(s);

name=newchar[len+1];

strcpy(name,s);

}

void show()

{

cout<<"NAME IS:->"<<name<<endl;

}

void join(str &a,str &b);

};

void str::join(str &a,str &b)

{

len=a.len+b.len;

delete new;

name=newchar[len+1];

strcpy(name,a.name);

strcat(name,b.name);

};

main()

{

clrscr();

char *first="HARSHIL";

str n1(first),n2("NINAD"),n3("PRATIK"),n4,n5;

n4.join(n1,n2);

n5.join(n4,n3);

n1.show();

n2.show();

n3.show();

n4.show();

n5.show();

}

(b) (i) Write a program to perform dvnamic initialization of objects. (6) [N/D-

14]

Dynamic Initialization of objects:

It is initializing the objects by passing the valued to the constructor from the user input or

other means. Through cin operator a value can be stored in a variable and passed through a

constructor this form of initializing an object is known dynamic initialization.

Dynamic Constructor:

The memory allocation for a constructor can be managed using new operator called new,

similarly the memory can be free with another operator called deleter.

class dynmem

{ char *name;

int length;

public:

dynmem(void)

{length =0;

name = new char[length+1];

}

dynmem(char *s)

{length = strlen(s);

name = new char[length+1];//for null terminator

strcpy(name,s);

}

void display(void)

{cout<

}

void join(dynmem &a, dynmem &b);

};

void dynmem::join(dynmem &a, dynmem &b)

{length = a.length+b.length;

delete name;

name = new char[length+1]; strcpy(name,a.name); strcat(name,b.name);

};

void main()

{

clrscr();

char *first="Electronic ";

dynmem name1(first);

dynmem name2("and Communication ");

dynmem name3("Engineering"); dynmem s1,s2; s1.join(name1,name2); s2.join(s1,name3);

name1.display();

name2.display(); name3.display(); s1.display(); s2.display();

}