1.修改程序清单11.5(随机漫步),使之以特定的格式将结果写入文件中。
//vector.h -- Vector Class
#ifndef _VECTOR_H_
#define _VECTOR_H_
#include
#include
namespace VECTOR
{
class Vector
{
public:
enum Mode{RECT,POL};
private:
double x;
double y;
double mag;
double ang;
Mode mode;
//private methods for setting values
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; }
double yval() const { return y; }
double magval() const { return mag; }
double angval() const { return ang; }
void polar\_mode();
void rect\_mode();
//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, Vector & a);
friend std::ostream & operator<<(std::ostream & os, const Vector & v);
friend std::ofstream & operator<<(std::ofstream & ofs, const Vector & v);
};
} //end namespace VECTOR
#endif // VECTOR_H_INCLUDED
//vector.cpp -- Methods for Vector class
#include
#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);
//private methods
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);
}
//public methods
Vector::Vector()
{
x = y = mag = ang = 0.0;
mode = RECT;
}
//construct vector from rectangular or polar coordinate
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;
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;
mode = RECT;
}
}
Vector::~Vector()
{
}
void Vector::rect\_mode()
{
mode = RECT;
}
void Vector::polar\_mode()
{
mode = POL;
}
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;
}
//display coordinates
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<<")";
}
else
os<<"Vector object is invalid";
return os;
}
//再为文件对象重载一个输出函数
std::ofstream & operator<<(std::ofstream & ofs, const Vector & v)
{
if(v.mode == Vector::RECT)
ofs<<"(x,y) = ("<<v.x<<","<<v.y<<")";
else if(v.mode == Vector::POL)
{
ofs<<"(m,a) = ("<<v.mag<<","<<v.ang<<")";
}
else
ofs<<"Vector object is invalid";
return ofs;
}
} //end namespace VECTOR
//randwalk.cpp -- using Vector Class
#include
#include
#include
#include "vector.h"
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 outfile; //文件对象
outfile.open("record.txt"); //打开文件
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.reset(dstep,direction,Vector::POL); //利用步长和方向设置移动的矢量
result = result + step; //(重载+)结果矢量更新
outfile<<steps<<": (x,y) = "<<"("<<result.xval()<<","<<result.yval()<<")"<<endl;
steps++;
}
outfile<<"After "<<steps<<" steps, the subject has the following location:\\n";
outfile<<result<<endl;
result.polar\_mode();
outfile<<" or\\n"<<result<<endl;
outfile<<"Average outward distance per step = "<<result.magval()/steps<<endl;
steps = 0;
result.reset(0.0,0.0);
cout<<"Enter target distance (q to quit): ";
}
outfile.close(); //关闭文件
cout<<"Bye!\\n";
cin.clear();
while(cin.get() != '\\n')
continue;
return 0;
}
2.保留类的公有接口不变,修改私有部分,使得其不再存储长度mag和角度ang的值,而是在调用magval()和angval()时计算它们。重新测试,结果应与原来相同。
主函数没动。类的声明和实现如下:
//vector.h -- Vector Class
#ifndef _VECTOR_H_
#define _VECTOR_H_
#include
#include
namespace VECTOR
{
class Vector
{
public:
enum Mode{RECT,POL};
private:
double x;
double y;
Mode mode;
//private methods for setting values
void set\_x(double m,double a); //使用长度和方向换算x和y
void set\_y(double m,double a);
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; }
double yval() const { return y; }
double magval() const; //调用时通过x和y计算长度和方向
double angval() const;
void polar\_mode();
void rect\_mode();
//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, Vector & a);
friend std::ostream & operator<<(std::ostream & os, const Vector & v);
friend std::ofstream & operator<<(std::ofstream & ofs, const Vector & v);
};
} //end namespace VECTOR
#endif // VECTOR_H_INCLUDED
//vector.cpp -- Methods for Vector class
#include
#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);
//private methods
void Vector::set\_x(double m,double a )
{
x = m \* cos(a/Rad\_to\_deg);
}
void Vector::set\_y(double m,double a )
{
y = m \* sin(a/Rad\_to\_deg);
}
//public methods
Vector::Vector()
{
x = y = 0.0;
mode = RECT;
}
double Vector::magval() const
{
return sqrt(x\*x +y\*y);
}
double Vector::angval() const
{
if (x == 0.0 && y == 0.0)
{
return 0.0;
}
else
{
return atan2(y, x);
}
}
//construct vector from rectangular or polar coordinate
Vector::Vector(double n1, double n2, Mode form)
{
mode = form;
if (form == RECT)
{
x = n1;
y = n2;
}
else if (form == POL)
{
set\_x(n1,n2);
set\_y(n1,n2);
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "Vector set to 0\\n";
x = y = 0;
mode = RECT;
}
}
void Vector::reset(double n1, double n2, Mode form)
{
mode = form;
if (form == RECT)
{
x = n1;
y = n2;
}
else if (form == POL)
{
set\_x(n1,n2);
set\_y(n1,n2);
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "Vector set to 0\\n";
x = y = 0;
mode = RECT;
}
}
Vector::~Vector()
{
}
void Vector::rect\_mode()
{
mode = RECT;
}
void Vector::polar\_mode()
{
mode = POL;
}
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;
}
//display coordinates
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.magval()<<","<<v.angval()<<")";
}
else
os<<"Vector object is invalid";
return os;
}
//再为文件对象重载一个输出函数
std::ofstream & operator<<(std::ofstream & ofs, const Vector & v)
{
if(v.mode == Vector::RECT)
ofs<<"(x,y) = ("<<v.x<<","<<v.y<<")";
else if(v.mode == Vector::POL)
{
ofs<<"(m,a) = ("<<v.magval()<<","<<v.angval()<<")";
}
else
ofs<<"Vector object is invalid";
return ofs;
}
} //end namespace VECTOR
3.继续修改上面的程序,不再写入每次测试的具体结果,而是由用户指定特定的测试次数N,写入N次测试的最大步数和最小步数。
//randwalk.cpp -- using Vector Class
#include
#include
#include
#include "vector.h"
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;
unsigned long max\_steps;
unsigned long min\_steps;
double target = 0; //移动距离范围
double dstep = 0; //每次移动的步长
unsigned test\_times = 0;
unsigned N; //用户指定的测试次数
//测试准备
ofstream outfile; //文件对象
outfile.open("record.txt"); //打开文件
cout<<"Enter times you want to test: ";
if(cin>>N)
{
cout<<"Enter target distance: ";
cin>>target;
cout<<"Enter step length: ";
cin>>dstep;
}
else
{
N = 1;
}
outfile<<"Target Distance: "<<target<<", Step Size: "<<dstep<<endl;
unsigned long \* all\_steps = new unsigned long \[N\]; //分配用于存储所有测试步数的数组指针
//测试过程
while(test\_times<N)
{
while(result.magval() < target)
{
direction = rand()%360; //随机生成一个方向(角度)
step.reset(dstep,direction,Vector::POL); //利用步长和方向设置移动的矢量
result = result + step; //(重载+)结果矢量更新
steps++;
}
all\_steps\[test\_times\] = steps; //存储此次测试的步数
outfile<<"Test "<<test\_times<<" used "<<steps<<" steps."<<endl;
steps = 0;
result.reset(0.0,0.0);
test\_times++;
}
//测试结果
outfile<<"You have tested "<<N<<" times."<<endl;
max\_steps = min\_steps = all\_steps\[0\]; //比较最大和最小步数
for(unsigned i=0;i<N;i++)
{
if(all\_steps\[i\]>max\_steps)
max\_steps = all\_steps\[i\];
else{};
if(all\_steps\[i\]<min\_steps)
min\_steps = all\_steps\[i\];
else{};
}
outfile<<"Max steps: "<<max\_steps<<endl;
outfile<<"Minimum steps: "<<min\_steps<<endl;
outfile.close(); //关闭文件
cout<<"Bye!\\n";
delete\[\]all\_steps; //删除动态内存
cin.clear();
while(cin.get() != '\\n')
continue;
return 0;
}
输出结果的形式:
7.实现一个复数类,使之能进行基本的加减乘运算,其中需要重载“<<”、“>>”、“~”、“+”、“-”、“*”等运算符,并定义友元函数。
//complex0.h -- Declaration of Complex Class
#ifndef _COMPLEX0_H_
#define _COMPLEX0_H_
#include
using namespace std;
class Ccomplex
{
private:
double m_real ;
double m_imag ;
public:
Ccomplex();
~Ccomplex();
void set_real(double i);
void set_imag(double r);
Ccomplex(double r ,double i );
Ccomplex operator +(const Ccomplex & c) const;
Ccomplex operator -(const Ccomplex & c) const;
Ccomplex operator *(const Ccomplex & c) const;
friend istream & operator >> (istream & is, Ccomplex & c);
friend ostream & operator << (ostream & os, const Ccomplex c);
friend Ccomplex operator ~(const Ccomplex c); //如果按引用传递上一句重载函数会不匹配,所以按值传递
friend Ccomplex operator *(const double n,const Ccomplex c);
};
#endif // _COMPLEX0_H_
//complex0.cpp -- Methods of Complex Class
#include"complex0.h"
Ccomplex::Ccomplex()
{
m_real = 0;
m_imag = 0;
}
Ccomplex::~Ccomplex()
{
}
Ccomplex::Ccomplex(double r = 0,double i = 0)
{
m_real = r;
m_imag = i;
}
void Ccomplex::set_imag(double i)
{
m_imag = i;
}
void Ccomplex::set_real(double r)
{
m_real = r;
}
Ccomplex operator ~(const Ccomplex c)
{
return Ccomplex(c.m_real,-c.m_imag);
}
Ccomplex Ccomplex::operator +(const Ccomplex & c) const
{
return Ccomplex(m_real + c.m_real,m_imag + c.m_imag);
}
Ccomplex Ccomplex::operator -(const Ccomplex & c) const
{
return Ccomplex(m_real - c.m_real,m_imag - c.m_imag);
}
Ccomplex Ccomplex::operator *(const Ccomplex & c) const
{
return Ccomplex(m_real*c.m_real - m_imag*c.m_imag , m_real*c.m_imag + m_imag*c.m_real);
}
Ccomplex operator *(const double n,const Ccomplex c)
{
return Ccomplex(n*c.m_real,n*c.m_imag);
}
istream & operator >> (istream & is, Ccomplex & c)
{
double tr,ti;
cout<<"real: ";
is >> tr;
cout<<"imaginary: ";
is >> ti;
c.set_real(tr);
c.set_imag(ti);
return is;
}
ostream & operator << (ostream & os, const Ccomplex c)
{
if(c.m_imag > 0)
{
os<<"("<<c.m_real<<"+"<<c.m_imag<<"i)";
}
else if(c.m_imag == 0)
{
os<<c.m_real<<endl;
}
else
{
os<<"("<<c.m_real<<c.m_imag<<"i)";
}
return os;
}
//main.cpp -- Using Complex Class
#include
#include"complex0.h"
int main()
{
Ccomplex a(3.0,4.0);
Ccomplex c;
cout<<"Enter a complex number (q to quit):\\n";
while(cin>>c)
{
cout<<"c is "<<c<<'\\n';
cout<<"complex conjugate is "<<~c<<'\\n';
cout<<"a is "<<a<<'\\n';
cout<<"a + c is "<<a + c<<'\\n';
cout<<"a - c is "<<a - c<<'\\n';
cout<<"a \* c is "<<a \* c<<'\\n';
cout<<"2 \* c is "<<2 \* c<<'\\n';
cout<<"Enter a complex number (q to quit):\\n";
}
cout<<"Done!\\n";
return 0;
}
调试的过程中遇到了很多问题,总结一下:
1.友元函数和类本体有着同样的权力,能够访问私有成员。
2.给出友元函数的定义时,不用加上类的“::”的解析符,和正常的函数定义一样。
3.如果不是在类成员函数的实现里面的话,类本身是调不出它的私有成员的。比如在主函数里想通过 “.” 调出私有成员赋给另一个变量是不行的,除非通过公共接口。
4.分清楚重载运算符是想用于什么样形式的运算。如果想定义一种【该类——该运算符——其它类型】的运算,使用成员函数重载,“其它类型”以参数传递(如上面例程中的加减号重载);如果想定义一种【其它类型——该运算符——该类】的运算,使用友元函数重载(如上面例程中的>>,<<,~的重载)。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章