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

// vector1.h -- Vector class with <<, mode state
#ifndef __VECTOR1_H__
#define __VECTOR1_H__

#include <iostream>

namespace VECTOR1
{
	class Vector
	{
	public:
		enum Mode { RECT, POL };
	// RECT for rectangular, POL for Polar modes
	private:
		double x;    // horizontal value
		double y;    // vertical value
		double mag;  // length of vector
		double ang;  // direction of vector in degrees
		Mode mode;   // RECT or POL
	// private methods for setting values
		void set_mag();
		void set_ang();
		void set_x();
		void set_y();
	public:
		Vector();
		Vector(double n1, double n2, Mode form = RECT);
		void reset(double n1, double n2, Mode form = RECT);
		~Vector();
		double xVal() const { return x; }      // report x value
		double yVal() const { return y; }      // report y value
		double magVal() const { return mag; }  // report magnitude
		double angVal() const { return ang; }  // report angle
		void polar_mode();                     // set mode to POL
		void rect_mode();                      // set mode to RECT
	// operator overloading // 类的成员函数对符号的重载
		Vector operator+(const Vector & b) const;
		Vector operator-(const Vector & b) const;
		Vector operator-() const;
		Vector operator*(double n) const;
	// friends // 类的非成员函数(友元函数)对符号的重载
		friend Vector operator*(double n, const Vector & a);
		friend std::ostream & 
			operator<<(std::ostream & os, const Vector & v);
	};

}  // end namespace VECTOR1 

#endif /* __VECTOR1_H__ */

// vector1.cpp -- methods for the Vector class
#include <cmath>
#include "vector1.h"  // include <iostream>

using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;

namespace VECTOR1
{
	// compute degrees in one radian
	const double Rad_to_deg = 45.0 / atan(1.0);
	// shoule be about 57.2957795130823

	// private methods
	// calculates magnitude from x and y
	void Vector::set_mag()
	{
		mag = sqrt(x * x + y * y);
	}
	void Vector::set_ang()
	{
		if (0.0 == x && 0.0 == y)
			ang = 0.0;
		else
			ang = atan2(y, x);
	}

	// set x from polar coordinate
	void Vector::set_x()
	{
		x = mag * cos(ang);
	}

	// set y from polar coordinate
	void Vector::set_y()
	{
		y = mag * sin(ang);
	}

	// public methods
	Vector::Vector()      // default constructor
	{
		x = y = mag = ang = 0.0;
		mode = RECT;
	}

	// construct vector from rectangular coordinates if form is r
	// (the default) or else from polar coordinates if form is p
	Vector::Vector(double n1, double n2, Mode form)
	{
		mode = form;
		if (RECT == form) {
			x = n1; 
			y = n2;
			set_mag();
			set_ang();
		} else if (POL == form) {
			mag = n1;
			ang = n2;
			set_x();
			set_y();
		} else {
			cout << "Incorrect 3rd argument to Vector() -- ";
			cout << "vector set to 0\n";
			x = y = mag = ang = 0.0;
			mode = RECT;
		}
	}

	// reset vector from rectangular coordinates if form is 
	// RECT (the default) or else from polar coordinates if
	// form is POL
	void Vector::reset(double n1, double n2, Mode form)
	{	
		mode = form;
		if (RECT == form) {
			x = n1;
			y = n2;
			set_mag();
			set_ang();
		} else if (POL == form) {
			mag = n1;
			ang = n2;
			set_x();
			set_y();
		} else {
			cout << "Incorrect 3rd argument to Vector() -- ";
			cout << "vector set to 0\n";
			x = y = mag = ang = 0.0;
			mode = RECT;
		}
	
	}

	Vector::~Vector()   // destructor
	{
	}

	void Vector::polar_mode()   // set to polar mode
	{
		mode = POL;
	}

	void Vector::rect_mode()   // set to rectangular mode
	{
		mode = RECT;
	}

	// operator overloading
	// add to Vectors
	Vector Vector::operator+(const Vector & b) const
	{
		// 调用构造函数会自动生成一个临时对象来存放这些值
		return Vector(x + b.x, y + b.y); 
		// 等价 {
			/*		Vector sum;
					sum.x = x + b.x;
					sum.y = y + b.y;
					sum.set_ang(sum.x, sum.y);
					sum.set_ang(sum.x, sum.y);
					return sum;    // version duplicates needlessly
					*/
               //}
	} 
    

	// subtract Vector b from a
	Vector Vector::operator-(const Vector & b) const
	{
		return Vector(x - b.x, y - b.y);
	}

	// reverse sign of Vector
	Vector Vector::operator-() const
	{
		return Vector(-x, -y);
	}

	// multiply vector by n
	Vector Vector::operator*(double n) const
	{
		return Vector(n * x, n * y);
	}

	// friend methods
	// multiply n by Vector a
	Vector operator*(double n, const Vector & a)
	{
		return a * n;
	}

	// display rectangular coordinates if mode is RECT
	// else display polar coordinates if mode is POL
	std::ostream & operator<<(std::ostream & os, const Vector & v)
	{ // 因为该函数是友元函数,不属于类成员,所以使用RECT和POL
	  // 需要加Vector::来访问类的枚举成员
		if (v.mode == Vector::RECT)
			os << "(x, y) = (" << v.x << ", " << v.y << ")";
		else if (v.mode == Vector::POL) {
			os << "(m, a) = (" << v.mag << ", " 
			   << v.ang * Rad_to_deg << ")";
		} else
			os << "Vector object mode is invalid";

		return os;
	}

}  // end namespace VECTOR1 

/***********************************
	2017年11月13日16:11:48
	Athor:xiyuan255
	Course:C++
	Contain:randwalk1.cpp
			 vactor1.h
		     vactor1.cpp
	Reference: C++ Primer plus
	说明:C++ Primer plus第十一章的第一题练习题
		 【 P423 】
*************************************/
// randwalk1.cpp -- using the Vector class
// compile with the vector1.cpp file
#include <iostream>
#include <cstdlib>    // rand(), srand() prototypes
#include <ctime>      // time() prototype
#include <fstream>    // ofstream and ifstream
#include "vector1.h"

int main()
{
	using namespace std;
	using VECTOR1::Vector;
	srand(time(0));     // seed random-number generator
	double direction;
	Vector step;
	Vector result(0.0, 0.0);
	unsigned long steps = 0;
	double target;
	double dstep;
	ofstream fout;
	fout.open("reault.txt");
	if (!fout.is_open()) {
		cout << "File reault.txt cannot open.\n";
		exit(-1);
	}
	cout << "Enter target distance (q to quit): ";
	while (cin >> target) {
		cout << "Enter step length: ";
		if (!(cin >> dstep)) 
			break;
		fout << "Target Distance: " << target << ", Step: " << dstep << endl;
		while (result.magVal() < target) {
			fout << steps << ": " << result << endl;
			direction = rand() % 360;
			step.reset(dstep, direction, Vector::POL);
			result = result + step;
			steps++;
		}
		fout << "After " << steps << " steps, the subject "
			"has the following location:\n";
		fout << result << endl;
		result.polar_mode();
		fout << " or\n" << result << endl;
		fout << "Average outward distance per step = "
			 << result.angVal() / steps << endl;
		steps = 0;
		result.reset(0.0, 0.0);
		cout << "Enter target distance (q to quit): ";
	}
	cout << "check reault.txt file -Bye!\n";
	/* 当cin >> xxx 返回错误时,会堵塞输入序列,则需要
	 * 使用cin.clear() 重新打开输入序列 */
	cin.clear();
	while (cin.get() != '\n')
		continue;

	return 0;
}

/**
输出结果:
	Enter target distance (q to quit): 100
	Enter step length: 20
	Enter target distance (q to quit): q
	check reault.txt file -Bye!
result.txt文件的内容是:
	Target Distance: 100, Step: 20
	0: (x, y) = (0, 0)
	1: (x, y) = (-3.95627, 19.6048)
	2: (x, y) = (-8.94766, 38.9719)
	3: (x, y) = (-6.73931, 19.0942)
	4: (x, y) = (-24.4987, 9.89616)
	5: (x, y) = (-32.1727, -8.57301)
	6: (x, y) = (-12.2854, -6.45266)
	7: (x, y) = (-10.2537, 13.4439)
	8: (x, y) = (-26.4339, 1.68797)
	9: (x, y) = (-43.8565, -8.13298)
	10: (x, y) = (-51.5305, -26.6022)
	11: (x, y) = (-71.1526, -30.4716)
	12: (x, y) = (-52.7176, -38.2273)
	13: (x, y) = (-70.3113, -47.7383)
	14: (x, y) = (-61.3504, -29.8581)
	15: (x, y) = (-44.1947, -19.578)
	16: (x, y) = (-25.2571, -26.0098)
	17: (x, y) = (-30.2485, -6.64271)
	18: (x, y) = (-12.3288, -15.5244)
	19: (x, y) = (-10.8255, -35.4678)
	20: (x, y) = (8.99858, -38.1149)
	21: (x, y) = (-10.9889, -37.4075)
	22: (x, y) = (8.9829, -36.3458)
	23: (x, y) = (28.9328, -34.9308)
	24: (x, y) = (26.5486, -15.0734)
	25: (x, y) = (6.56816, -15.9583)
	26: (x, y) = (-4.97189, 0.376584)
	27: (x, y) = (-6.47461, -19.5669)
	28: (x, y) = (-25.8196, -14.4904)
	29: (x, y) = (-41.1275, -27.3616)
	30: (x, y) = (-53.9304, -42.7267)
	31: (x, y) = (-34.6784, -37.308)
	32: (x, y) = (-51.8345, -27.0285)
	33: (x, y) = (-62.6411, -10.1994)
	34: (x, y) = (-76.499, 4.22138)
	35: (x, y) = (-56.9865, 8.61047)
	36: (x, y) = (-74.6641, 17.9648)
	37: (x, y) = (-84.0966, 0.328869)
	38: (x, y) = (-88.5714, -19.1641)
	39: (x, y) = (-70.206, -11.245)
	40: (x, y) = (-59.5488, -28.1691)
	41: (x, y) = (-39.8612, -31.6901)
	42: (x, y) = (-53.1999, -16.7878)
	43: (x, y) = (-55.7592, -36.6234)
	44: (x, y) = (-35.7662, -37.1538)
	45: (x, y) = (-45.5095, -54.62)
	46: (x, y) = (-25.5095, -54.62)
	47: (x, y) = (-42.7555, -64.7479)
	48: (x, y) = (-23.2826, -69.3089)
	49: (x, y) = (-31.9261, -51.2731)
	50: (x, y) = (-11.9543, -50.2115)
	51: (x, y) = (-27.8171, -38.0306)
	52: (x, y) = (-38.324, -21.0128)
	53: (x, y) = (-18.8923, -16.279)
	54: (x, y) = (-14.7627, -35.848)
	55: (x, y) = (-24.8136, -53.1391)
	56: (x, y) = (-44.8065, -53.6701)
	57: (x, y) = (-25.0066, -56.4919)
	58: (x, y) = (-7.58362, -66.3123)
	59: (x, y) = (0.253528, -47.9118)
	60: (x, y) = (20.0535, -50.7336)
	61: (x, y) = (0.754301, -55.9817)
	62: (x, y) = (-3.37475, -75.5508)
	63: (x, y) = (2.29849, -94.7293)
	64: (x, y) = (-15.6991, -86.0065)
	After 65 steps, the subject has the following location:
	(x, y) = (-31.6687, -98.047)
	 or
	(m, a) = (103.035, -107.9)
	Average outward distance per step = -0.0289725

*/
// stonewt2.cpp -- Stonewt methods
#include <iostream>
using std::cout;
#include "stonewt2.h"

// constructor Stonewt object from double value
Stonewt::Stonewt(double lbs)
{
	stone = int (lbs) / Lbs_per_stn;   // integer division
	pds_left = int (lbs) % Lbs_per_stn + lbs - int(lbs);
	pounds = lbs;
}

// constructor Stonewt object from stone, double values
Stonewt::Stonewt(int stn, double lbs)
{
	stone = stn;
	pds_left = lbs;
	pounds = stn * Lbs_per_stn + lbs;
}

Stonewt::Stonewt()  // default constructor, wt = 0
{
	stone = pounds = pds_left = 0;
}

Stonewt::~Stonewt()  // destructor 
{

}

void Stonewt::setState()
{
	using std::cout;
	using std::cin;

	int mode = 0;
	cout << "Enter object fromat:\n"
		 << " 1) stone format         2) integer pounds format\n"
		 << " 3) double pounds format 4) unkown \n";
	cin >> mode;
	if (1 == mode) {
		state = STON_FORMAT;
	} else if (2 == mode) {
		state = INT_POUN_FORMAT;
	} else if (3 == mode) {
		state = DOU_POUN_FORMAT;
	} else {
		cout << "Not the this object format!\n";
	}
}

void Stonewt::resetStonewt(double lbs)
{
	stone = int (lbs) / Lbs_per_stn;   // integer division
	pds_left = int (lbs) % Lbs_per_stn + lbs - int(lbs);
	pounds = lbs;
}

void Stonewt::resetStonewt(int stn, double lbs)
{
	stone = stn;
	pds_left = lbs;
	pounds = stn * Lbs_per_stn + lbs;
}

// overload operator
Stonewt Stonewt::operator+(const Stonewt & swt) const
{
	return Stonewt(pounds + swt.pounds);
}

Stonewt Stonewt::operator-(const Stonewt & swt) const
{
	return Stonewt(pounds - swt.pounds);
}

Stonewt Stonewt::operator*(double m) const
{
	return Stonewt(pounds * m);
}

Stonewt Stonewt::operator/(const Stonewt & swt) const
{
	return Stonewt(pounds / swt.pounds);
}

std::ostream & operator<<(std::ostream & os, const Stonewt & swt)
{
	if (swt.state == Stonewt::STON_FORMAT) {
		os << swt.stone << " stone, " << swt.pds_left << " pounds ";
	} else if (swt.state == Stonewt::INT_POUN_FORMAT) {
		os << int(swt.pounds + 0.5) << " pounds ";
	} else if (swt.state == Stonewt::DOU_POUN_FORMAT) {
		os << swt.pounds << " pounds ";
	} else {
		os << "Output error not the this object!";
	}
	return os;
}

/***********************************
	2017年11月14日13:10:48
	Athor:xiyuan255
	Course:C++
	Contain:usestone.cpp
			 stonewt2.h
		     stonewt2.cpp
	Reference: C++ Primer plus
	说明:C++ Primer plus第十一章的第五题练习题
		 【 P423 】
*************************************/
// usestone.cpp -- user-defined conversions
// compile with stonewt2.cpp
#include <iostream>
using std::cout;
using std::endl;
#include "stonewt2.h"

int main()
{
	// 只有有一个参数的构造函数才可如此调用
	Stonewt incognito = 275;  // uses constructor to initialize 
	// or Stonewt incognito = Stonewt(275); // 显式调用构造函数
	// or Stonewt incognito(275); // 隐式调用构造函数

	Stonewt wolfe(285.7);     // same as Stonewt wolfe = 285.7;
	Stonewt taft(21, 8);     

	incognito.setState();
	cout << "The celebrity weighed ";
	cout << incognito << endl;

	Stonewt sum = incognito + wolfe;
	sum.setState();
	cout << "sum = ";
	cout << sum << endl;

	Stonewt sub = wolfe - incognito;
	sub.setState();
	cout << "sub = ";
	cout << sub << endl;

    Stonewt mult = 2 * taft;
	mult.setState();
	cout << "mult = ";
	cout << mult << endl;

	Stonewt div = mult / taft;
	div.setState();
	cout << "div = ";
	cout << div << endl;

	incognito.resetStonewt(255);
	incognito.setState();
	cout << "incognito = ";
	cout << incognito << endl;

	return 0;
}

/**
输出结果:
	Enter object fromat:
	 1) stone format         2) integer pounds format
	 3) double pounds format 4) unkown
	2
	The celebrity weighed 275 pounds
	Enter object fromat:
	 1) stone format         2) integer pounds format
	 3) double pounds format 4) unkown
	3
	sum = 560.7 pounds
	Enter object fromat:
	 1) stone format         2) integer pounds format
	 3) double pounds format 4) unkown
	3
	sub = 10.7 pounds
	Enter object fromat:
	 1) stone format         2) integer pounds format
	 3) double pounds format 4) unkown
	1
	mult = 43 stone, 2 pounds
	Enter object fromat:
	 1) stone format         2) integer pounds format
	 3) double pounds format 4) unkown
	1
	div = 0 stone, 2 pounds
	Enter object fromat:
	 1) stone format         2) integer pounds format
	 3) double pounds format 4) unkown
	2
	incognito = 255 pounds
*/

// stonewt3.h -- definition for the Stonewt class
#ifndef __STONEWT3_H__
#define __STONEWT3_H__
#include <iostream>

class Stonewt
{
private:
	enum Mode_e { STON_FORMAT, INT_POUN_FORMAT, DOU_POUN_FORMAT };
    static const int Lbs_per_stn = 14; // 一英石 = 14磅
	Mode_e state;
	int stone;                    // whole stones (英石)
	double pds_left;              // fractional pounds (不够1英石的磅重量)
	double pounds;                // entire weight in pounds (磅)
public:
	Stonewt(double lbs);          // constructor for double pounds
	Stonewt(int stn, double lbs); // constructor for stone, lbs
	Stonewt();  // 默认的构造函数
	~Stonewt(); // 析构函数

	void setState();
	void setState(int mode);
	void resetStonewt(double lbs);
	void resetStonewt(int stn, double lbs);

	// conversion function  // 转换函数
	operator double() const;
	operator int() const;

	// overload operator  // 运算符的重载函数
	bool operator>(const Stonewt & swt) const;
	bool operator<(const Stonewt & swt) const;
	bool operator>=(const Stonewt & swt) const;
	bool operator<=(const Stonewt & swt) const;
	bool operator==(const Stonewt & swt) const;
	bool operator!=(const Stonewt & swt) const;

	// 友元函数
	friend std::ostream & operator<<(std::ostream & os, const Stonewt & swt);
	friend std::istream & operator>>(std::istream & is, Stonewt & swt);
};

#endif /* __STONEWT3_H__ */

// stonewt3.cpp -- Stonewt methods
#include <iostream>
#include "stonewt3.h"

// constructor Stonewt object from double value
Stonewt::Stonewt(double lbs)
{
	stone = int (lbs) / Lbs_per_stn;   // integer division
	pds_left = int (lbs) % Lbs_per_stn + lbs - int(lbs);
	pounds = lbs;
}

// constructor Stonewt object from stone, double values
Stonewt::Stonewt(int stn, double lbs)
{
	stone = stn;
	pds_left = lbs;
	pounds = stn * Lbs_per_stn + lbs;
}

Stonewt::Stonewt()  // default constructor, wt = 0
{
	stone = pounds = pds_left = 0;
}

Stonewt::~Stonewt()  // destructor 
{

}

void Stonewt::setState()
{
	using std::cout;
	using std::cin;

	int mode = 0;
	cout << "Enter object fromat:\n"
		 << " 1) stone format         2) integer pounds format\n"
		 << " 3) double pounds format 4) unkown \n";
	cin >> mode;
	if (1 == mode) {
		state = STON_FORMAT;
	} else if (2 == mode) {
		state = INT_POUN_FORMAT;
	} else if (3 == mode) {
		state = DOU_POUN_FORMAT;
	} else {
		cout << "Not the this object format!\n";
	}
}

void Stonewt::setState(int mode)
{
	using std::cout;
	if (1 == mode) {
		state = STON_FORMAT;
	} else if (2 == mode) {
		state = INT_POUN_FORMAT;
	} else if (3 == mode) {
		state = DOU_POUN_FORMAT;
	} else {
		cout << "Not the this object format!\n";
	}
}

void Stonewt::resetStonewt(double lbs)
{
	stone = int (lbs) / Lbs_per_stn;   // integer division
	pds_left = int (lbs) % Lbs_per_stn + lbs - int(lbs);
	pounds = lbs;
}

void Stonewt::resetStonewt(int stn, double lbs)
{
	stone = stn;
	pds_left = lbs;
	pounds = stn * Lbs_per_stn + lbs;
}

Stonewt::operator double() const
{
	return pounds;
}

Stonewt::operator int() const
{
	return int (pounds + 0.5);
}

// overload operator
bool Stonewt::operator>(const Stonewt & swt) const
{
	return (pounds > swt.pounds);
}

bool Stonewt::operator<(const Stonewt & swt) const
{
	return (pounds < swt.pounds);
}

bool Stonewt::operator>=(const Stonewt & swt) const
{
	//return (pounds >= swt.pounds);
	if (pounds >= swt.pounds)
		return true;
	else
		return false;
}

bool Stonewt::operator<=(const Stonewt & swt) const
{
	return (pounds <= swt.pounds);
}

bool Stonewt::operator==(const Stonewt & swt) const
{
	return (pounds == swt.pounds);
}

bool Stonewt::operator!=(const Stonewt & swt) const
{
	return (pounds != swt.pounds);
}

std::ostream & operator<<(std::ostream & os, const Stonewt & swt)
{
	if (swt.state == Stonewt::STON_FORMAT) {
		os << swt.stone << " stone, " << swt.pds_left << " pounds ";
	} else if (swt.state == Stonewt::INT_POUN_FORMAT) {
		os << (int)swt.pounds << " pounds ";
	} else if (swt.state == Stonewt::DOU_POUN_FORMAT) {
		os << swt.pounds << " pounds ";
	} else {
		os << "Output error not the this object!";
	}
	return os;
}

std::istream & operator>>(std::istream & is, Stonewt & swt)
{
	double temp;
	is >> temp;
	swt.resetStonewt(temp);

	return is;
}

/***********************************
	2017年11月14日17:07:39
	Athor:xiyuan255
	Course:C++
	Contain:usestone3.cpp
			 stonewt3.h
		     stonewt3.cpp
	Reference: C++ Primer plus
	说明:C++ Primer plus第十一章的第六题练习题
		 【 P423 】
*************************************/
// usestone3.cpp -- user-defined conversions
// compile with stonewt3.cpp
#include <iostream>
#include "stonewt3.h"

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

	Stonewt temp(11, 0);
	Stonewt ston[6] = { 10, 11, 12 };
	cout << "enter last third element value: \n";
	for (int i = 3; i < 6; i++) {
		cout << " #" << i << " element value:";
		if (!(cin >> ston[i]))
			break;
		
	}

	cout << "Set array stone display format:\n"
		 << " 1) stone format         2) integer pounds format\n"
		 << " 3) double pounds format 4) unkown \n";
	int mode;
	cin >> mode;
	for (int i = 0; i < 6; i++) {
		ston[i].setState(mode);
	}
	temp.setState(mode);
	
	for (int i = 0; i < 6; i++) {
		cout << "#" << (i + 1) << ": " << ston[i] << endl;
	}

	cout << "more than 11 stone(154 pounds) for element: " << endl;
	Stonewt max = ston[0], min = ston[0];
	for (int i = 0; i < 6; i++){
		if (ston[i] < min)
			min = ston[i];
		if (ston[i] > max)
			max = ston[i];
		if (ston[i] >= temp)
			cout << ston[i];

	}
	cout << "\nmaximum element:" << max;
	cout << ", minimum element:" << min << endl;

	return 0;
}

/**
输出结果:
	enter last third element value:
	 #3 element value:153
	 #4 element value:154
	 #5 element value:256
	Set array stone display format:
	 1) stone format         2) integer pounds format
	 3) double pounds format 4) unkown
	2
	#1: 10 pounds
	#2: 11 pounds
	#3: 12 pounds
	#4: 153 pounds
	#5: 154 pounds
	#6: 256 pounds
	more than 11 stone(154 pounds) for element:
	154 pounds 256 pounds
	maximum element:256 pounds , minimum element:10 pounds
*/

// complex0.h -- class Complex0 declaration
#ifndef __COMPLEX0_H__
#define __COMPLEX0_H__
#include <iostream>

class complex
{
private:
	double real;
	double imaginary;
public:
	complex();  // 构造函数
	complex(double re, double im);
	~complex(); // 析构函数

	// overload operator
	complex operator+(const complex & c) const;
	complex operator-(const complex & c) const;
	complex operator*(const complex & c) const;
	complex operator~() const;

	friend complex operator*(double x, const complex & c);
	friend std::ostream & operator<<(std::ostream & os, const complex & c);
	friend std::istream & operator>>(std::istream & is, complex & c);
};

#endif /* __COMPLEX0_H__ */

// complex0.cpp -- class complex function definition

#include "complex0.h"

// constructor function
complex::complex()
{
	real = imaginary = 0.0;
}

complex::complex(double re, double im)
{
	real = re;
	imaginary = im;
}

complex::~complex()
{
}

complex complex::operator+(const complex & c) const
{
	return complex(real + c.real, imaginary + c.imaginary);
}

complex complex::operator-(const complex & c) const
{
	return complex(real - c.real, imaginary - c.imaginary);
}

complex complex::operator*(const complex & c) const
{
	return complex(real * c.real - imaginary * c.imaginary, 
		         real * c.imaginary + imaginary * c.real);
}

complex complex::operator~() const
{
	return complex(real, -imaginary);
}

// friend function
complex operator*(double x, const complex & c)
{
	return complex(x * c.real, x * c.imaginary);
}

std::ostream & operator<<(std::ostream & os, const complex & c)
{
	os << "(" << c.real << ", " << c.imaginary << "i) ";
	return os;
}

std::istream & operator>>(std::istream & is, complex & c)
{
	using std::cout;

	cout << "real: ";
	if (!(is >> c.real))
		return is;
	cout << "imaginary: ";
	is >> c.imaginary;

	return is;
}

/***********************************
	2017年11月15日10:40:18
	Athor:xiyuan255
	Course:C++
	Contain:usecomplex0.cpp
			 complex0.h
		     complex0.cpp
	Reference: C++ Primer plus
	说明:C++ Primer plus第十一章的第七题练习题
		 【 P423 】
	注:运算符的重载函数,当是局部变量作为返回值,不要用引用返回;
	如:complex operator+(const complex & c) const 
	函数的返回值不要写成complex & 类型,因为它在本程序返回的是
	complex(real + c.real, imaginary + c.imaginary)对象,如果是引用
	类型的返回值,则是返回complex(real + c.real, imaginary + c.imaginary)
	对象的别名,而这个对象在搞函数执行完毕后会被释放,则在主函数中如果访问
	了该对象别名就会出现访问已经被释放的内存空间。
	如果是非引用型返回值,则不会有这个问题,它会通过return将该对象复制到该
	函数的返回类型对应的临时空间中,然后在主函数把该临时对象复制该需要的对象。
*************************************/
// usecomplex0.cpp -- use class complex0 of function
// compile with complex0.cpp
#include <iostream>
using namespace std;
#include "complex0.h"  // to avoid confusion with complex.h

int main()
{
	complex a(3.0, 4.0);  // initialie to (3, 4i)
	complex c;
	cout << "Enter a complex number (q to quit):\n";
	while (cin >> c) {
		cout << "c is " << c << endl;
		cout << "complex conjugate is " << ~c << '\n';
		cout << "a is " << a << '\n';
		cout << "a + c is " << a + c << '\n';
		cout << "a - c is " << a - c << '\n';
		cout << "a * c is " << a * c << '\n';
		cout << "2 * c is " << 2 * c << '\n';
		cout << "Enter a complex number (q to quit):\n";
	}
	cout << "Done!\n";

	return 0;
}

/**
输出结果:
	Enter a complex number (q to quit):
	real: 10
	imaginary: 12
	c is (10, 12i)
	complex conjugate is (10, -12i)
	a is (3, 4i)
	a + c is (13, 16i)
	a - c is (-7, -8i)
	a * c is (-18, 76i)
	2 * c is (20, 24i)
	Enter a complex number (q to quit):
	real: q
	Done!

*/

 
// vector2.h -- Vector class with <<, mode state
#ifndef __VECTOR2_H__
#define __VECTOR2_H__

#include <iostream>

namespace VECTOR2
{
	class Vector
	{
	public:
		enum Mode { RECT, POL };
	// RECT for rectangular, POL for Polar modes
	private:
		double x;    // horizontal value
		double y;    // vertical value
		Mode mode;   // RECT or POL
	public:
		Vector();
		Vector(double n1, double n2, Mode form = RECT);
		void reset(double n1, double n2, Mode form = RECT);
		~Vector();
		double xVal() const { return x; }      // report x value
		double yVal() const { return y; }      // report y value
		double magVal() const { return sqrt(x * x + y * y); }  // report magnitude
		double angVal() const { 
			double ang;
			if (0.0 == x && 0.0 == y)
				ang = 0.0;
			else
				ang = atan2(y, x); 
			return ang; 
		}  // report angle
		void polar_mode();                     // set mode to POL
		void rect_mode();                      // set mode to RECT
	// operator overloading // 类的成员函数对符号的重载
		Vector operator+(const Vector & b) const;
		Vector operator-(const Vector & b) const;
		Vector operator-() const;
		Vector operator*(double n) const;
	// friends // 类的非成员函数(友元函数)对符号的重载
		friend Vector operator*(double n, const Vector & a);
		friend std::ostream & 
			operator<<(std::ostream & os, const Vector & v);
	};

}  // end namespace VECTOR2 

#endif /* __VECTOR2_H__ */

// vector2.cpp -- methods for the Vector class
#include <cmath>
#include "vector2.h"  // include <iostream>

using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;

namespace VECTOR2
{
	// compute degrees in one radian
	const double Rad_to_deg = 45.0 / atan(1.0);
	// shoule be about 57.2957795130823

	// public methods
	Vector::Vector()      // default constructor
	{
		x = y = 0.0;
		mode = RECT;
	}

	// construct vector from rectangular coordinates if form is r
	// (the default) or else from polar coordinates if form is p
	Vector::Vector(double n1, double n2, Mode form)
	{
		mode = form;
		if (RECT == form) {
			x = n1; 
			y = n2;
		} else if (POL == form) {
			x = n1 * cos(n2);
			y = n1 * sin(n2);
		} else {
			cout << "Incorrect 3rd argument to Vector() -- ";
			cout << "vector set to 0\n";
			x = y = 0.0;
			mode = RECT;
		}
	}

	// reset vector from rectangular coordinates if form is 
	// RECT (the default) or else from polar coordinates if
	// form is POL
	void Vector::reset(double n1, double n2, Mode form)
	{	
		mode = form;
		if (RECT == form) {
			x = n1;
			y = n2;
		} else if (POL == form) {
			x = n1 * cos(n2);
			y = n1 * sin(n2);
		} else {
			cout << "Incorrect 3rd argument to Vector() -- ";
			cout << "vector set to 0\n";
			x = y = 0.0;
			mode = RECT;
		}
	
	}

	Vector::~Vector()   // destructor
	{
	}

	void Vector::polar_mode()   // set to polar mode
	{
		mode = POL;
	}

	void Vector::rect_mode()   // set to rectangular mode
	{
		mode = RECT;
	}

	// operator overloading
	// add to Vectors
	Vector Vector::operator+(const Vector & b) const
	{
		// 调用构造函数会自动生成一个临时对象来存放这些值
		return Vector(x + b.x, y + b.y); 
		// 等价 {
			/*		Vector sum;
					sum.x = x + b.x;
					sum.y = y + b.y;
					sum.set_ang(sum.x, sum.y);
					sum.set_ang(sum.x, sum.y);
					return sum;    // version duplicates needlessly
					*/
               //}
	} 
    

	// subtract Vector b from a
	Vector Vector::operator-(const Vector & b) const
	{
		return Vector(x - b.x, y - b.y);
	}

	// reverse sign of Vector
	Vector Vector::operator-() const
	{
		return Vector(-x, -y);
	}

	// multiply vector by n
	Vector Vector::operator*(double n) const
	{
		return Vector(n * x, n * y);
	}

	// friend methods
	// multiply n by Vector a
	Vector operator*(double n, const Vector & a)
	{
		return a * n;
	}

	// display rectangular coordinates if mode is RECT
	// else display polar coordinates if mode is POL
	std::ostream & operator<<(std::ostream & os, const Vector & v)
	{ // 因为该函数是友元函数,不属于类成员,所以使用RECT和POL
	  // 需要加Vector::来访问类的枚举成员
		if (v.mode == Vector::RECT)
			os << "(x, y) = (" << v.x << ", " << v.y << ")";
		else if (v.mode == Vector::POL) {
			os << "(m, a) = (" << v.magVal() << ", " 
			   << v.angVal() * Rad_to_deg << ")";
		} else
			os << "Vector object mode is invalid";

		return os;
	}

}  // end namespace VECTOR2

/***********************************
	2017年11月13日16:59:23
	Athor:xiyuan255
	Course:C++
	Contain:randwalk2.cpp
			 vactor2.h
		     vactor2.cpp
	Reference: C++ Primer plus
	说明:C++ Primer plus第十一章的第二题练习题
		 【 P423 】
*************************************/
// randwalk2.cpp -- using the Vector class
// compile with the vector2.cpp file
#include <iostream>
#include <cstdlib>    // rand(), srand() prototypes
#include <ctime>      // time() prototype
#include "vector2.h"

int main()
{
	using namespace std;
	using VECTOR2::Vector;
	srand(time(0));     // seed random-number generator
	double direction;
	Vector step;
	Vector result(0.0, 0.0);
	unsigned long steps = 0;
	double target;
	double dstep;
	cout << "Enter target distance (q to quit): ";
	while (cin >> target) {
		cout << "Enter step length: ";
		if (!(cin >> dstep))
			break;
		while (result.magVal() < target) {
			direction = rand() % 360;
			step.reset(dstep, direction, Vector::POL);
			result = result + step;
			steps++;
		}
		cout << "After " << steps << " steps, the subject "
			"has the following location:\n";
		cout << result << endl;
		result.polar_mode();
		cout << " or\n" << result << endl;
		cout << "Average outward distance per step = "
			 << result.angVal() / steps << endl;
		steps = 0;
		result.reset(0.0, 0.0);
		cout << "Enter target distance (q to quit): ";
	}
	cout << "Bye!\n";
	/* 当cin >> xxx 返回错误时,会堵塞输入序列,则需要
	 * 使用cin.clear() 重新打开输入序列 */
	cin.clear();
	while (cin.get() != '\n')
		continue;

	return 0;
}

/**
输出结果:
	Enter target distance (q to quit): 50
	Enter step length: 2
	After 857 steps, the subject has the following location:
	(x, y) = (-50.5311, 3.03791)
	 or
	(m, a) = (50.6223, 176.56)
	Average outward distance per step = 0.00359574
	Enter target distance (q to quit): 50
	Enter step length: 2
	After 370 steps, the subject has the following location:
	(x, y) = (38.7306, -33.2692)
	 or
	(m, a) = (51.0578, -40.6622)
	Average outward distance per step = -0.00191808
	Enter target distance (q to quit): 50
	Enter step length: 1
	After 7595 steps, the subject has the following location:
	(x, y) = (8.80658, 49.2528)
	 or
	(m, a) = (50.0339, 79.8624)
	Average outward distance per step = 0.000183524
	Enter target distance (q to quit): q
	Bye!
*/

// vector3.h -- Vector class with <<, mode state
#ifndef __VECTOR3_H__
#define __VECTOR3_H__

#include <iostream>

namespace VECTOR3
{
	class Vector
	{
	public:
		enum Mode { RECT, POL };
	// RECT for rectangular, POL for Polar modes
	private:
		double x;    // horizontal value
		double y;    // vertical value
		double mag;  // length of vector
		double ang;  // direction of vector in degrees
		Mode mode;   // RECT or POL
	// private methods for setting values
		void set_mag();
		void set_ang();
		void set_x();
		void set_y();
	public:
		Vector();
		Vector(double n1, double n2, Mode form = RECT);
		void reset(double n1, double n2, Mode form = RECT);
		~Vector();
		double xVal() const { return x; }      // report x value
		double yVal() const { return y; }      // report y value
		double magVal() const { return mag; }  // report magnitude
		double angVal() const { return ang; }  // report angle
		void polar_mode();                     // set mode to POL
		void rect_mode();                      // set mode to RECT
	// operator overloading // 类的成员函数对符号的重载
		Vector operator+(const Vector & b) const;
		Vector operator-(const Vector & b) const;
		Vector operator-() const;
		Vector operator*(double n) const;
	// friends // 类的非成员函数(友元函数)对符号的重载
		friend Vector operator*(double n, const Vector & a);
		friend std::ostream & 
			operator<<(std::ostream & os, const Vector & v);
	};

}  // end namespace VECTOR3 

#endif /* __VECTOR3_H__ */

// vector3.cpp -- methods for the Vector class
#include <cmath>
#include "vector3.h"  // include <iostream>

using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;

namespace VECTOR3
{
	// compute degrees in one radian
	const double Rad_to_deg = 45.0 / atan(1.0);
	// shoule be about 57.2957795130823

	// private methods
	// calculates magnitude from x and y
	void Vector::set_mag()
	{
		mag = sqrt(x * x + y * y);
	}
	void Vector::set_ang()
	{
		if (0.0 == x && 0.0 == y)
			ang = 0.0;
		else
			ang = atan2(y, x);
	}

	// set x from polar coordinate
	void Vector::set_x()
	{
		x = mag * cos(ang);
	}

	// set y from polar coordinate
	void Vector::set_y()
	{
		y = mag * sin(ang);
	}

	// public methods
	Vector::Vector()      // default constructor
	{
		x = y = mag = ang = 0.0;
		mode = RECT;
	}

	// construct vector from rectangular coordinates if form is r
	// (the default) or else from polar coordinates if form is p
	Vector::Vector(double n1, double n2, Mode form)
	{
		mode = form;
		if (RECT == form) {
			x = n1; 
			y = n2;
			set_mag();
			set_ang();
		} else if (POL == form) {
			mag = n1;
			ang = n2;
			set_x();
			set_y();
		} else {
			cout << "Incorrect 3rd argument to Vector() -- ";
			cout << "vector set to 0\n";
			x = y = mag = ang = 0.0;
			mode = RECT;
		}
	}

	// reset vector from rectangular coordinates if form is 
	// RECT (the default) or else from polar coordinates if
	// form is POL
	void Vector::reset(double n1, double n2, Mode form)
	{	
		mode = form;
		if (RECT == form) {
			x = n1;
			y = n2;
			set_mag();
			set_ang();
		} else if (POL == form) {
			mag = n1;
			ang = n2;
			set_x();
			set_y();
		} else {
			cout << "Incorrect 3rd argument to Vector() -- ";
			cout << "vector set to 0\n";
			x = y = mag = ang = 0.0;
			mode = RECT;
		}
	
	}

	Vector::~Vector()   // destructor
	{
	}

	void Vector::polar_mode()   // set to polar mode
	{
		mode = POL;
	}

	void Vector::rect_mode()   // set to rectangular mode
	{
		mode = RECT;
	}

	// operator overloading
	// add to Vectors
	Vector Vector::operator+(const Vector & b) const
	{
		// 调用构造函数会自动生成一个临时对象来存放这些值
		return Vector(x + b.x, y + b.y); 
		// 等价 {
			/*		Vector sum;
					sum.x = x + b.x;
					sum.y = y + b.y;
					sum.set_ang(sum.x, sum.y);
					sum.set_ang(sum.x, sum.y);
					return sum;    // version duplicates needlessly
					*/
               //}
	} 
    

	// subtract Vector b from a
	Vector Vector::operator-(const Vector & b) const
	{
		return Vector(x - b.x, y - b.y);
	}

	// reverse sign of Vector
	Vector Vector::operator-() const
	{
		return Vector(-x, -y);
	}

	// multiply vector by n
	Vector Vector::operator*(double n) const
	{
		return Vector(n * x, n * y);
	}

	// friend methods
	// multiply n by Vector a
	Vector operator*(double n, const Vector & a)
	{
		return a * n;
	}

	// display rectangular coordinates if mode is RECT
	// else display polar coordinates if mode is POL
	std::ostream & operator<<(std::ostream & os, const Vector & v)
	{ // 因为该函数是友元函数,不属于类成员,所以使用RECT和POL
	  // 需要加Vector::来访问类的枚举成员
		if (v.mode == Vector::RECT)
			os << "(x, y) = (" << v.x << ", " << v.y << ")";
		else if (v.mode == Vector::POL) {
			os << "(m, a) = (" << v.mag << ", " 
			   << v.ang * Rad_to_deg << ")";
		} else
			os << "Vector object mode is invalid";

		return os;
	}

}  // end namespace VECTOR3 

/***********************************
	2017年11月14日09:10:25
	Athor:xiyuan255
	Course:C++
	Contain:randwalk3.cpp
			 vactor3.h
		     vactor3.cpp
	Reference: C++ Primer plus
	说明:C++ Primer plus第十一章的第三题练习题
		 【 P423 】
*************************************/
// randwalk3.cpp -- using the Vector class
// compile with the vector3.cpp file
#include <iostream>
#include <cstdlib>    // rand(), srand() prototypes
#include <ctime>      // time() prototype
#include "vector3.h"

int main()
{
	using namespace std;
	using VECTOR3::Vector;
	srand(time(0));     // seed random-number generator

	int N;
	double direction;
	Vector step;
	Vector result(0.0, 0.0);
	unsigned long steps = 0;
	double target;
	double dstep;
	unsigned long max_steps = 0x0000000000000000;
	unsigned long min_steps = 0xFFFFFFFFFFFFFFFF;
	unsigned long sum_steps = 0;
	
	cout << "Enter target distance (q to quit): ";
	while (cin >> target) {
		cout << "Enter step length: ";
		if (!(cin >> dstep))
			break;
		cout << "Enter N number value: ";
		if (!(cin >> N))
			break;
		int n = 0;
		while (n++ < N) {
			while (result.magVal() < target) {
				direction = rand() % 360;
				step.reset(dstep, direction, Vector::POL);
				result = result + step;
				steps++;
			}
			if (max_steps < steps)
				max_steps = steps;
			if (min_steps > steps)
				min_steps = steps;
			sum_steps += steps;

			steps = 0;
			result.reset(0.0, 0.0);
		}
		cout <<	N << " times sample steps of "<< "Maximum: " << max_steps;
		cout << ", Minimum: " << min_steps;
		cout << ", Average: " << (double)sum_steps / N << endl;
		cout << "Enter target distance (q to quit): ";
	}
	
	cout << "Bye!\n";
	/* 当cin >> xxx 返回错误时,会堵塞输入序列,则需要
	 * 使用cin.clear() 重新打开输入序列 */
	cin.clear();
	while (cin.get() != '\n')
		continue;

	return 0;
}

/**
输出结果:
	Enter target distance (q to quit): 100
	Enter step length: 2
	Enter N number value: 3
	3 times sample steps of Maximum: 11656, Minimum: 1169, Average: 5158.67
	Enter target distance (q to quit): q
	Bye!
*/

// mytime4.h -- Time class before operator overloading
#ifndef __MYTIME4_H__
#define __MYTIME4_H__

#include <iostream>

class Time
{
private:
	int hours;
	int minutes;
public:
	Time();
	Time(int h, int m = 0);
	void addMin(int m);
	void addHr(int h);
	void reset(int h = 0, int m = 0);
	friend Time operator+(const Time & t1, const Time & t2);
	friend Time operator-(const Time & t1, const Time & t2);
	friend Time operator*(const Time & t, double m);
	friend Time operator*(double m, const Time & t) { // 有元函数
		return t * m;  // inline definition 内联定义 (use t.operator*(m))
	}
	friend std::ostream & operator<<(std::ostream & os, const Time & t);
};

#endif /* __MYTIME4_H__ */

// mytime4.cpp -- implementing Time methods
#include <iostream>
#include "mytime4.h"

Time::Time()
{
	hours = minutes = 0;
}

Time::Time(int h, int m)
{
	hours = h;
	minutes = m;
}

void Time::addMin(int m)
{
	minutes += m;
	hours += minutes / 60;
	minutes %= 60;
}

void Time::addHr(int h)
{
	hours += h;
}

void Time::reset(int h, int m)
{
	hours = h;
	minutes = m;
}

Time operator+(const Time & t1, const Time & t2)
{
	Time sum;
	sum.minutes = t1.minutes + t2.minutes;
	sum.hours = t1.hours + t2.hours + sum.minutes / 60;
	sum.minutes %= 60;

	return sum;
}

Time operator-(const Time & t1, const Time & t2)
{
	Time diff;
	int tot1, tot2;
	tot1 = t2.minutes + 60 * t2.hours;
	tot2 = t1.minutes + 60 * t1.hours;
	diff.minutes = (tot2 - tot1) % 60;
	diff.hours = (tot2 - tot1) / 60;

	return diff;
}

Time operator*(const Time & t, double mult)
{
	Time result;
	long totalminutes = t.hours * mult * 60 + t.minutes * mult;
	result.minutes = totalminutes % 60;
	result.hours = totalminutes / 60;

	return result;
}

std::ostream & operator<<(std::ostream & os, const Time & t)
{
	os << t.hours << " hours, " << t.minutes << " minutes";
	return os;
}

/***********************************
	2017年11月14日09:26:15
	Athor:xiyuan255
	Course:C++
	Contain:usetime4.cpp
			 mytime4.h
		     mytime4.cpp
	Reference: C++ Primer plus
	说明:C++ Primer plus第十一章的第四题练习题
		 【 P423 】
*************************************/
// usetime4.cpp -- using the fourth draft of the Time class
// compile usetime4.cpp and mytime4.cpp together
#include <iostream>
#include "mytime4.h"

int main()
{
	using std::cout;
	using std::endl;
	Time aida(3, 35);
	Time tosca = Time(2, 48);
	Time temp;

	cout << "Aida and Tosca: \n";
	// std::ostream & operator<<(cout, aida)
	cout << aida << "; " << tosca << endl; 
	temp = aida + tosca;
	cout << "Aida + Tosca: " << temp << endl;
	temp = aida * 1.17; // use aida.operator*(1.17) 类的重载函数调用
	cout << "aida * 1.17: " << temp << endl;

	// use operator*(10.0, tosca) 有元函数的调用
	cout << "10.0 * Tosca: " << 10.0 * tosca << endl; 

	return 0;
}

/**
输出结果:
	Aida and Tosca:
	3 hours, 35 minutes; 2 hours, 48 minutes
	Aida + Tosca: 6 hours, 23 minutes
	aida * 1.17: 4 hours, 11 minutes
	10.0 * Tosca: 28 hours, 0 minutes
*/

// stonewt2.h -- definition for the Stonewt class
#ifndef __STONEWT2_H__
#define __STONEWT2_H__
#include <iostream>

class Stonewt
{
private:
	enum Mode_e { STON_FORMAT, INT_POUN_FORMAT, DOU_POUN_FORMAT };
	/* 一英石 = 14磅 */
	enum { Lbs_per_stn = 14 };    // pounds per stone
	// or static const int Lbs_per_stn = 14;
	Mode_e state;
	int stone;                    // whole stones (英石)
	double pds_left;              // fractional pounds (不够1英石的磅重量)
	double pounds;                // entire weight in pounds (磅)
public:
	Stonewt(double lbs);          // constructor for double pounds
	Stonewt(int stn, double lbs); // constructor for stone, lbs
	Stonewt();  // 默认的构造函数
	~Stonewt(); // 析构函数

	void setState();
	void resetStonewt(double lbs);
	void resetStonewt(int stn, double lbs);

	// overload operator
	Stonewt operator+(const Stonewt & swt) const;
	Stonewt operator-(const Stonewt & swt) const;
	Stonewt operator*(double n) const;
	Stonewt operator/(const Stonewt & swt) const;

	friend Stonewt operator*(double n, const Stonewt & swt) {
		return swt * n;
	}
	friend std::ostream & operator<<(std::ostream & os, const Stonewt & swt);

	// void show_lbs() const;        // show weight in pounds format
	// void show_stn() const;        // show weight in stone format
};

#endif /* __STONEWT2_H__ */

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值