0% found this document useful (0 votes)
4 views

Assignment 8 Solution

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

Assignment 8 Solution

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

Programming in Modern C++: Assignment Week 8

Total Marks : 27

Partha Pratim Das


Department of Computer Science and Engineering
Indian Institute of Technology Kharagpur, Kharagpur – 721302
[email protected]

March 7, 2023

Question 1
Consider the program given below. [MCQ, Marks 2]

#include<iostream>

void validate(int i){


try{
if(i < 0)
throw "negetive";
else if(i > 0)
throw i * 1.00;
else
throw 0;
}
catch(int ){ std::cout << "int "; } //LINE-1
catch(float ){ std::cout << "float "; } //LINE-2
catch(const char* ){ std::cout << "char *"; } //LINE-3
}
int main(){
try{
validate(0);
validate(1);
validate(-1);
}
catch(...) { std::cout << "ALL"; } //LINE-4
}

What will be the output?

a) int float char *

b) int float

c) int ALL

d) int ALL char *

1
Answer: c)
Explanation:
For call validate(0); it executes statement throw 0;, which throws int type exception. int
type exception will be handled within the function validate() and it prints int .
For call validate(1); it executes statement throw i * 1.00;, which throws double type
exception. double type exception will be handled in the main function (because validate()
cannot handle it) and it prints ALL . Due to the exception in main() the control comes out of
the try block.

2
Question 2
Consider the program given below. [MCQ, Marks 2]

#include<iostream>

namespace PrinterErrors{
class PrinterException {};
class NozzleException : public PrinterException{};
class CartridgeException : public PrinterException{};
class HeadException : public PrinterException{};

class Printer{
public:
static void print(int i = 0){
try{
if(i == 0)
throw NozzleException();
else if(i < 0)
throw CartridgeException();
else if (i > 0 && i < 10)
throw HeadException();
else
throw PrinterException();
}
catch(HeadException) { std::cout << "PrinterErrors::HeadException"; }
}
};
}

int main(){
try{
_____________________________; //LINE-1
}
catch(PrinterErrors::PrinterException) {
std::cout << "PrinterErrors::PrinterException";
}
catch(PrinterErrors::NozzleException) {
std::cout << "PrinterErrors::NozzleException";
}
catch(PrinterErrors::CartridgeException) {
std::cout << "PrinterErrors::CartridgeException";
}
return 0;
}

Identify the option/s to fill in the blank at LINE-1 such that output IS NOT
PrinterErrors::PrinterException.

a) PrinterErrors::Printer::print(-1)

b) PrinterErrors::Printer::print(0)

3
c) PrinterErrors::Printer::print(5)

d) PrinterErrors::Printer::print(10)

Answer: c)
Explanation:
For option c), it throws exception HeadException, which is handled by the catch block within
the function print(). Therefore, option c) will print PrinterErrors::HeadException.
For all other options, the exception thrown cannot be handled within the function print().
Since in function main(), the first catch block handles exception PrinterErrors::PrinterException
which is the base class of all exceptions handled by the rest of the catch blocks, all these excep-
tions are handled at the first catch block. Therefore, it prints PrinterErrors::PrinterException.

4
Question 3
Consider the following program. [MCQ, Marks 2]

#include<iostream>

class PrinterException {};


class NozzleException : public PrinterException{};
class CartridgeException : public PrinterException{};

void print(int i){


try{
i < 0 ? throw NozzleException() : throw new CartridgeException();
}
catch(PrinterException) { std::cout << "PrinterException "; }
catch(NozzleException) { std::cout << "NozzleException "; }
catch(CartridgeException) { std::cout << "CartridgeException "; }
};

int main(){
try{
for(int i = -1; i < 2; i++)
print(i);
}
catch(...) { std::cout << "Some other exception "; }
return 0;
}

What will be the output?

a) NozzleException CartridgeException CartridgeException

b) PrinterException Some other exception

c) PrinterException PrinterException

d) NozzleException Some other exception

Answer: b)
Explanation:
For print(-1), the thrown exception type is NozzleException. Since within print() func-
tion, the first catch block handles the exception of type PrinterException that is base class of
NozzleException, the first catch block will handle it and the output will be PrinterException.
For print(0), the thrown exception type is CartridgeException*. Since it is not handled
within print() function, it will be forwarded to main() function. In main(), it will be handled
with printing Some other exception, and the control goes out of for loop.

5
Question 4
Consider the following program. [MCQ, Marks 2]

#include<iostream>

class PrinterException {
public:
virtual const char* what() const throw() {
return "PrinterException*";
}
};
class NozzleException : public PrinterException{
public:
virtual const char* what() const throw() {
return "NozzleException*";
}
};
class CartridgeException : public PrinterException{
public:
virtual const char* what() const throw() {
return "CartridgeException*";
}
};

void print(int i){


try{
i < 0 ? throw new NozzleException() : i == 0 ?
throw new PrinterException(): throw new CartridgeException();
}
catch(NozzleException* e) { std::cout << e->what() << std::endl; }
catch(PrinterException* e) { std::cout << e->what() << std::endl; }
catch(CartridgeException* e) { std::cout << e->what() << std::endl; }
};

int main(){
for(int i = -1; i < 2; i++)
print(i);
return 0;
}

What will be the output?

a) NozzleException* PrinterException* CartridgeException*

b) PrinterException* PrinterException* PrinterException*

c) NozzleException*

d) 7

Answer: a)
Explanation:
For call print(-1), the code within print() throws the exception of type NozzleException*,

6
which is handled by the first catch block. Therefore, the output is NozzleException*.
For call print(0), the code within print() throws the exception of type PrinterException*,
which is handled by the second catch block. Therefore, the output is PrinterException*.
For call print(1), the code within print() throws the exception of type CartridgeException*,
which is handled by the second catch block (because it handles a base type exception). However,
since what() is a virtual function, it will be executed from the subclass CartridgeException.
Therefore, the output is CartridgeException*.

7
Question 5
Consider the following code segment. [MSQ, Marks 2]

#include<iostream>

template<typename T>
int compare(T n1, T n2){
return n1 - n2;
}
int main(){
std::cout << _______________; //LINE-1
return 0;
}

Which of the following call/s to compare at LINE-1 will result in compiler error?

a) compare(’i’, ’k’)

b) compare(31.46, 34.0)

c) compare(31.46, 34)

d) compare(’A’, 34)

Answer: c), d)
Explanation:
Since the types of the actual arguments in the calls in option c) and d) are different, the
deduction of type T is ambiguous. Therefore, it generates a compiler error – ”no matching
function for call to compare”.

8
Question 6
Consider the following code segment. [MCQ, Marks 2]

#include <iostream>

_________________________________________________ //LINE-1
class Pair {
T1 n1;
T2 n2;
public:
Pair(T1 _n1, T2 _n2) : n1(_n1), n2(_n2) { }
void show() {
std::cout << n1 << " " << n2 << std::endl;
}
};

int main(){
Pair<> ob1(120, 88);
ob1.show();
Pair<> ob2('x', 'X');
ob2.show();
return 0;
}

Choose the appropriate option to fill in the blank at LINE-1 so that the output become:
120 X
120 X

a) template<typename T1, typename T2>

b) template<typename T1, typename T2 = char>

c) template<typename T1 = char, typename T2 = char>

d) template<typename T1 = int, typename T2 = char>

Answer: d)
Explanation:
As the output given, the data member n1 should be of type int and n2 should be of type
char. Hence, the template should be defined as template<typename T1 = int, typename
T2 = char>.

9
Question 7
Consider the following program. [MCQ, Marks 2]

#include <iostream>

struct point{
point(int x = 0, int y = 0) : x_(x), y_(y){}
point(const point& p_) : x_(p_.x_), y_(p_.y_){}
void print() { std::cout << "[" << x_ << ", " << y_ << "]"; }
int x_, y_;
};

template<typename T>
class calculator{
public:
calculator(T val) : val_(val){}
T add(calculator c){
val_ += c.val_;
return val_;
}
private:
T val_;
};

___________________________ //LINE-1
__________________________ { //LINE-2
public:
calculator(point val) : val_(val) {}
point add(calculator c){
val_.x_ += c.val_.x_;
val_.y_ += c.val_.y_;
return val_;
}
private:
point val_;
};

int main() {
double d1 = 4.5, d2 = 3.35;
calculator<double> c1(d1);
calculator<double> c2(d2);
std::cout << c1.add(c2) << " ";

point p1 = {10, 20};


point p2 = {2, 3};
calculator<point> c3(p1);
calculator<point> c4(p2);
(c3.add(c4)).print();
return 0;
}

Choose the correct option to fill in the blanks at LINE-1 and LINE-2 so that the output becomes

10
7.85 [12, 23].

a) LINE-1: template<class point> LINE-2: class calculator<>

b) LINE-1: template<class point> LINE-2: class calculator

c) LINE-1: template<> LINE-2: class calculator<point>

d) LINE-1: template<> LINE-2: class calculator

Answer: c)
Explanation:
class calculator is available in two versions. In the generic version and in a specialized
version for point. The template specialization at LINE-1 and the specialized class declaration
at LINE-2 can be done as:
LINE-1: template<>
LINE-2: class calculator<point>

11
Question 8
Consider the following code segment. [MCQ, Marks 2]

#include<iostream>

class Incrementor{
public:
Incrementor(int i = 0) : i_(i){}
________________ { return ++i_; } //LINE-1
________________ { return i_ = i_ + j; } //LINE-2
private:
int i_;
};

int main(){
Incrementor data(10);
std::cout << data(5) << " ";
std::cout << data();
return 0;
}

Choose the appropriate option to fill in the blank at LINE-1 and LINE-2 so that the output
becomes
15 16

a) LINE-1: int operator()


LINE-2: int operator(int j)

b) LINE-1: int data()


LINE-2: int data(int j)

c) LINE-1: int operator()()


LINE-2: int operator()(int j)

d) LINE-1: void operator()()


LINE-2: void operator(int j)()

Answer: c)
Explanation:
Since the statement data(5) in main() function calls function at LINE-2, it should an overload
of the function call operator with single argument and returns int.
Similarly, Since the statement data() in main() function calls function at LINE-1, it should
an overload of the function call operator with no arguments and returns int.

12
Question 9
Consider the following code segment. [MCQ, Marks 2]

#include <iostream>

class compute {
public:
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
};

____________________________________________________ { //LINE-1
return (obj->*fp)(x, y);
}

int main() {
compute cm;
std::cout << caller(10, 20, &cm, &compute::add) << " ";
std::cout << caller(10, 20, &cm, &compute::subtract) << std::endl;
return 0;
}

Choose the appropriate option to fill in the blank at LINE-1 so that the output becomes
30 -10

a) int caller(int& x, int& y, compute* obj, int(compute::fp)(int, int))

b) int caller(int x, int y, compute* obj, int(compute::*fp)(int, int))

c) int caller(int& x, int& y, compute* obj, int(*compute::fp)(int, int))

d) int caller(int x, int y, compute* obj, int*(compute::fp)(int, int))

Answer: b)
Explanation:
The appropriate way to declare a function pointer to point to compute::add and compute::subtract
is as follows:
int(compute::*fp)(int, int))
Therefore, the correct option is b).

13
Programming Questions

Question 1
Consider the program below.

• Fill in the blank at LINE-1 with appropriate template definition for function average.

• Fill in the blank at LINE-2 with appropriate header for function average.

• Fill in the blank at LINE-3 with appropriate declaration of total.

• Fill in the blank at LINE-4 with appropriate declaration of size.

The program must satisfy the given test cases. Marks: 3

#include <iostream>

____________________________________ //LINE-1
__________________________________ { //LINE-2
_________________________ ; //LINE-3
for(int i = 0; i < N; i++)
total += arr[i];
avg = (double)total / N;
}

int main(){
______________ size = 5; //LINE-4
int iA[size];
for(int i = 0; i < size; i++)
std::cin >> iA[i];
double avg = 0.0;
average<int, double, 5>(iA, avg);
std::cout << avg;
return 0;
}

Public 1
Input: 10 20 30 40 50
Output: 30

Public 2
Input: -2 4 5 -1 7
Output: 2.6

Private
Input: 9 10 -5 7 11
Output: 6.4

Answer:
LINE-1: template<typename T1, typename T2, int N>
Or

14
LINE-1: template<class T1, class T2, int N>
LINE-2: void average(T1 arr[], T2& avg)
LINE-3: T1 total = 0
LINE-4: const int
Explanation:
Since the call to the function average is made as:
average<int, double, 5>(iA, avg); , the first two arguments of template are type argu-
ments, whereas the third one is non-type, which can be filled at LINE-1 as:
template<typename T1, typename T2, int N>
Or
template<class T1, class T2, int N>
At LINE-2, the function header can be
void average(T1 arr[], T2& avg)
At LINE-3, the declaration of total can be done as:
T1 total = 0; At LINE-4, the constant size can be declared as:
LINE-4: const int

15
Question 2
Consider the following program.

• Fill in the blank at LINE-1 with an appropriate template definition.

• Fill in the blank at LINE-2 with appropriate initializer list for the constructor.

• Fill in the blanks at LINE-3 with appropriate template definition of function print.

• Fill in the blanks at LINE-4 to complete the header of function print.

The program must satisfy the sample input and output. Marks: 3

#include<iostream>

________________________________ //LINE-1
class FiveVals{
type *base;
public:
FiveVals(type a[]) : ______________ { //LINE-2
for(int i = 0; i < N; i++)
base[i] = a[i];
}
void print();
};

________________________________ //LINE-3
_____________________ ::print(){ //LINE-4
for(int i = 0; i < N; i++)
std::cout << base[i] * 10 << "-";
}

int main(){
int a;
double b;
int c[5];
double d[5];
for(int i = 0; i < 5; i++){
std::cin >> a;
c[i] = a;
}
for(int i = 0; i < 5; i++){
std::cin >> b;
d[i] = b;
}
FiveVals<int, 5> iv(c);
iv.print();
FiveVals<double, 5> dv(d);
dv.print();
return 0;
}

16
Public 1
Input:
1 2 3 4 5
1.1 2.2 3.3 4.4 5.5
Output: 10-20-30-40-50-11-22-33-44-55-

Public 2
Input:
10 20 30 40 50
10.2 20.3 30.4 40.4 50.5
Output: 100-200-300-400-500-102-203-304-404-505-

Private
Input:
1 4 6 8 9
9.1 8.1 7.1 6.1 5.1
Output: 10-40-60-80-90-91-81-71-61-51-

Answer:
LINE-1: template<typename type, int N>
Or
LINE-1: template<class type, int N>
LINE-2: base(new type[N])
LINE-3: template<typename type, int N>
LINE-4: void FiveVals<type, N>
Explanation:
The template definition at LINE-1 must consists of a type parameter and a non-type parameter,
which can be done in any of the following ways:
template<typename type, int N>
Or
template<class type, int N>
At LINE-2, the initialization list can be specified as:
base(new type[N])
At LINE-3, the template definition for function print can be:
template<typename type, int N>
, and the function header can be:
void FiveVals<type, N>

17
Question 3
Consider the following program, in which add function has a generic version along with a
specialized version for complex type.
• Fill in the blank at LINE-1 to define the template for the generic version of add function.
• Fill in the blank at LINE-2 to define the template for the specialize version of add function.
• Fill in the blank at LINE-3 with the header of the specialize version of add function.
The program must satisfy the sample input and output. Marks: 3
#include<iostream>

class complex{
public:
complex(double r = 0.0, double i = 0.0) : r_(r), i_(i){}
int getR(){ return r_; }
int getI(){ return i_; }
friend std::ostream& operator<<(std::ostream& os, const complex& c);
private:
double r_, i_;
};

std::ostream& operator<<(std::ostream& os, const complex& c){


os << c.r_ << " + " << c.i_ << "i";
return os;
}

____________________ //LINE-1
T add(T n1, T n2){
return n1 + n2;
}
___________________ //LINE-2
______________________________ { //LINE-3
complex t(n1.getR() + n2.getR(), n1.getI() + n2.getI());
return t;
}

int main(){
double a, b, c, d;
int e, f;
std::cin >> a >> b >> c >> d >> e >> f;
complex c1(a, b);
complex c2(c, d);
std::cout << add<complex>(c1, c2) << ", ";
std::cout << add<int>(e, f);
return 0;
}

Public 1
Input: 10.4 4.5 2.5 2.5 10 20
Output: 12 + 6i, 30

18
Public 2
Input: 1 2 3 4 5 -4
Output: 4 + 6i, 1

Private
Input: 1.1 2.2 3.1 3.2 2 3
Output: 4 + 5i, 5

Answer:
LINE-1: template<class T>
LINE-2: template<>
LINE-3: complex add<complex>(complex n1, complex n2)
Explanation:
The template for the generic version of add can be defined as:
template<class T>
The template for the generic version of add and its header can be defined as:
template<>
complex add<complex>(complex n1, complex n2)

19

You might also like