1. 修改程序清单11.15,使之将一系列连续的随机漫步者位置写入到文件中。对于每个位置,用步号进行标示。另外,让该程序将初始条件(目标距离和步长)以及结果小结写入到该文件中。
// 类描述中包含两种形式,设计这个类时,将使得用户修改了矢量的一种表示后,对象将自动更新另一种表示。
// 使对象拥有这种智能,使C++类的一个优点
// vector.h
#ifndef VECTOR_H_
#define VECTOR_H_
#include <iostream>
namespace VECTOR {
class Vector {
public:
// RECT表示直角坐标系,POL表示极坐标系
// 注意:状态成员,标识符POL的作用域为类
enum Mode{RECT, POL};
private:
double x;
double y;
double mag;
double ang;
Mode mode;
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; } // 获取x值
double yval() const { return y; } // 获取y值
double magval() const { return mag; }
double angval() const { return ang; }
void polar_mode(); // 将mode设置为POL
void rect_mode(); // 将mode设置为RECT
// 运算符重载
Vector operator+(const Vector& b) const;
Vector operator-(const Vector& b) const;
Vector operator-() const;
Vector operator*(double n) const;
// 友元函数
friend Vector operator*(double n, const Vector& a);
friend std::ostream& operator<<(std::ostream& os, const Vector& v);
};
}
#endif // !VECTOR_H_
// vector.cpp
#include <cmath>
#include "vector.h"
using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;
namespace VECTOR {
const double Rad_to_deg = 45.0 / atan(1.0); // 该值大约为57.2957795130823
// private methods
void Vector::set_mag() {
mag = sqrt(x * x + y * y);
}
void Vector::set_ang() {
if (x == 0 && y == 0) ang = 0.0;
else ang = atan2(y, x);
}
void Vector::set_x() {
x = mag * cos(ang);
}
void Vector::set_y() {
y = mag * sin(ang);
}
// public methods
Vector::Vector() {
x = y = mag = ang = 0.0;
mode = RECT;
}
Vector::Vector(double n1, double n2, Mode form) {
mode = form;
if (form == RECT) {
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (form == POL) {
mag = n1;
ang = n2 / Rad_to_deg;
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;
}
}
void Vector::reset(double n1, double n2, Mode form) {
mode = form;
if (form == RECT) {
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (form == POL) {
mag = n1;
ang = n2 / Rad_to_deg;
set_x();
set_y();
}
else {
cout << "Incorrect 3rd argument to reset() -- ";
cout << "vector set to 0.\n";
x = y = mag = ang = 0.0;
mode = RECT;
}
}
Vector::~Vector() {
}
void Vector::polar_mode() {
mode = POL;
}
void Vector::rect_mode() {
mode = RECT;
}
// 运算符重载
// 如果方法通过计算得到一个新的类对象,则应考虑是否可以使用类构造函数来完成这项工作。
// 这样不仅可以避免麻烦,而且可以确保新的对象是按照正确的方式创建的。
Vector Vector::operator+(const Vector& b) const {
return Vector(x + b.x, y + b.y);
}
// 对于减法来说顺序很重要
Vector Vector::operator-(const Vector& b) const {
return Vector(x - b.x, y - b.y);
}
Vector Vector::operator-() const {
return Vector(-x, -y);
}
Vector Vector::operator*(double n) const {
return Vector(n * x, n * y);
}
// 友元函数
Vector operator*(double n, const Vector& a) {
return a * n;
}
std::ostream& operator<<(std::ostream& os, const Vector& v) {
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;
}
}
// 11-1
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
#include "vector.h"
int main() {
using namespace std;
using VECTOR::Vector;
ofstream fout;
fout.open("thewalk.txt");
srand(time(0)); // time(0)获取当前时间的秒数,srand()设置随机数种子
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;
fout << "Target Distance: " << target << ", Step Size: " << dstep << endl;
fout << steps << ": (x, y) = (0, 0)\n";
while (result.magval() < target) {
direction = rand() % 360; // 随机找方向
step.reset(dstep, direction, Vector::POL);
result = result + step;
steps++;
fout << steps << ": (x, y) = (" << result.xval() << ", " << result.yval() << ")\n";
}
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.magval() / steps << endl;
steps = 0;
result.reset(0.0, 0.0);
cout << "Enter target distance (q to quit): ";
}
cout << "Bye!\n";
cin.clear();
while (cin.get() != '\n') continue;
return 0;
}
thewalk.txt文件中的内容:
Target Dist