C++ Primer Plus(第五版)第11章编程题答案
1.修改程序清单11.15,使之将一系列连续的随机漫步者位置写入到文件中。对于每个位置,用步号进行标示。另外,让该程序将初始条件(目标距离和步长)以及结果小结写入到该文件中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
#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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
// 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
#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是用户输入的整数),而不是报告每次测试的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
#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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
#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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
// 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
// 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
#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
1 条留言 访客:0 条 博主:0 条 引用: 1 条
来自外部的引用: 1 条