本章所有编程练习的工程源码可在此处下载(点击此链接下载),供大家参考交流!
1. 修改程序清单11.5,使之将一系列连续的随机漫步者位置写入到文件中。对于每个位置,用步号进行标示。另外,让该程序将初始条件(目标距离和步长)以及结果小结写入到该文件中。该文件的内容与下面类似:
(……代码省略……)
本题要求将随机漫步者的位置写入到文件中,这些内容刚好和程序清单11.13,11.14,11.15的内容类似,所以我们可以效仿这几个例子来进行修改,以完成题目要求。(不知道为什么题目说的是修改程序清单11.5,猜测应该是“修改程序清单11.15”)
首先我们把头文件拿过来,原封不动地就可以了,因为我们这里并没有什么新的功能,所有需要使用的功能程序清单11.13都包含了。
所以头文件vector.h代码如下:
// vector.h -- Vector class with <<, mode state
#ifndef VECTOR_H_
#define VECTOR_H_
#include <iostream>
namespace VECTOR
{
class Vector
{
public:
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; } // repot values
double yval() const { return y; }
double magval() const { return mag; }
double angval() const { return ang; }
void polar_mode();
void rect_mode();
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
有了头文件之后,我们需要来为头文件里面的公有成员函数做函数定义,因为头文件和程序清单11.13完全相同,所以函数定义文件和程序清单11.14也就完全一样了,完全相同来定义就可以了。
所以vector.cpp代码如下:
//vector.cpp -- methods for the Vector class
//
#include "stdafx.h"
#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);
void Vector::set_mag()
{
mag = sqrt(x * x + y * y);
}
void Vector::set_ang()
{
if (x == 0.0 && y == 0.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);
}
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 Vector() -- ";
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;
}
}
那么接下来主要就是检查函数了,首先,本题的检查函数要能够将数据写入到文件,这需要使用头文件<fstream>,并使用其中的fout函数来进行数据的写入;其实我们可以使用程序清单11.15的大框架,然后在此基础上进行功能的添加就可以了。
首先,我们按照程序清单11.15一模一样,根据随机种子来产生随机漫步者的随机方向和距离,初始化为原点,接下来加入写入到文件中的fout语句,
ofstream fout;
fout.open("RandWalk.txt");
下面这两句非常重要,第一句是定义fout为写入函数,fout.open就成为了打开文件的函数,因为此时目录中没有名字为“Randwalk.txt”的文件,所以就会自动去生成一个该名字的文件。
接下来和程序清单11.15相同,我们提示输入,但是一定要记得加上将输入结果写入到文件中的功能。对于题目要求的每一次显示结果都要在前面加上序号,我们必须自定义一个int整数类作为序号,每次将结果按照序号来写入。如下所示:
fout << i << ": (x,y) = (" << result.xval() << ", " << result.yval() << ")\n";
i++;
其中i就是序号。
其他的其实就没有什么特殊的了,功能上来说主要就是在程序11.13,11.14,11.15的基础上加了一个写入文件,以及按要求写入。
所以randwalk.cpp代码如下:
// randwalk.cpp -- using the Vector class
// compile with the vector.cpp file
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "vector.h"
#include <fstream>
int main()
{
using namespace std;
using VECTOR::Vector;
srand(time(0));
double direction;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
ofstream fout;
fout.open("RandWalk.txt");
cout << "Enter target distance (q to quit): ";
while (cin >> target)
{
cout << "Enetr step length: ";
if (!(cin >> dstep))
{
break;
}
else
{
fout << "Target Distance: " << target << ", Step Size: " << dstep << endl;
}
int i = 0;
while (result.magval() < target)
{
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result + step;
steps++;
fout << i << ": (x,y) = (" << result.xval() << ", " << result.yval() << ")\n";
i++;
}
cout << "After " << steps << " steps, the subject has the following location:\n";
cout << result << endl;
fout << "After " << steps << " steps, the subject has the following location:\n";
fout << result << endl;
result.polar_mode();
cout << " or\n" << result << endl;
cout << "Average outward distance per step = " << result.magval() / steps << endl;
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";
fout << "Bye!\n";
cin.clear