C++ Primer Plus(第五版)第11章编程题答案

1.修改程序清单11.15,使之将一系列连续的随机漫步者位置写入到文件中。对于每个位置,用步号进行标示。另外,让该程序将初始条件(目标距离和步长)以及结果小结写入到该文件中。

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include "vector.h"
using namespace std;
using VECTOR::Vector;
int main() {
	ofstream outFile;
	outFile.open("exercise1.txt");
	srand(time(0));
	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;
		outFile << "Target Distance: " << target << ", Step Size: " << dstep << endl;
		while (result.magval() < target)
		{
			direction = rand() % 360;
			step.set(dstep, direction, 'p');
			result = result + step;
			outFile << steps << ": (x,y) = " << "(" << step.xval() << ", " << step.yval() << ")" << endl;
			steps++;
		}
		outFile << "After " << steps << " steps, the subject "
			"has the following location:\n";
		outFile << "(x,y)=" << result << endl;
		result.polar_mode();
		outFile << " or\n" << result << endl;
		outFile << "Average outward distance per step = "
			<< result.magval() / steps << endl;
		outFile << "===================================================="<<endl;
                outFile << "COPYRIGHT 2018 WWW.YUSHUAI.XYZ" << endl;
		steps = 0;
		result.set(0.0, 0.0);
		cout << "Enter target distance (q to quit): ";
	}
	outFile.close();
	cout << "Bye~" << endl;
	system("pause");
	return 0;
}

2.对Vector类的头文件(程序清单11.13)和实现文件(程序清单11.14)进行修改,使其不再存储矢量的长度和角度,而是在magval()和angval()被调用时计算它们。
应保留公有接口不变(公有方法及其参数不变),但对私有部分(包括一些私有方法)和方法实现进行修改。然后,使用程序清单11.15对修改后的版本进行测试,结果应该与以前相同,因为Vector类的公有接口与原来相同。

vector.h

// vect.h -- Vector class with <<, mode state
#ifndef VECTOR_H_
#define VECTOR_H_
#include <iostream>
namespace VECTOR
{
	class Vector
	{
	private:
		double x;          // horizontal value
		double y;          // vertical value
		char mode;         // 'r' = rectangular, 'p' = polar
						   // private methods for setting values
		void set_x(double mag, double ang);
		void set_y(double mag, double ang);
	public:
		Vector();
		Vector(double n1, double n2, char form = 'r');
		void set(double n1, double n2, char form = 'r');
		~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// report angle
		{
			if (x == 0.0 && y == 0.0)
				return 0.0;
			else
				return atan2(y, x);
		}
		
		void polar_mode();                    // set mode to 'p'
		void rect_mode();                     // set mode to 'r'
											  // 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 VECTOR
#endif
#pragma once

vector.cpp

#include <cmath>
#include "vector.h"   // includes <iostream>
using std::sqrt;
using std::sin;
using std::cos;
using std::atan2;
using std::cout;

namespace VECTOR
{

	const double Rad_to_deg = 57.2957795130823;

	// private methods
	// calculates magnitude from x and y
	// set x from polar coordinate
	void Vector::set_x(double mag, double ang)
	{
		x = mag * cos(ang);
	}

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

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

	// 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, char form)
	{
		mode = form;
		if (form == 'r')
		{
			x = n1;
			y = n2;
		}
		else if (form == 'p')
		{
			set_x(n1, n2);
			set_y(n1, n2);
		}
		else
		{
			cout << "Incorrect 3rd argument to Vector() -- ";
			cout << "vector set to 0\n";
			x = y = 0.0;
			mode = 'r';
		}
	}

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

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

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

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

	// operator overloading
	// add two Vectors
	Vector Vector::operator+(const Vector & b) const
	{
		return Vector(x + b.x, y + b.y);
	}

	// 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);
	}

	// multiple 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 r,
	// else display polar coordinates if mode is p
	std::ostream & operator<<(std::ostream & os, const Vector & v)
	{
		if (v.mode == 'r')
			os << "(x,y) = (" << v.x << ", " << v.y << ")";
		else if (v.mode == 'p')
		{
			os << "(m,a) = (" << v.magval() << ", "
				<< v.angval() * Rad_to_deg << ")";
		}
		else
			os << "Vector object mode is invalid";
		return os;
	}

}  // end namespace VECTOR

3.修改程序清单11.15,使之报告N次测试中的最高、最低和平均步数(其中N是用户输入的整数),而不是报告每次测试的结果。

#include<iostream>
#include<cstdlib>
#include<ctime>
#include "vector.h"
using namespace std;
using VECTOR::Vector;
int main() {
	srand(time(0));
	double direction;
	Vector step;
	Vector result(0.0, 0.0);
	unsigned long steps = 0;
	double target;
	double dstep;
	unsigned long max = 0;
	unsigned long min = 999;
	double avg = 0;
	int N;
	cout << "请输入测试的次数:N=";
	cin >> N;
	cout << "第一次:" << endl;
	int i;
	for (i = 0; i < N; i++)
	{
		cout << "Enter target distance(ONLY ENTER NUMBER): ";
		cin >> target;
		cout << "Enter step length: ";
		if (!(cin >> dstep))
			break;
		while (result.magval() < target)
		{
			direction = rand() % 360;
			step.set(dstep, direction, 'p');
			result = result + step;
			steps++;
		}
		if (max < steps)
			max = steps;
		if (min > steps)
			min = steps;
		avg += steps;
		result.polar_mode();
		steps = 0;
		result.set(0.0, 0.0);
	}
	avg /= N;
	cout << "max: " << max << endl << "min: " << min << endl << "average: " << avg << endl;
	cout << "Bye~";
	system("pause");
	return 0;
}

4.重新编写最后的Time类示例(程序清单11.10、程序清单11.11和程序清单11.12),使用友元函数来实现所有的重载运算符。

mytime3.h

#pragma once
#ifndef MYTIME3_H_
#define MYTIME3_H_
#include<iostream>
using namespace std;
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 n);
	friend Time operator*(double m, const Time & t) { return t*m; }
	friend ostream & operator<<(ostream & os, const Time & t);
};
#endif // !MYTIME_H_

mytime3.cpp

#include<iostream>
#include "mytime3.h"
using namespace std;
Time::Time() {
	hours = minutes = 0;

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

}
void Time::AddMin(int m) {
	minutes += m;
	hours += minutes / 0;
	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 n) {
	Time result;
	long totalminutes = t.hours*n * 60 + t.minutes*n;
	result.hours = totalminutes / 60;
	result.minutes = totalminutes % 60;
	return result;
}

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

usetime3.cpp

#include<iostream>
#include"mytime3.h"
using namespace std;
int main() {
	Time aida(3, 35);
	Time tosca(2, 48);
	Time temp;
	cout << "Aida and Tosca:\n";
	cout << aida << ";" << tosca << endl;
	temp = aida + tosca;
	temp = aida*1.17;
	cout << "Aida*1.17: " << temp << endl;
	cout << "10*Tosca: " << 10 * tosca << endl;

	system("pause");
	return 0;
}

5.重新编写Stonewt类(程序清单11.16和程序清单11.17),使它有一个状态成员,由该成员控制对象应转换为英石格式、整数磅格式还是浮点磅格式。重载<<运算符,使用它来替换show_stn()和show_lbs()方法。重载加法、减法和乘法运算符,以便可以对Stonewt值进行加、减、乘运算。编写一个使用所有类方法和友元的小程序,来测试这个类。

stonewt.h

// stonewt.h -- definition for the Stonewt class
#ifndef STONEWT_H_
#define STONEWT_H_
class Stonewt
{
private:
    enum {Lbs_per_stn = 14};      // pounds per stone
    int stone;                    // whole stones
    double pds_left;              // fractional pounds
    double pounds;                // entire weight in pounds
public:
    Stonewt(double lbs);          // constructor for double pounds
    Stonewt(int stn, double lbs); // constructor for stone, lbs
    Stonewt();                    // default constructor
    ~Stonewt();
    void show_lbs() const;        // show weight in pounds format
    void show_stn() const;        // show weight in stone format
};
#endif

stonewt.cpp

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

// construct 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;
}

// construct 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
{
}

// show weight in stones
void Stonewt::show_stn() const
{
    cout << stone << " stone, " << pds_left << " pounds\n";
}

// show weight in pounds
void Stonewt::show_lbs() const
{
    cout << pounds << " pounds\n";
}

stone.cpp

// stone.cpp -- user-defined conversions
// compile with stonewt.cpp
#include <iostream>
using std::cout;
#include "stonewt.h"
void display(const Stonewt & st, int n);
int main()
{
    Stonewt pavarotti = 260; // uses constructor to initialize
    Stonewt wolfe(285.7);    // same as Stonewt wolfe = 285.7;
    Stonewt taft(21, 8);

    cout << "The tenor weighed ";
    pavarotti.show_stn();
    cout << "The detective weighed ";
    wolfe.show_stn();
    cout << "The President weighed ";
    taft.show_lbs();
    pavarotti = 265.8;       // uses constructor for conversion
    taft = 325;      
    cout << "After dinner, the tenor weighed ";
    pavarotti.show_stn();
    cout << "After dinner, the President weighed ";
    taft.show_lbs();
    display(taft, 2);
    cout << "The wrestler weighed even more.\n";
    display(422, 2);
    cout << "No stone left unearned\n";
	system("pause");
    return 0;
}

void display(const Stonewt & st, int n)
{
    for (int i = 0; i < n; i++)
    {
        cout << "Wow! ";
        st.show_stn();
    }
}

7.复数有两个部分组成:实数部分和虚数部分。复数的一种书写方式是:(3.0,4.0)。请定义一个复数类,以便下面的程序可以使用它来获得正确的结果。
(……代码省略……)
注意。必须重载运算符<<和>>。标准C++使用头文件complex提供了比这个示例更广泛的复数支持,因此应将自定义的头文件命名为complex0.h,以免发生冲突。应尽可能使用const。
请注意,经过重载后,cin>>c将提示用户输入实数和虚数部分。

complex0.h

#pragma once
#include<iostream>
#ifndef COM0_H_
using namespace std;
class complex {
	double a;
	double b;
public:
	complex();
	complex(double x, double y);
	~complex();
	complex operator+(const complex & t) const;
	complex operator-(const complex & t) const;
	friend complex operator*(const complex & t,double n);//Êý³Ë
	friend complex operator*(const complex & t1, const complex & t2);
	friend complex operator~(const complex & t);
	friend ostream & operator<<(ostream & os, const complex & c);
	friend istream & operator >> (istream &in, complex &c);


};
#endif // !COM0_H_

complex0.cpp

#include "complex0.h"
#include<iostream>
complex::complex() {
	a = 0;
	b = 0;
}
complex::complex(double x, double y) {
	a = x;
	b = y;

}
complex::~complex() {}
complex complex::operator+(const complex & t) const
{
	
	complex sum;
	sum.a = a + t.a;
	sum.b = b + t.b;
	return sum;

}
complex complex::operator-(const complex & t) const
{
	complex diff;
	diff.a = a - t.a;
	diff.b = b - t.b;
	return diff;

}
complex operator*(const complex & t, double n)  //Êý³Ë
{
	return complex((t.a)*n, (t.b)*n);

}
	
complex operator*(const complex & t1, const complex & t2)
{
	return complex((t1.a*t2.a - t1.b*t2.b), (t1.a*t2.b + t1.b*t2.a));

}
complex operator~(const complex & t)
{
	return complex(t.a, (-1.0)*t.b);

}
ostream & operator<<(ostream & os, const complex & c)
{
	os << "(" << c.a << "," << c.b << "!" << ")";
	return os;

}
istream & operator >> (istream &in, complex &c)
{
	in >> c.a >> c.b;
	return in;
}

备注:

操作系统:Windows 10 x64(1803)

编译器:Microsoft Visual Studio 2015

 

One thought on “C++ Primer Plus(第五版)第11章编程题答案

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注