You are on page 1of 24

1.

Modify the Tv and Remote classes as follows:


a. Make them mutual friends.
b. Add a state variable member to the Remote class that describes whether the
remote
control is in normal or interactive mode.
c. Add a Remote method that displays the mode.
d. Provide the Tv class with a method for toggling the new Remote member. This
method should work only if the TV is in the on state.
Write a short program that tests these new features.
tv.h
1 #ifndef TV_H_
2 #define TV_H_
3 class Tv
4{
5 public:
6

friend class Remote; // Remote can access Tv private parts

enum {Off, On};

enum {MinVal,MaxVal = 20};

enum {Antenna, Cable};

1
0

enum {TV, VCR};

1
1
1
2

Tv(int s = Off, int mc = 100) : state(s), volume(5),


maxchannel(mc), channel(2), mode(Cable), input(TV) {}
void onoff() {state = (state == On)? Off : On;}
bool ison() const {return state == On;}

1
3

bool volup();

1
4

void chanup();

bool voldown();

1
5

void chandown();

1
6

void set_input() {input = (input == TV)? VCR : TV;}

1
7

bool changeRmode(Remote & r);

void set_mode() {mode = (mode == Antenna)? Cable : Antenna;}

void settings() const; // display all settings

1 private:
8
int state; // on or off
1
9

2
0
2
1
2
2

int volume; // assumed to be digitized


int maxchannel; // maximum number of channels
int channel; // current channel setting
int mode; // broadcast or cable
int input; // TV or VCR

2 };
3
class Remote
2
4{
2 private:
5
int mode; // on or off
2
6

int i_mode;

2
8

friend class Tv;

enum {Normal, Interactive}; // Normal or Interactive mode


2
7 public:

2
9
3
0
3
1
3
2
3
3

Remote(int m = Tv::TV) : mode(m), i_mode(Normal) {}


bool volup(Tv & t) { return t.volup();}
bool voldown(Tv & t) { return t.voldown();}
void onoff(Tv & t) { t.onoff(); }
void chanup(Tv & t) {t.chanup();}
void chandown(Tv & t) {t.chandown();}
void set_chan(Tv & t, int c) {t.channel = c;}
void set_mode(Tv & t) {t.set_mode();}
void set_input(Tv & t) {t.set_input();}

3
void disp_mode() { std::cout << "Remote mode is " << (i_mode ==
4 Normal? "Normal.\n" : "Interactive.\n"); }
3 };
5
#endif
3
6
3
7
3
8
3

9
4
0
4
1
4
2
4
3
4
4
4
5
4
6
4
7
4
8
4
9
5
0
tv.cpp
1 #include <iostream>
2 #include "tv.h"
3
4 bool Tv::volup()
5 {
6

if (volume < MaxVal)

volume++;

return true;

10

11

else

12

return false;

13 }
14
15 bool Tv::voldown()
16 {
17

if (volume > MinVal)

18

19

volume--;

20

return true;

21

22

else

23

return false;

24 }
25
26 void Tv::chanup()
27 {
28
29
30
31

if (channel < maxchannel)


channel++;
else
channel = 1;

32 }
33
34 void Tv::chandown()
35 {
36

if (channel > 1)

37

channel--;

38
39

else
channel = maxchannel;

40 }
41
42 void Tv::settings() const
43 {
44

using std::cout;

45

using std::endl;

46

cout << "TV is " << (state == Off? "Off" : "On") << endl;

47

if (state == On)

48

49

cout << "Volume setting = " << volume << endl;

50

cout << "Channel setting = " << channel << endl;

51

cout << "Mode = "

52

<< (mode == Antenna? "antenna" : "cable") << endl;

53

cout << "Input = "

54

<< (input == TV? "TV" : "VCR") << endl;

55

56 }
57
58 bool Tv::changeRmode(Remote & r)
59 {
60

if (state == Off)

61

62

std::cout << "Tv is Off, remote mode cannot be changed!\n";

63

return false;

64

65

else

66

67

r.i_mode = (r.i_mode == r.Normal)? r.Interactive: r.Normal;

68

return true;

69

70 }
cp15ex1.cpp
1

#include <iostream>

#include "tv.h"

3
4

int main()

using namespace std;

Tv s27;

cout << "Initial settings for 27\" TV:\n";

s27.settings();

10
11

Remote red;

12

red.disp_mode();

13
14

s27.changeRmode(red);

15

s27.onoff();

16

s27.settings();

17

s27.changeRmode(red);

18

red.disp_mode();

19

red.onoff(s27);

20

s27.changeRmode(red);

21
22

red.onoff(s27);

23

s27.changeRmode(red);

24

red.disp_mode();

25
26

cin.get();

27

cin.get();

28

return 0;

29

2. Modify Listing 15.11 so that the two exception types are classes derived from
the
logic_error class provided by the header file. Have each what() method
report the function name and the nature of the problem. The exception objects
need not
hold the bad values; they should just support the what() method.
exc_mean.h
1 #ifndef EXC_MEAN_H

2
3
4
5
6
7
8

#define EXC_MEAN_H

#include <iostream>
#include <stdexcept>

class bad_hmean : public std::logic_error


1
0{
1 public:
1
bad_hmean() : std::logic_error("hmean() invalid arguments: a = -b\n") {} //
1 string to be displayed for what() method
2
};
1
3
class bad_gmean : public std::logic_error
1
4{
1 public:
5
bad_gmean() : std::logic_error("gmean() arguments should be >= 0\n")
1 {} // string to be displayed for what() method
6
};
1
7
#endif
1
8
1
9
cp15ex2.cpp
1 #include <iostream>
2 #include <cmath> // or math.h, unix users may need -lm flag
3 #include "exc_mean.h"
4
5 // function prototypes
6 double hmean(double a, double b) throw(bad_hmean); // each function gets
personal exception type

7 double gmean(double a, double b) throw(bad_gmean);


8
9 int main()
1{
0
1
1
1
2

using std::cout;
using std::cin;
using std::endl;
double x, y, z;

1
3

cout << "Enter two numbers: ";

1
4

while (cin >> x >> y)

try { // start of try block

1
5

z = hmean(x,y);

1
6

cout << "Harmonic mean of " << x << " and " << y

1
7

cout << "Geometric mean of " << x << " and " << y

<< " is " << z << endl;

<< " is " << gmean(x,y) << endl;

1
8

cout << "Enter next set of numbers <q to quit>: ";

1
9
2
0

}// end of try block


catch (bad_hmean & bg) // start of catch block
{

2
1

cout << bg.what();


cout << "Try again.\n";

2
2

continue;

2
3

2
4

catch (bad_gmean & hg)

cout << hg.what();

2
5
2
6
2
7

cout << "Sorry, you dont get to play any more.\n";


break;
} // end of catch block
}

2
8

cout << "Bye!\n";

2
9

cin.get();
cin.get();

3
0

return 0;

3}
1
3
2 double hmean(double a, double b) throw(bad_hmean) // each function gets
personal exception type, ie bad_Hmean
3
3{
3
4

if (a == -b)

3
5

return 2.0 * a * b / (a + b);

3
6

throw bad_hmean(); // if invalid arguments throw the exception

3 double gmean(double a, double b) throw(bad_gmean) // bad_Gmean exception


7
{
3
if (a < 0 || b < 0)
8
throw bad_gmean(); // if invalid arguments throw the exception
3
9
return std::sqrt(a * b);
4}
0
4
1
4
2
4
3
4
4
4
5
4
6
4

7
4
8
4
9
5
0
5
1
5
2
5
3
5
4
5
5
5
6
5
7
5
8

3. This exercise is the same as Programming Exercise 2, except that the


exceptions should
be derived from a base class (itself derived from logic_error) that stores the two
argument
values, the exceptions should have a method that reports these values as well as
the function name, and a single catch block that catches the base-class
exemption
should be used for both exceptions, with either exception causing the loop to
terminate.
excpt.h
1 #ifndef EXCPT_H
2 #define EXCPT_H
3
4 #include <iostream>
5 #include <stdexcept>

6
7 class abc_bad : public std::logic_error
8{
9 protected:
1
0

double v1;
double v2;

1
public:
1
abc_bad(const char * s ="not defined yet", double a = 0, double b = 0) :
1
std::logic_error(s), v1(a), v2(b) {}
2
virtual void mesg() const = 0;
1
3
virtual ~abc_bad() {}
1 };
4
1
5 class bad_hmean : public abc_bad
1{
6 public:
1
bad_hmean(double a, double b) : abc_bad("\ninvalid arguments: a = -b\n", a,
7 b) {}
1
8
1
9

void mesg() const;


};

2 inline void bad_hmean::mesg() const


0
{
2
std::cout << "hmean(" << v1 << ", " << v2 <<"): ";
1
std::cout << what();
2
2}
2
3

class bad_gmean : public abc_bad


2
4{
2 public:
5
bad_gmean(double a = 0, double b = 0) : abc_bad("\ngmean() arguments
should
be >= 0\n", a, b) {}
2
6

void mesg() const;

2
7
2
8
2
9
3
0
3
1
3
2
3
3 };
3
4 inline void bad_gmean::mesg() const
3{
5
3
6

std::cout << "Values used: " << v1 << ", " << v2;
std::cout << what();

3}
7
3 #endif
8
3
9
4
0
4
1
4
2
4
3
4
4
cp15ex3.cpp
1

#include <iostream>

#include <cmath> // or math.h, unix users may need -lm flag

#include "excpt.h"

4
5

// function prototypes

double hmean(double a, double b) throw(abc_bad);

double gmean(double a, double b) throw(abc_bad);

8
9

int main()

10 {
11

using std::cout;

12

using std::cin;

13

using std::endl;

14

double x, y, z;

15

cout << "Enter two numbers: ";

16

while (cin >> x >> y)

17

18

try { // start of try block

19

z = hmean(x,y);

20

cout << "Harmonic mean of " << x << " and " << y

21

<< " is " << z << endl;

22

cout << "Geometric mean of " << x << " and " << y

23

<< " is " << gmean(x,y) << endl;

24

cout << "Enter next set of numbers <q to quit>: ";

25

}// end of try block

26
27

catch (abc_bad & abc)

28

29

abc.mesg();

30

cout << "Sorry, you dont get to play any more.\n";

31

break;

32
33

} // end of catch block


}

34
35

cin.get();

36

cin.get();

37

cout << "Bye!\n";

38

return 0;

39 }
40
41 double hmean(double a, double b) throw(abc_bad)
42 {
43

if (a == -b)

44

throw bad_hmean(a, b);

45

return 2.0 * a * b / (a + b);

46 }
47
48 double gmean(double a, double b) throw(abc_bad)
49 {
50

if (a < 0 || b < 0)

51
52

throw bad_gmean(a, b);


return std::sqrt(a * b);

53 }

4. Listing 15.16 uses two catch blocks after each try block so that the nbad_index
exception
leads to the label_val() method being invoked. Modify the program so that it uses
a single catch block after each try block and uses RTTI to handle invoking
label_val() only when appropriate.
sales.h
1 #include <stdexcept>
2 #include <cstring>
3 class Sales
4 {
5 public:
6

enum {MONTHS = 12}; // could be a static const

7
8

class bad_index : public std::logic_error

1
0

private:
int bi; // bad index value

1
1

public:
explicit bad_index(int ix, const char * s = "Index error in Sales object\n");

1
2

int bi_val() const {return bi;}

1
3

};

1
4

explicit Sales(int yy = 0);

1
5

Sales(int yy, const double * gr, int n);

1
6

int Year() const { return year; }

1
7

virtual double & operator[](int i) throw(std::logic_error);

1
8

virtual ~Sales() { }

virtual double operator[](int i) const throw(std::logic_error);

private:

1
9
2
0 };

double gross[MONTHS];
int year;

2
1

class LabeledSales : public Sales


2
2 {
2 public:
3
static const int STRLEN = 50; // could be an enum
2
4
2
5

class nbad_index : public Sales::bad_index


{

2
6

private:

2
7

public:

char lbl[STRLEN];

2
nbad_index(const char * lb, int ix, const char * s = "Index error in
8 LabeledSales object\n");
2
9

const char * label_val() {return lbl;}


};

3
0
3
1

explicit LabeledSales(const char * lb = "none", int yy = 0);


LabeledSales(const char * lb, int yy, const double * gr, int n);

3
2

virtual ~LabeledSales() { }

3
3

virtual double operator[](int i) const throw(std::logic_error);

3
4

const char * Label() const {return label;}

virtual double & operator[](int i) throw(std::logic_error);

3 private:
5
char label[STRLEN];
3
6 };
3
7
3
8
3
9
4
0
4
1
4
2
4
3
4
4
4
5
4
6
4

7
4
8
4
9
5
0
5
1
5
2
sales.cpp
1 #include "sales.h"
2
3 Sales::bad_index::bad_index(int ix, const char * s ) : std::logic_error(s), bi(ix) {}
4
5 Sales::Sales(int yy)
6{
7

year = yy;

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

gross[i] = 0;

1}
0
1
Sales::Sales(int yy, const double * gr, int n)
1
{
1
2
year = yy;
1
3

int lim = (n < MONTHS)? n : MONTHS;

1
4

for (i = 0; i < lim; ++i)

int i;

1
5

gross[i] = gr[i];

1
6

for ( ; i < MONTHS; ++i)

1
7

// for i > n and i < MONTHS

gross[i] = 0;

1}
8
1
double Sales::operator[](int i) const throw(std::logic_error)
9
{
2
0
if(i < 0 || i >= MONTHS)
2
1

throw bad_index(i);

2
2}

return gross[i];

2
3 double & Sales::operator[](int i) throw(std::logic_error)
2{
4
2
5
2
6

if(i < 0 || i >= MONTHS)


throw bad_index(i);
return gross[i];

2
7
LabeledSales::nbad_index::nbad_index(const char * lb, int ix, const char * s ) :
2
Sales::bad_index(ix, s)
8
{
2
9
std::strcpy(lbl, lb);
3}
0
3
1 LabeledSales::LabeledSales(const char * lb, int yy) : Sales(yy)
3{
2
std::strcpy(label, lb);
3}
3
3
4 LabeledSales::LabeledSales(const char * lb, int yy, const double * gr, int n) :
Sales(yy, gr, n)
3
5{
std::strcpy(label, lb);
3
6}
3

7
3 double LabeledSales::operator[](int i) const throw(std::logic_error)
8
{
3
if(i < 0 || i >= MONTHS)
9
throw nbad_index(Label(), i);
4
0
return Sales::operator[](i);
4}
1
4
2 double & LabeledSales::operator[](int i) throw(std::logic_error)
4{
3
if(i < 0 || i >= MONTHS)
4
4
4
5}
4
6
4
7
4
8
4
9
5
0
5
1
5
2
5
3
5
4
5
5
5
6

throw nbad_index(Label(), i);


return Sales::operator[](i);

5
7
5
8
5
9
6
0
6
1
6
2
6
3
6
4
6
5
cp15ex4.cpp
1 #include <iostream>
2 #include "sales.h"
3
4 int main()
5{
6

using std::cout;

using std::cin;

using std::endl;

9
1
0

double vals1[12] =
{

1
1
1
2
1
3
1

1220, 1100, 1122, 2212, 1232, 2334,


2884, 2393, 3302, 2922, 3002, 3544
};

double vals2[12] =

1
5

12, 11, 22, 21, 32, 34,

1
6
1
7
1
8
1
9

28, 29, 33, 29, 32, 35


};

Sales sales1(2004, vals1, 12);


LabeledSales sales2("Blogstar",2005, vals2, 12 );
LabeledSales::nbad_index * excpt;

2
0

cout << "First try block:\n";

2
1

try

int i;

2
2

cout << "Year = " << sales1.Year() << endl;


for (i = 0; i < 12; ++i)

2
3

2
4

cout << sales1[i] << ' ';


if (i % 6 == 5)

2
5

cout << endl;

2
6

}
cout << "Year = " << sales2.Year() << endl;

2
7

cout << "Label = " << sales2.Label() << endl;


for (i = 0; i <= 12; ++i)

2
8

2
9

cout << sales2[i] << ' ';


if (i % 6 == 5)

3
0

cout << endl;


}

3
1
3
2
3
3

cout << "End of try block 1.\n";


}

catch(Sales::bad_index & bad)

3
4
3
5
3
6

{
cout << bad.what();
if (excpt = dynamic_cast<LabeledSales::nbad_index *>(&bad)) // if ref
exception = nbax_index
cout << "Company: " << excpt->label_val() << endl; // display a
message specific to that certain class

3
7
3
8

cout << "bad index: " << bad.bi_val() << endl;


}

3
9

cout << "\nNext try block:\n";

4
0

try

4
1

sales2[2] = 37.5;

4
2

cout << "End of try block 2.\n";

4
3
4
4
4
5

sales1[20] = 23345;

catch(Sales::bad_index & bad)


{
cout << bad.what();

if (excpt = dynamic_cast<LabeledSales::nbad_index *>(&bad)) // if ref


4
exception = nbax_index
6
cout << "Company: " << excpt->label_val() << endl; // display a
4
message specific to that certain class
7
cout << "bad index: " << bad.bi_val() << endl;
4
8
}
4
9
5
0
5
1
5}
2
5

cout << "done\n";


cin.get();
cin.get();
return 0;

3
5
4
5
5
5
6
5
7
5
8
5
9
6
0
6
1
6
2
6
3
6
4
6
5
6
6
6
7
6
8
6
9
7
0
7
1
7
2

7
3
7
4
7
5
7
6