当前位置: 首页 > 工具软件 > V2EX PLUS > 使用案例 >

C.Primer.Plus(第六版)第15章 编程练习

堵浩波
2023-12-01
//sales.h     //15.4
#ifndef SALES__H__
#define SALES__H__
#include <stdexcept>
#include <string>
class Sales
{
public:
	enum{MONTHS = 12};
	class bad_index : public std::logic_error
	{
	private:
		int bi;
	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 LabeledSales : public Sales
{
public:
	class nbad_index : public Sales::bad_index
	{
	private:
		std::string lbl;
	public:
		nbad_index(const std::string & lb,int ix,
			const std::string & s = "Index error in LabeledSales object\n");
		const std::string & label_val() const {return lbl;}
		virtual ~nbad_index() throw() {}
	};
	explicit LabeledSales(const std::string & lb = "none",int yy = 0);
	LabeledSales(const std::string & lb, int yy ,const double* gr,int n);
	virtual ~LabeledSales() {}
	const std::string & Label() const {return label;}
	virtual double operator[] (int i) const;
	virtual double & operator[] (int i);
private:
	std::string label;
};
#endif
//sales.cpp
#include "sales.h"
using std::string;
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 < 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];  
}  
  
LabeledSales::nbad_index::nbad_index(const std::string &lb, int ix, const std::string &s) : Sales::bad_index(ix, s)  
{  
    lbl = lb;  
}  
  
LabeledSales::LabeledSales(const std::string &lb, int yy) : Sales(yy)  
{  
    label = lb;  
}  
  
LabeledSales::LabeledSales(const std::string &lb, int yy, const double *gr, int n) : Sales(yy, gr, n)  
{  
    label = lb;  
}  
  
double LabeledSales::operator[](int i) const  
{  
    if (i < 0 || i >= MONTHS)  
        throw nbad_index(Label(), i);  
    return Sales::operator[](i);  
}  
  
double &LabeledSales::operator[](int i)  
{  
    if (i < 0 || i >= MONTHS)  
        throw nbad_index(Label(), i);  
    return Sales::operator[](i);  
}  
//use_sales.cpp
#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);  
    LabeledSales sales2("Blogstar", 2012, vals2, 12);  
  
    cout << "First try block:\n";  
    try  
    {  
        int i;  
        cout << "Year = " << sales1.Year() << std::endl;  
        for (i = 0; i < 12; ++i)  
        {  
            cout << sales1[i] << ' ';  
            if (i % 6 == 5)  
                cout << endl;  
        }  
        cout << "Year = " << sales2.Year() << endl;  
        cout << "Label = " << sales2.Label() << endl;  
        for (i = 0; i <= 12; ++i)  
        {  
            cout << sales2[i] << ' ';  
            if (i % 6 == 5)  
                cout << endl;  
        }  
        cout << "End of try block 1.\n";  
    } 
	catch(std::logic_error & log)//能捕捉基类及其派生类的的异常
	{
		cout<<log.what();
		if(LabeledSales::nbad_index* nbad = dynamic_cast<LabeledSales::nbad_index *>(&log))
		{	//如果上面表示传入实参的类型为尖括号内的类型或其派生类,则返回传入对象的地址,否则传入空地址。
			 cout << "Company: " << nbad->label_val() << endl;  
             cout << "bad index: " << nbad->bi_val() << endl; 
		}
		else if(LabeledSales::bad_index* bad = dynamic_cast<LabeledSales::bad_index *>(&log))
		{
			 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 (std::logic_error &log)  
    {  
        cout << log.what();  
        if (LabeledSales::nbad_index *nbad = dynamic_cast<LabeledSales::nbad_index *>(&log))  
        {  
            cout << "Company: " << nbad->label_val() << endl;  
            cout << "bad index: " << nbad->bi_val() << endl;  
        }  
        else if (Sales::bad_index *bad = dynamic_cast<Sales::bad_index *>(&log))  
            cout << "bad index: " << bad->bi_val() << endl;  
    }  
    return 0;  
}
//exc_mean.h //15.3
#include <iostream>
#include <stdexcept>
using namespace std;
class base : public logic_error
{
private:
	double v1;
	double v2;
public:
	base(double a = 0,double b =0):v1(a),v2(b),logic_error("base"){}
	virtual ~base(){}
	virtual void mesg() const;
};
inline void base::mesg() const
{
	std::cout<<"The argument 'a' is "<<v1<<" ,and the argument 'b' is "
		<<v2<<endl;
}
class bad_hmean : public base
{
public:
	bad_hmean(double a = 0,double b = 0) : base(a,b)
	{
		//logic_error("bad_hmean");
	}
	const char* what() const {return "bad_gmean";}
	virtual void mesg() const;
};
inline void bad_hmean::mesg() const
{
	base::mesg();
	std::cout<<" the function name is "<<what()<<endl;
}
class bad_gmean : public base
{
public:
	bad_gmean(double a = 0,double b = 0):base(a,b)
	{
	//logic_error("bad_gmean");
	}
	const char* what() const {return "bad_gmean";}//新定义了一个what方法,而不是重定义基类的what方法,因为不知道怎么使用才能满足条件。
	virtual void mesg() const;
};
inline void bad_gmean::mesg() const
{
	base::mesg();
	std::cout<<" the function name is "<<(*this).what()<<endl;
}
//error4.cpp
#include <iostream>
#include <cmath>
#include "exc_mean.h"

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
		{
			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>:";
		}
		catch(const base & bg)
		{
			bg.mesg();
			cout<<"Done!\n";
			break;
		}
	}
	cout<<"Bye!\n";
	return 0;
}
double hmean(double a,double b)
{
	if(a == -b)
		throw bad_hmean(a,b);
	return 2.0 * a *b /(a+b);
}
double gmean(double a, double b)
{
	if(a<0||b<0)
		throw bad_gmean(a,b);
	return std::sqrt(a*b);
}

//15.2
//exc_mean.h
#include <iostream>
#include <stdexcept>
#include <stdexcpt.h>
using namespace std;
class bad_hmean : public logic_error
{
private:
	double v1;
	double v2;
public:
	bad_hmean(double a = 0,double b =0):v1(a),v2(b),logic_error("1"){}
	void mesg();
	void what();
};
inline void bad_hmean::what() 
{
	std::cout<<"hmean(" << v1<<" ,"<<v2<<"): "
		<<"invalie arguments: a = -b\n";
}
class bad_gmean
{
public:
	double v1;
	double v2;
	bad_gmean(double a = 0,double b = 0):v1(a),v2(b){}
	const char* what();
};
inline const char* bad_gmean::what()
{
	return "gmean() argument should be >= 0\n";
}

//error4.cpp
#include <iostream>
#include <cmath>
#include "exc_mean.h"

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
		{
			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>:";
		}
		catch(bad_hmean & bg)
		{
			bg.what();
			cout<<"Try again.\n";
			continue;
		}
		catch(bad_gmean & hg)
		{
			hg.what();
			cout<<"Values used: "<<hg.v1<<" , "<<hg.v2<<endl;
			cout<<"Sorrt,you don't get to play any more.\n";
			break;
		}
	}
	cout<<"Bye!\n";
	return 0;
}
double hmean(double a,double b)
{
	if(a == -b)
		throw bad_hmean(a,b);
	return 2.0 * a *b /(a+b);
}
double gmean(double a, double b)
{
	if(a<0||b<0)
		throw bad_gmean(a,b);
	return std::sqrt(a*b);
}

//tv.h -- Tv and Remote classes   //15.1
#ifndef TV__H__
#define TV__H__
class Tv
{
public:
	friend class Remote;
	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 state == On;}
	bool volup();
	bool voldown();
	void chanup();
	void chandown();
	void set_mode() {mode = (mode == Antenna)? Cable : Antenna;}
	void set_input() {input = (input == TV)? DVD : TV;}
	void settings() const ;
	void change_sta_mode(Remote & r) const;
private:
	int state;
	int volume;
	int maxchannel;
	int channel;
	int mode;
	int input;
};
class Remote
{
private:
	int sta_mode;
	int mode;
public:
	friend class Tv;
	enum{NORMAl_STATUS,INTERACTIVE_STATUS};
	Remote(int m = Tv::TV):mode(m),sta_mode(NORMAl_STATUS){}
	bool volup(Tv & t) {return t.volup();}
	bool voldown(Tv & t) {return t.voldown();}
	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) {}
	void show() const ;
};
#endif
//tv.cpp
#include <iostream>
#include "tv.h"

bool Tv::volup()
{
	if(volume < MaxVal)
	{
		volume++;
		return true;
	}
	else 
		return false;
}
bool Tv::voldown()
{
	if(volume>MinVal)
	{
		volume--;
		return true;
	}
	else
		return false;
}
void Tv::chanup()
{
	if(channel < maxchannel)
		channel++;
	else
		channel = 1;
}
void Tv::chandown()
{
	if(channel > 1)
		channel--;
	else
		 channel = maxchannel;
}
void Tv::settings() const 
{
	using std::cout;
	using std::cin;
	using std::endl;
	cout<<"TV is "<<(state == Off? "Off" : "On")<<endl;
	if(state == On)
	{
		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::change_sta_mode(Remote & r) const
{
	if(state == On)
		r.sta_mode = (r.sta_mode == r.NORMAl_STATUS?r.INTERACTIVE_STATUS : r.NORMAl_STATUS);
}
void Remote::show() const 
{
	if(sta_mode == NORMAl_STATUS)
		std::cout<<"the status mode is NORMAl_STATUS."<<std::endl;
	else
		std::cout<<"the status mode is INTERACTIVE_STATUS."<<std::endl;
}
//use_tv.cpp
#include <iostream>
#include "tv.h"

int main()
{
	using std::cout;
	Tv s42;
	cout<<"Initial settings for 42\"TV :\n";
	s42.settings();
	s42.onoff();
	s42.chanup();
	cout<<"\nAdjusted settings for 42\"TV :\n";
	s42.chanup();
	cout<<"\nAdjusted settings for 42\"TV :\n";
	s42.settings();
	Remote grey;
	grey.set_chan(s42,10);
	grey.volup(s42);
	grey.volup(s42);
	cout<<"\n42\" settings after using remote:\n";
	s42.settings();
	Tv s58(Tv::On);
	s58.set_mode();
	grey.set_chan(s58,28);
	cout<<"\n58\" settings:\n";
	s58.settings();
	grey.show();
	s58.change_sta_mode(grey);
	grey.show();
	return 0;
}


 类似资料: