【第十五章】C++ Primer plus 的编程练习题

#pragma once
// tv2.h -- Tv and Remote classes
#ifndef __TV2_H__
#define __TV2_H__

class Tv
{
public:
	friend class Remote;  // Remote can access Tv private parts
	enum { Off, On };
	enum { MinVal, MaxVal = 20 };
	enum { Antenna, Cable };
	enum { TV, DVD };

	Tv(int s = Off, int mc = 125) : state(s), volume(5),
		maxchannel(mc), channel(2), mode(Cable), input(TV) { }
	void onOff() { state = (state == On) ? Off : On; }
	bool isOn() const { return On == state; }
	bool volUp();
	bool volDown();
	void chanUp();
	void chanDown();
	void set_mode() { mode = (Antenna == mode) ? Cable : Antenna; }
	void set_input() { input = (TV == input) ? DVD : TV; }
	void setting() const;  // display all settings
	void set_dispaly_mode(Remote & r);
private:
	int state;      // on or off
	int volume;     // assumed to be diginized // 音量
	int maxchannel; // maximum number of channels // 最大的电视频道
	int channel;    // current channel setting // 当前电视频段
	int mode;       // broadcast or cable // 
	int input;      // TV or DVD
};

class Remote
{
public:
	enum { RegularMode, InteractionMode };
private:
	int mode;        // constrol TV or DVD
	int status;
public:
	friend class Tv;  // TV can access Remote private parts
	Remote(int m = Tv::TV, int state = RegularMode) : mode(m), status(state){ }
	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(); }
	void displayMode() const {
		std::cout << "DisplayMode: " << (status == RegularMode ? 
			      "RegularMode" : "InteractionMode") << std::endl;
	}
};

#endif /* __TV2_H__ */

// tv2.cpp -- methods for the Tv class (Remote methods are inline)
#include <iostream>
#include "tv2.h"

// class Tv methods
bool Tv::volUp()
{
	if (volume < MaxVal) {  // MaxVal: 音量的最大值
		volume++;
		return true;
	} else
		return false;
}

bool Tv::volDown()
{
	if (volume > MinVal) {  // MinVal: 音量的最小值
		volume--;
		return true;
	}
	else
		return false;
}

void Tv::chanUp()
{
	if (channel < maxchannel) {  // maxchannel: 频道的最大值
		channel++;
	}
	else
		channel = 1;  // 频道的范围:1 ~ maxchannel
}

void Tv::chanDown()
{
	if (channel > 1) {  // 1: 频道的最小值
		channel--;
	}
	else
		channel = maxchannel;  // 频道的范围:1 ~ maxchannel
}

void Tv::setting() const
{
	using std::cout;
	using std::endl;
	cout << "TV is " << (Off == state? "Off" : "On") << endl;
	if (On == state) {
		cout << "Volume setting = " << volume << endl;
		cout << "Channel setting = " << channel << endl;
		cout << "Mode = "
			 << (mode == Antenna? "antenna" : "cable") << endl;
		cout << "Input = " 
			 << (input == TV? "TV" : "DVD") << endl;
	}
}

void Tv::set_dispaly_mode(Remote & r) {
	if (On == state) {
		r.status = (r.status == Remote::RegularMode)
			? Remote::InteractionMode
			: Remote::RegularMode;
	}
}




/***********************************
	2017年12月11日 19:58:29
	Athor:xiyuan255
	Course:C++
	Contain:use_tv2.cpp.cpp
			tv2.h
			tv2.cpp
	Reference: C++ Primer plus
		知识点:友元类的应用
		总结:如果类A成为类B的友元类,那么类A可以访问类B的私有成员的含义是:
		      类A可以通过类B对象的引用间接访问类B的私有成员。无法直接使用
			  类B私有成员名,直接访问。
			  因为,类A可能不只是类B的的友元类,直接使用私有成员名,无法知道
			  它是属于哪个类的私有成员。		      
	说明:C++ Primer plus第十五章的练习题 第一题
		 【 参考 P654 】
*************************************/
// use_tv.cpp -- using the TV and Remote classes
#include <iostream>
#include "tv2.h"

int main()
{
	using std::cout;
	Tv s42;
	Remote grey;
	cout << "Initial setting for 42\" TV:\n";
	s42.setting();
	grey.displayMode();
	s42.onOff();
	s42.set_dispaly_mode(grey);
	grey.displayMode();
	s42.chanUp();
	cout << "\nAdjusted setting for 42\" TV:\n";
	s42.setting();

	grey.set_chan(s42, 10);
	grey.volUp(s42);
	grey.volUp(s42);
	cout << "\n42\" setting after using remote:\n";
	s42.setting();

	return 0;
}

/**
输出结果:
	Initial setting for 42" TV:
	TV is Off
	DisplayMode: RegularMode
	DisplayMode: InteractionMode

	Adjusted setting for 42" TV:
	TV is On
	Volume setting = 5
	Channel setting = 3
	Mode = cable
	Input = TV

	42" setting after using remote:
	TV is On
	Volume setting = 7
	Channel setting = 10
	Mode = cable
	Input = TV
*/

#pragma once
// exc_mean2.h -- exception classes for hmean(), gmean()
#ifndef __EXC_MEAN2_H__
#define __EXC_MEAN2_H__
#include <iostream>
#include <stdexcept>  // for class logic_error and class runtime_error

class bad_hmean : public std::logic_error
{
public:
	bad_hmean(const std::string & str = "bad_hmean(): invalid argument: a = -b")
		: logic_error(str) { }
};

class bad_gmean : public std::logic_error
{
public:
	bad_gmean(const std::string & str = "gmean() arguments should be >= 0")
		: logic_error(str) { }
};

#endif /* __EXC_MEAN2_H__ */

/***********************************
	2017年12月11日 20:24:40
	Athor:xiyuan255
	Course:C++
	Contain:pe15-2.cpp
			exc_mean2.h
	Reference: C++ Primer plus
	知识点:异常应用
		1.在头文件stdexcept中包含两个从exception异常基类继承而来的
		  子异常类,分别是logic_error和runtime_error;
		2.logic_error类下有一个异常构造函数,参数为const string &
		  类型,而logic_error类还有一个what的方法,用于logic_error
		  对象,并把该对象转换为const string 类型。
	说明:C++ Primer plus第十五章的练习题 第二题
	【 参考 P654 】
*************************************/
// pe15-2.cpp -- using exception classes
#include <iostream>
#include <cmath>   // or math.h, unix users may need -lm flag
#include "exc_mean2.h"

// function ptototypes
double hmean(double a, double b);
double gmean(double a, double b);

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

	double x, y, z;

	cout << "Enter two numbers: ";
	while (cin >> x >> y) {
		try {                  // start of block
			z = hmean(x, y);
			cout << "Harmonic mean of " << x << " and " << y
				<< " is " << z << endl;
			cout << "Geometric mean of " << x << " and " << y
				<< " is " << gmean(x, y) << endl;
			cout << "Enter next set of numbers <q to quit>: ";
		} // end of try block
		catch (bad_hmean & bg) {   // start of catch block
			cout << bg.what() << endl;
			cout << "Try again.\n";
			continue;
		}
		catch (bad_gmean & hg) {   // start of catch block
			cout << hg.what() << endl;
			cout << "Sorry, you don't get to play any more.\n";
			break;
		}  // end of catch block
		
	}
	std::cout << "Bye!\n";

	return 0;
}

/**
输出结果:
	Enter two numbers: 4 12
	Harmonic mean of 4 and 12 is 6
	Geometric mean of 4 and 12 is 6.9282
	Enter next set of numbers <q to quit>: 5 -5
	bad_hmean(): invalid argument: a = -b
	Try again.
	5 -2
	Harmonic mean of 5 and -2 is -6.66667
	gmean() arguments should be >= 0
	Sorry, you don't get to play any more.
	Bye!
*/

double hmean(double a, double b)
{
	if (a == -b)
		throw bad_hmean();
	return 2.0 * a * b / (a + b);
}

double gmean(double a, double b)
{
	if (a < 0 || b < 0)
		throw bad_gmean();
	return std::sqrt(a * b);
}

#pragma once
// exc_mean3.h -- exception classes for hmean(), gmean()
#ifndef __EXC_MEAN3_H__
#define __EXC_MEAN3_H__
#include <iostream>
#include <stdexcept>  // for class logic_error and class runtime_error

class bad_base : public std::logic_error
{
private:
	double v1;
	double v2;
public:
	bad_base(const std::string str, double val1, double val2)
		: logic_error(str), v1(val1), v2(val2) { }
	double v1_val() { return v1; }
	double v2_val() { return v2; }
	virtual void report() { }
};

class bad_hmean : public bad_base
{
public:
	bad_hmean(const std::string str, double a = 0, double b = 0) 
		: bad_base(str, a, b) { }
	virtual void report() { 
		std::cout << "hmean(" << v1_val() << ", " << v2_val() << "): ";
	}
};

class bad_gmean : public bad_base
{
public:
	bad_gmean(const std::string str, double a = 0, double b = 0)
		: bad_base(str, a, b) { }
	virtual void report() {
		std::cout << "gmean(" << v1_val() << ", " << v2_val() << "): ";
	}
};

#endif /* __EXC_MEAN2_H__ */

/***********************************
	2017年12月11日 20:55:55
	Athor:xiyuan255
	Course:C++
	Contain:pe15-3.cpp
			exc_mean3.h
	Reference: C++ Primer plus
	知识点:异常应用
		1.基类异常对象引用可以捕获它的所有派生类的异常对象引用;
	说明:C++ Primer plus第十五章的练习题 第三题
	【 参考 P654 】
*************************************/
// pe15-3.cpp -- using exception classes
#include <iostream>
#include <cmath>   // or math.h, unix users may need -lm flag
#include "exc_mean3.h"

// function ptototypes
double hmean(double a, double b);
double gmean(double a, double b);

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

	double x, y, z;

	cout << "Enter two numbers: ";
	while (cin >> x >> y) {
		try {                  // start of block
			z = hmean(x, y);
			cout << "Harmonic mean of " << x << " and " << y
				<< " is " << z << endl;
			cout << "Geometric mean of " << x << " and " << y
				<< " is " << gmean(x, y) << endl;
			cout << "Enter next set of numbers <q to quit>: ";
		} // end of try block
		catch (bad_base & hg) {   // start of catch block
			hg.report();
			cout << hg.what() << endl;
			cout << "Sorry, you don't get to play any more.\n";
			break;
		}  // end of catch block
		
	}
	std::cout << "Bye!\n";

	return 0;
}

/**
输出结果1:
	Enter two numbers: 4 12
	Harmonic mean of 4 and 12 is 6
	Geometric mean of 4 and 12 is 6.9282
	Enter next set of numbers <q to quit>: 5 -5
	hmean(5, -5): invalid arguments : a = -b
	Sorry, you don't get to play any more.
	Bye!

输出结果2:
	Enter two numbers: 4 12
	Harmonic mean of 4 and 12 is 6
	Geometric mean of 4 and 12 is 6.9282
	Enter next set of numbers <q to quit>: 5 -2
	Harmonic mean of 5 and -2 is -6.66667
	gmean(5, -2): arguments should be >= 0
	Sorry, you don't get to play any more.
	Bye!

*/

double hmean(double a, double b)
{
	if (a == -b)
		throw bad_hmean("invalid arguments : a = -b", a, b);
	return 2.0 * a * b / (a + b);
}

double gmean(double a, double b)
{
	if (a < 0 || b < 0)
		throw bad_gmean("arguments should be >= 0", a, b);
	return std::sqrt(a * b);
}

#pragma once
// sales.h -- exceptions and inheritance
#ifndef __SALES_H__
#define __SALES_H__
#include <stdexcept>  // stdexcept从exception基类继承而来 for logic_error
#include <string>

class Sales
{
public:
	enum { MONTHS = 12 };   // could be a static const 
	class bad_index : public std::logic_error
	{
	private:
		int bi;   // bad index value
	public:
		explicit bad_index(int ix, 
			const std::string & s = "Index error in Sales object\n");
		int bi_val() const { return bi; }
		virtual ~bad_index() throw() { }
	};
	explicit Sales(int yy = 0);
	Sales(int yy, const double * gr, int n);
	virtual ~Sales() { }
	int Year() const { return year; }
	virtual double operator[](int i) const;
	virtual double & operator[](int i);
private:
	double gross[MONTHS];
	int year;
};

class LabelSales : public Sales
{
public:
	class nbad_index : public Sales::bad_index 
	{
	private:
		std::string lb1;
	public:
		nbad_index(const std::string & lb, int ix,
			const std::string & s = "Index error in LabelSales object\n");
		const std::string & label_val() const { return lb1; }
		virtual ~nbad_index() throw() { }
	};
	explicit LabelSales(const std::string & lb = "none", int yy = 0);
	LabelSales(const std::string & lb, int yy, const double * gr, int n);
	virtual ~LabelSales() { }
	const std::string & Label() const { return label; }
	virtual double operator[](int i) const;
	virtual double & operator[](int i);
private:
	std::string label;
};

#endif /* __SALES_H__ */

/* programNo15.15 */
// sales.cpp -- Sales implementation
#include "sales.h"
using std::string;

// class Sales methods
Sales::bad_index::bad_index(int ix, const std::string & s)
	: std::logic_error(s), bi(ix)
{
}

Sales::Sales(int yy)
{
	year = yy;
	for (int i = 0; i < MONTHS; i++)
		gross[i] = 0;
}

Sales::Sales(int yy, const double * gr, int n)
{
	year = yy;
	int lim = (n < MONTHS) ? n : MONTHS;
	int i;
	for (i = 0; i < lim; i++)
		gross[i] = gr[i];
	// for i > n and i < MONTHS;
	for ( ; i < MONTHS; i++)
		gross[i] = 0;
}

double Sales::operator[](int i) const
{
	if (i < 0 || i >= MONTHS)
		throw bad_index(i);
	return gross[i];
}

double & Sales::operator[](int i)
{
	if (i < 0 || i >= MONTHS)
		throw bad_index(i);
	return gross[i];
}

// class LabelSales methods
LabelSales::nbad_index::nbad_index(const std::string & lb, int ix,
	const std::string & s) : Sales::bad_index(ix, s)
{
	lb1 = lb;
}

LabelSales::LabelSales(const std::string & lb, int yy)
	: Sales(yy)
{
	label = lb;
}

LabelSales::LabelSales(const std::string & lb, int yy, const double * gr,
		int n) : Sales(yy, gr, n)
{
	label = lb;
}

double LabelSales::operator[](int i) const
{
	if (i < 0 || i >= MONTHS)
		throw nbad_index(Label(), i);
	return Sales::operator[](i);
}

double & LabelSales::operator[](int i)
{
	if (i < 0 || i >= MONTHS)
		throw nbad_index(Label(), i);
	return Sales::operator[](i);
}

/***********************************
	2017年12月11日 21:12:45
	Athor:xiyuan255
	Course:C++
	Contain:use_sales2.cpp
			sales2.h
			sales2.cpp
	Reference: C++ Primer plus
	说明:C++ Primer plus第十五章的练习题 第四题
		 【 参考 P654 】
*************************************/
// use_sales.cpp -- nested exceptions 
#include <iostream>
#include "sales.h"

int main()
{
	using std::cout;
	using std::cin;
	using std::endl;
	double vals1[12] = {
			1220, 1100, 1122, 2212, 1232, 2334,
			2884, 2393, 3302, 2922, 3002, 3544,
		};
	
	double vals2[12] = {
			12, 11, 22, 21, 32, 34,
			28, 29, 33, 29, 32, 35,
		};
	Sales sales1(2011, vals1, 12);
	LabelSales sales2("Blogstar", 2012, vals2, 12);

	cout << "First try block:\n";
	try {
		int i;
		cout << "Year = " << sales1.Year() << endl;
		for (i = 0; i < 12; i++) {
			cout << sales1[i] << ' ';
			if (5 == i % 6)
				cout << endl;
		}
		cout << "Year = " << sales2.Year() << endl;
		cout << "Label = " << sales2.Label() << endl;
		for (i = 0; i <= 12; i++) {
			cout << sales2[i] << ' ';
			if (5 == i % 6)
				cout << endl;
		}
		cout << "End of try block 1.\n";
	} catch (Sales::bad_index & bad) {
		cout << bad.what();
		if (LabelSales::nbad_index * p = dynamic_cast<LabelSales::nbad_index *> (&bad))
			cout << "Company: " << p->label_val() << endl;
		cout << "bad index: " << bad.bi_val() << endl;
	}

	cout << "\nNext try block:\n";
	try {
		sales2[2] = 37.5;
		sales1[20] = 23345;
		cout << "End of try block 2.\n";
	} catch (Sales::bad_index & bad) {
		cout << bad.what();
		if (LabelSales::nbad_index * p = dynamic_cast<LabelSales::nbad_index *> (&bad))
			cout << "Company: " << p->label_val() << endl;
		cout << "bad index: " << bad.bi_val() << endl;
	}
	cout << "Done.\n";

	return 0;
}

/**
输出结果:
	First try block:
	Year = 2011
	1220 1100 1122 2212 1232 2334
	2884 2393 3302 2922 3002 3544
	Year = 2012
	Label = Blogstar
	12 11 22 21 32 34
	28 29 33 29 32 35
	Index error in LabelSales object
	Company: Blogstar
	bad_index: 12

	Next try block:
	Index error in Sales object
	bad index: 20
	Done.
*/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值