1.修改程序清单11.5(随机漫步),使之以特定的格式将结果写入文件中。

//vector.h -- Vector Class
#ifndef _VECTOR_H_
#define _VECTOR_H_
#include<iostream>
#include<fstream>
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 <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); //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 <iostream>
#include <cstdlib>
#include <ctime>
#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<iostream>
#include<fstream>
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 <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); //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 <iostream>
#include <cstdlib>
#include <ctime>
#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<iostream>
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 <iostream>
#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.分清楚重载运算符是想用于什么样形式的运算。如果想定义一种【该类——该运算符——其它类型】的运算,使用成员函数重载,“其它类型”以参数传递(如上面例程中的加减号重载);如果想定义一种【其它类型——该运算符——该类】的运算,使用友元函数重载(如上面例程中的>>,<<,~的重载)。

《C++primerplus》第11章练习题的更多相关文章

  1. 读《编写可维护的JavaScript》第11章总结

    这周也是拿到了同程的offer,从此走上了前端之路!感谢我的贵人们.再次纪念一下~! 第11章 不是你的对象不要动 11.1 什么是你的 你的对象:当你的代码创建了这些对象或者你有职责维护其他人的代码 ...

  2. 第11章 Windows线程池(1)_传统的Windows线程池

    第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...

  3. 《TCP/IP详解卷1:协议》第11章 UDP:用户数据报协议-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  4. java JDK8 学习笔记——第11章 线程和并行API

    第11章 线程与并行API 11.1 线程 11.1.1 线程 在java中,如果想在main()以外独立设计流程,可以撰写类操作java.lang.Runnable接口,流程的进入点是操作在run( ...

  5. 高性能Linux服务器 第11章 构建高可用的LVS负载均衡集群

    高性能Linux服务器 第11章 构建高可用的LVS负载均衡集群 libnet软件包<-依赖-heartbeat(包含ldirectord插件(需要perl-MailTools的rpm包)) l ...

  6. Linux就这个范儿 第11章 独霸网络的蜘蛛神功

    Linux就这个范儿 第11章  独霸网络的蜘蛛神功  第11章 应用层 (Application):网络服务与最终用户的一个接口.协议有:HTTP FTP TFTP SMTP SNMP DNS表示层 ...

  7. 锋利的jQuery第2版学习笔记8~11章

    第8章,用jQuery打造个性网站 网站结构 文件结构 images文件夹用于存放将要用到的图片 styles文件夹用于存放CSS样式表,个人更倾向于使用CSS文件夹 scripts文件夹用于存放jQ ...

  8. 《Android开发艺术探索》读书笔记 (11) 第11章 Android的线程和线程池

    第11章 Android的线程和线程池 11.1 主线程和子线程 (1)在Java中默认情况下一个进程只有一个线程,也就是主线程,其他线程都是子线程,也叫工作线程.Android中的主线程主要处理和界 ...

  9. C++ Primer 读书笔记:第11章 泛型算法

    第11章 泛型算法 1.概述 泛型算法依赖于迭代器,而不是依赖容器,需要指定作用的区间,即[开始,结束),表示的区间,如上所示 此外还需要元素是可比的,如果元素本身是不可比的,那么可以自己定义比较函数 ...

随机推荐

  1. CPU有个禁区,内核权限也无法进入!

    神秘项目 我是CPU一号车间的阿Q,是的,我又来了. 最近一段时间,我几次下班约隔壁二号车间虎子,他都推脱没有时间,不过也没看见他在忙个啥. 前几天,我又去找他,还是没看到他人,却意外地在他桌上发现了 ...

  2. unity 对Animator动画系统的研究

    unity的新动画系统叫Mecanim,使用Animator来取代旧系统Animation,按Unity文档的惯例:知识点主要分2部分:unity manual和unity script,读者可以边看 ...

  3. 最详细不过的CUDA的下载安装使用、环境变量配置,有这一篇就够了

    在上一期中,我们介绍了为什么使用GPU可以加速计算和处理图像,以及查看自己的电脑能否使用GPU加速,不知道的可以去看上一期文章,这期我们正式的来下载与安装GPU加速工具CUDA,并检查是否安装成功. ...

  4. Zabbix housekeeper processes more than 75% busy

    原因分析 为了防止数据库持续增大,Zabbix有自动删除历史数据的机制,即housekeeper,而在频繁清理历史数据的时候,MySQL数据库可能出现性能降低的情况,此时就会告警. 一般来说,Zabb ...

  5. [Python]在当前目录下创建三个目录

    import os os.mkdir("2018-03-16-b018") os.mkdir("2019-03-16-b019") os.mkdir(" ...

  6. linux下禁止root和匿名用户登录ftp

    1.ftp通过root或其他用户进入可视化界面权限过大,容易导致系统文件误删 windows下输入ftp://IP去访问,不需要账号密码就可以访问到ftp文件夹 刚进去pub是空的,在linux上新增 ...

  7. SpringCloud实战 | 第二篇:SpringCloud整合Nacos实现注册中心

    前言 随着eureka的停止更新,如果同时实现注册中心和配置中心需要SpringCloud Eureka和SpringCloud Config两个组件;配置修改刷新时需要SpringCloud Bus ...

  8. Video.js + HLS 在production环境下webpack打包后出错的解决方案

    Video.js是一个非常强大的视频播放库,能在微信下完美提供inline小窗口播放模式,但当涉及到hls格式视频播放时就比较麻烦,出现的数种现象都不好解决. 错误现象:  1.  PC Chrome ...

  9. 关于java数组基础练习题

    定义一个int[] a ={4,2,0,-1,-8,23,9}求数组元素的最大值.最小值.平均数.总和.数组的复制.反转 //3.定义一个int[] a ={4,2,0,-1,-8,23,9}求数组元 ...

  10. JAVA之代理1JDK

    代理主要有JDK的代理以及CGLIB的代理 代理方式 实现 优点 缺点 特点 JDK静态代理 代理类与委托类实现同一接口,并且在代理类中需要硬编码接口 实现简单,容易理解 代理类需要硬编码接口,在实际 ...