《C++primerplus》第11章练习题
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章练习题的更多相关文章
- 读《编写可维护的JavaScript》第11章总结
这周也是拿到了同程的offer,从此走上了前端之路!感谢我的贵人们.再次纪念一下~! 第11章 不是你的对象不要动 11.1 什么是你的 你的对象:当你的代码创建了这些对象或者你有职责维护其他人的代码 ...
- 第11章 Windows线程池(1)_传统的Windows线程池
第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...
- 《TCP/IP详解卷1:协议》第11章 UDP:用户数据报协议-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- java JDK8 学习笔记——第11章 线程和并行API
第11章 线程与并行API 11.1 线程 11.1.1 线程 在java中,如果想在main()以外独立设计流程,可以撰写类操作java.lang.Runnable接口,流程的进入点是操作在run( ...
- 高性能Linux服务器 第11章 构建高可用的LVS负载均衡集群
高性能Linux服务器 第11章 构建高可用的LVS负载均衡集群 libnet软件包<-依赖-heartbeat(包含ldirectord插件(需要perl-MailTools的rpm包)) l ...
- Linux就这个范儿 第11章 独霸网络的蜘蛛神功
Linux就这个范儿 第11章 独霸网络的蜘蛛神功 第11章 应用层 (Application):网络服务与最终用户的一个接口.协议有:HTTP FTP TFTP SMTP SNMP DNS表示层 ...
- 锋利的jQuery第2版学习笔记8~11章
第8章,用jQuery打造个性网站 网站结构 文件结构 images文件夹用于存放将要用到的图片 styles文件夹用于存放CSS样式表,个人更倾向于使用CSS文件夹 scripts文件夹用于存放jQ ...
- 《Android开发艺术探索》读书笔记 (11) 第11章 Android的线程和线程池
第11章 Android的线程和线程池 11.1 主线程和子线程 (1)在Java中默认情况下一个进程只有一个线程,也就是主线程,其他线程都是子线程,也叫工作线程.Android中的主线程主要处理和界 ...
- C++ Primer 读书笔记:第11章 泛型算法
第11章 泛型算法 1.概述 泛型算法依赖于迭代器,而不是依赖容器,需要指定作用的区间,即[开始,结束),表示的区间,如上所示 此外还需要元素是可比的,如果元素本身是不可比的,那么可以自己定义比较函数 ...
随机推荐
- Android Studio或者Eclipse中的最常用的快捷键,最简单的,部分不适用eclipse
重写方法:ctrl+shift+s 然后选择Generate 构建即可: 执行程序:shift+F10 多行注释:ctrl+shift+/ 单行注释:ctrl+/ 快速打印log:logr 快速复制 ...
- facebookPixel代码安装详解
最近接到一个需求,优化独立站的facebookPixel代码,完成后对这个项目进行复盘.首先要介绍facebookPixel的理论知识. Facebook像素是一段JavaScript代码,其中加载了 ...
- c# 可获取系统环境
c# 可获取系统环境, 启动进程执等 *.shell [MenuItem("Tools/DesignHelper/Clean and Pull")] private sta ...
- ios 常见性能优化
1. 用ARC管理内存 2. 在正确的地方使用reuseIdentifier 3. 尽可能使Views透明 4. 避免庞大的XIB 5. 不要block主线程 6. 在Image Views中调整图片 ...
- 【转】Android DrawingCache
转自:http://magiclen.org/android-drawingcache/ 日期: 2014 年 8 月 27 日 | 作者: Magic Len 開發Android的時候,在許多情況下 ...
- Easy Problem(等差数列求和导公式)
链接:https://ac.nowcoder.com/acm/contest/316/A 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言2621 ...
- 19_Python算法
1.冒泡算法 list = [1, 5, 2, 6, 9, 3, 4, 0] print(len(list)) # conunt = 1 while conunt < len(list): fo ...
- 《Redis内存数据库》Redis环境搭建
前言 Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多 ...
- DevOps-实践心得
基于最近几年从事与DevOps的相关实践,对这篇文章的观点深有体会,所以记录在这里.加粗部分是我比较深有体会的,但是对于最后作者对于"运维"有些悲观,我有点不敢苟同,反而对于运维的 ...
- ajax之---“伪”ajax
views.py def ajax1(request): ret={'status':'true','message':'successful'} return HttpResponse(json.d ...