编程练习11.9
1.修改程序清单 11.5,使之将一系列连续的随机漫步者位置写入到文件中。对于每个位置,用步号进行标示。另外,让该程序将初始条件(目标距离和步长)以及结果小结写入到该文件中。该文件的内容与下面类似:
Target Distance:100,stepSize:20
0:(xy)=(0,0)
1:(x,y)=(-11.4715,16.383)
2:(x,y)=(-8.68807,-3.42232)
26:(x,y)=(42.2919,-78.2594)
27:(x,y)=(58.6749,-89.7309)
After 27 steps,the subject has the following location:
(x,y)=(58.6749,-89.7309)
or
(m,a)=(107.212,-56.8194)
Average outward distance perstep=3.97081
vector.h
#pragma once
//vect.h -- Vector class with <<,mode state
#ifndef VECTOR_H_
#define VECTOR_H_
#include<iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode { RECT, POL };//以此为直角坐标,极坐标(长度,角度)
//RECT for rectangular,POL for Polar modes
private:
double x;//horizontal value x方向x坐标
double y;//vertical value y方向y坐标
double mag; //length of value 极坐标的长度
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 x, double y, Mode form = RECT);
void reset(double x, double y, Mode form = RECT);
~Vector();
double xval()const { return x; }//report x val
double yval()const { return y; }//report y val
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 Vector
}//end namespace VECTOR
#endif
vetor.cpp
//vect.cpp == methods for the Vector class
#include<cmath>
#include"vector.h" //includes<iostream>
using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;
using std::endl;
namespace VECTOR
{
//comput degrees in one radian
const double Rad_to_deg = 45.0 / atan(1.0);
//should 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 (x == 0.0 && y == 0.0)
{
ang = 0.0;
}
else
{
ang = atan2(y, x);
}
}
//set x from polar coorinate
void Vector::set_x()
{
x = mag * cos(ang);
}
//set y from polar coorinate
void Vector::set_y()
{
y = mag * sin(ang);
}
//public methods
//default constructor
Vector::Vector()
{
y = x = mag = ang = 0.0;
mode = RECT;
}
//construct vector from rectangular coordinates if form is r
//(the default) or else from polay coordinates if form is p
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_mag();
set_ang();
}
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 coorinates if form is
//RECT(the default) or else from polar coorinates if
//form is POL
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()//destructor
{
}
void Vector::polar_mode()//set to polay mode
{
mode = POL;
}
void Vector::rect_mode() // set to rectangular mode
{
mode = RECT;
}
//operator overloading
//add two Vectors
Vector Vector::operator+(const Vector& b)const
{
return Vector(x + b.x, y + b.y);
}
//sub 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);
}
//multyply 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 coorinates if mode is RECT
//else display polar coordinates if mode is POL
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;
}
}//end namespace VECTOR
main.cpp
#if 1
#include <iostream>
#include<cstdlib> //rand,srand() prototypes
#include<ctime>//time()prototype
#include<fstream>
#include"vector.h"
int main()
{
using namespace std;
using VECTOR::Vector;
ofstream of;
of.open("ofoutput.txt");
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.setf(ios_base::fixed, ios_base::floatfield);
cout.precision(2);
of.setf(ios_base::fixed, ios_base::floatfield);
of.precision(2);
cout << "Enter target distance(q to quit):";
of << "Enter target distance(q to quit):";
while (cin >> target)
{
of << target << ", ";
cout << "Enter step length: ";
of << "Enter step length: ";
if (!(cin >> dstep))
{
break;
}
of << dstep<<endl;
while (result.magVal() < target)
{
cout << steps << "\t: (x,y) = (" << result.xval()<<" " << result.yval() << ")" << endl;
of << steps << "\t: (x,y) = (" << result.xval() << " " << result.yval() << ")" << endl;
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result + step;
steps++;
}
cout << steps << ": (x,y) = (" << result.xval() << " " << result.yval() << ")" << endl;
of << steps << ": (x,y) = (" << result.xval() << " " << result.yval() << ")" << endl;
cout << "After " << steps << " steps,the subject " "has the following location:\n";
of << "After " << steps << " steps,the subject " "has the following location:\n";
cout << result << endl;
of << result << endl;
result.polar_mode();
cout << " or\n" << result << endl;
of << " or\n" << result << endl;
cout << "Average outward distance per step = "<< result.magVal() / steps << endl;
of << "Average outward distance per step = " << result.magVal() / steps << endl;
steps = 0;
result.reset(0.0, 0.0);
cout << "Enter target distance(q to quit): ";
of << "Enter target distance(q to quit): ";
}
cout << "Bye!\n";
cin.clear();
while (cin.get() != '\n')
{
continue;
}
cout.unsetf(cout.flags());
of.unsetf(cout.flags());
of.close();
return 0;
}
#endif
实验结果
总结:
1,在11.5程序清单中已经实现过。
2,增加文件处理的类ofstream,打开文件,关闭文件
3,增加格式化控制cout.setf(ios_base::fixed, ios_base::floatfield);
cout.precision(2);cout.unsetf(cout.flags());
4,这种处理的随机性使得每次运行结果都不同,即使初始条件相同。然而,平均而言,步长减半,步数将为原来的4倍。概率理论表明,平均而言,步数(N)、步长(s),净距离D之间的关系如下:
N=(D/s)的N次方
5,做这种练习锻炼思维为日后编程打下扎实的基础