写在前面:
昨天答了笔试,写问答题才发现自己C++类这部分的知识了解并不深入,有些知识点以为自己懂了,结果在题目面前还是发现自己没有想清楚。虽然之前看过很多遍C++ primer,但是从来没有自己动手写过编程练习,最多是照着答案看过复习题,看别人说写不写课后题对知识理解差别很大,决定从今天起认真把11章以后的每道课后题都写一下。
11.1 修改程序清单11.15,使之将一系列连续的随机漫步者位置写入到文件中。对于每个位置用步号进行标示。另外,让该程序将初始条件(目标距离和步长)以及结果小结写入到该文件中。该文件的内容与下面的类似:
Target Distance:100, Step Size: 20
0:(x,y) = (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 per step = 3.97081
题目需要做的就是把11.15的cout内容写入文件,考察C++写入文件,具体代码如下:
#include <iostream>
#include "vect.h"//书中11.13
#include <fstream>
#include <ctime>
using namespace std;
int main(){
using VECTOR::Vector;
string filename = "randwalk.txt";
ofstream outFile;
outFile.open(filename.c_str(), ios_base::out);
srand(time(0));
double direction;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
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;
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):";
}
cout<< "Bye!\n";
cin.clear();
while(cin.get() != '\n')
continue;
return 0;
}
11.2 对Vector类的头文件和实现文件进行修改,使其不再存储矢量的长度和角度,而是在magval()和angval()被调用时计算它们。应保留公有接口不变(公有方法及其参数不变),但对私有部分(包括一些私有方法)和方法 实现进行修改。然后,使用程序清单11.15对修改后的版本进行测试,结果应与之前相同。因为Vector类的公有接口与原来相同。
头文件:
//
// vect.h
// 11.1
//
// Created by apple on 2018/8/12.
// Copyright © 2018年 apple. All rights reserved.
//
#ifndef vect_h
#define vect_h
namespace VECTOR {
class Vector{
public:
enum Mode{RECT, POL};
private:
double x; //horizontal value
double y; //vertical value
double mag;//length of vector
double ang;//direction of vector in degrees
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 magval()const;
//修改前代码为double angval()const{return ang;}
double angval()const;
void polar_mode();
void rect_mode();
//operator overoading
Vector operator+(const Vector &b) const;
Vector operator-(const Vector &b) const;
Vector operator-() const;
Vector operator*(double n) const;
//friend;
friend Vector operator *(double n, const Vector &a);
friend std::ostream& operator<<(std::ostream &os, const Vector &v);
);
}
#endif /* vect_h */
头文件实现文件:
//
// vector.cpp
// 11.1
//
// Created by apple on 2018/8/12.
// Copyright © 2018年 apple. All rights reserved.
//
#include <stdio.h>
#include <iostream>
#include <cmath>
#include "vect.h"
using namespace std;
namespace VECTOR {
const double Rad_to_deg = 45.0 / atan(1.0);//atan返回数字的反正切,求出的ß的取值范围[-PI/2, PI/2]
//此处为修改后的实现
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);
}
Vector::Vector(){
x = y = mag = ang = 0;
mode = RECT;
}
Vector::Vector(double n1, double n2, Mode form){
mode = form;
if(form == RECT){
x = n1;
y = n2;
}
else if(form == POL){
x = n1 * cos(n2);
y = n1 * sin(n2);
}
else{
cout<<"Incorrect 3rd argument to Vector()";
cout<<"vector set to 0\n";
x = y = 0.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){
x = n1 * cos(n2);
y = n1 * sin(n2);
}
else{
cout<<"Incorrect 3rd argument to Vector()";
cout<<"vector set to 0\n";
x = y = 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;
}
}
测试文件:
//
// randwalk.cpp
// 11.1
//
// Created by apple on 2018/8/12.
// Copyright © 2018年 apple. All rights reserved.
//
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "vect.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;
cout<<"Enter target distance (q to quit):";
while(cin>>target){
cout<<"Enter step length: ";
if(!(cin>>dstep))
break;
while(result.magval() < target){
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result + step;
steps++;
}
cout<<"After " << steps<<"steps, the subject "<<"has the following location:\n";
cout<< result << endl;
result.polar_mode();
cout<<" or\n"<<result<<endl;
cout<<" 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";
cin.clear();
while(cin.get() != '\n')
continue;
return 0;
}
11.3 修改程序清单11.15,使之报告N次测试中的最高、最低和平均步数(其中N是用户输入的整数),而不是报告每次测试的结果。
//
// main.cpp
// 11.1
//
// Created by apple on 2018/8/12.
// Copyright © 2018年 apple. All rights reserved.
//
/*
修改程序清单11.5,使之将一系列连续的随机漫步者位置写入到文件中。对于每个位置用步号进行标示。另外,让该程序将初始条件(目标距离和步长)以及结果小结写入到该文件中。该文件的内容与下面的类似:
Target Distance:100, Step Size: 20
0:(x,y) = (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 per step = 3.97081
*/
#include <iostream>
#include "vect.h"
#include <fstream>
#include <ctime>
using namespace std;
int main(){
using VECTOR::Vector;
// string filename = "randwalk.txt";
// ofstream outFile;
// outFile.open(filename.c_str(), ios_base::out);
srand(time(0));
double direction;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
double avgstep;
int n;
cout<<"Enter target distance (q to quit):";
while(cin>>target){
cout<<"Enter step length: ";
if(!(cin>>dstep))
break;
cout<<"cout要测试的次数";
cin>>n;
double *p = new double[n];
double sum = 0;
cout<<"Target Distance: "<<target<<","<<"step size: "<<dstep<<endl;
for (int i = 0; i < n; ++i) {
result.reset(0.0, 0.0);
if(result.magval() < target){
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result + step;
steps++;
}
p[i] = steps;
sum += steps;
cout<< i+1 <<"test: "<< p[i]<<endl;
}
// outFile<<"Target Distance: "<<target<<","<<"step size: "<<dstep<<endl;
// while(result.magval() < target){
double maxstep = INT_MIN;
double minstep = INT_MAX;
for(int i = 0; i < n; i++){
if(p[i] > maxstep)
maxstep = p[i];
if(p[i] < minstep)
minstep = p[i];
}
avgstep = sum /n;
cout<<"After "<<n<<"test, Maxsteps = "<<maxstep<<" Minsteps = "<<minstep <<" avgsteps = "<<avgstep<<endl;
delete []p;
// outFile<<"After " << steps<<"steps, the subject "<<"has the following location:\n";
steps = 0;
result.reset(0.0, 0.0);
cout<<"Enter target distance (q to quit):";
}
cout<< "Bye!\n";
cin.clear();
while(cin.get() != '\n')
continue;
return 0;
}
11.4 重新编写最后的Time类示例(程序清单11.10、程序清单11.11和程序清单11.12)使用友元函数来实现所有的重载运算符。
//
// mytime3.cpp
// 11.2
//
// Created by apple on 2018/8/12.
// Copyright © 2018年 apple. All rights reserved.
//
#include <stdio.h>
#include "mytime3.h"
Time::Time(){
hours = minutes = 0;
}
Time::Time(int h, int m){
hours = h;
minutes = m;
}
void Time::AddMin(int m){
minutes += m;
hours += minutes/60;
minutes %= 60;
}
void Time::AddHr(int h){
hours += h;
}
void Time::Reset(int h, int m){
hours = h;
minutes = m;
}
Time operator+(const Time & t1,const Time & t2){
Time sum;
sum.minutes = t1.minutes + t2.minutes;
sum.hours = t1.hours + t2.hours + sum.minutes/60;
sum.minutes %=60;
return sum;
}
/*Time Time::operator+(const Time & t)const{
Time sum;
sum.minutes = minutes + t.minutes;
sum.hours = hours + t.hours + sum.minutes/60;
sum.minutes %= 60;
return sum;
}*/
Time operator-(const Time & t1,const Time & t2){
Time diff;
int tot1, tot2;
tot1 = t1.minutes + 60 * t1.hours;
tot2 = t2.minutes + 60 * t2.hours;
diff.minutes = (tot2 - tot1)%60;
diff.hours = (tot2-tot1)/60;
return diff;
}
/*Time Time::operator-(const Time & t) const{
Time diff;
int tot1, tot2;
tot1 = t.minutes + 60 * t.hours;
tot2 = minutes + 60 * hours;
diff.minutes = (tot2 - tot1)%60;
diff.hours = (tot2-tot1)/60;
return diff;
}*/
Time operator*(const Time &t,double n ){
Time result;
long totalminutes = t.hours * n * 60 + t.minutes * n;
result.hours = totalminutes/60;
result.minutes = totalminutes % 60;
return result;
}
/*Time Time::operator*(double mult) const{
Time result;
long totalminutes = hours * mult * 60 + minutes * mult;
result.hours = totalminutes/60;
result.minutes = totalminutes % 60;
return result;
}*/
std::ostream & operator<<(std::ostream & os, const Time &t){
os<<t.hours<<" house, "<<t.minutes<<" minutes";
return os;
}
5.重新编写Stonwt类(程序清单11.16和程序清单11.17),使它有一个状态成员,由该成员控制对象应转换为英石格式,整数磅格式还是浮点磅格式。重载<<运算符,使用它来替换show_stn()和show_lbs()方法。重载加法、减法和乘法运算符,以便可以对Stonwt值进行加、减、乘运算。编写一个使用所有类方法和友元的小程序,来测试这个类。
头文件
//
// stonewt.h
// 11.5
//
// Created by apple on 2018/8/12.
// Copyright © 2018年 apple. All rights reserved.
//
#ifndef stonewt_h
#define stonewt_h
class Stonewt{
private:
enum Mode{STO, POU, FLO};
Mode mode;
enum{Lbs_per_stn = 14}; //pounds per stone
int stone;
double pds_left;
double pounds;
public:
void sto_mode();
void pou_mode();
void flo_mode();
Stonewt(double lbs);
Stonewt(int stn, double lbs, Mode mode = FLO);
Stonewt();
~Stonewt();
Stonewt operator+(const Stonewt& n1);
Stonewt operator-(const Stonewt& n1);
Stonewt operator*(const double n) const;
// void show_lbs() const;
// void show_stn() const;
friend std::ostream& operator<<(std::ostream &os, const Stonewt &s);
};
#endif /* stonewt_h */
头文件实现
//
// stonewt.cpp
// 11.5
//
// Created by apple on 2018/8/12.
// Copyright © 2018年 apple. All rights reserved.
//
#include <stdio.h>
#include <iostream>
using std::cout;
#include "stonewt.h"
Stonewt::Stonewt(double lbs){
stone = int(lbs) / Lbs_per_stn;
pds_left = int(lbs)%Lbs_per_stn + lbs - int(lbs);
pounds = lbs;
}
Stonewt::Stonewt(int stn, double lbs, Mode mode){
stone = stn;
pds_left = lbs;
pounds = stn * Lbs_per_stn + lbs;
}
Stonewt::Stonewt(){
stone = pounds = pds_left = 0;
}
Stonewt::~Stonewt(){
}
/*void Stonewt::show_stn() const{
cout<< stone<<" stone, "<< pds_left<<" pounds.\n";
}
void Stonewt::show_lbs() const{
cout<<pounds<<" pounds.\n";
}*/
void Stonewt::flo_mode(){
mode = FLO;
}
void Stonewt::pou_mode(){
mode = POU;
}
void Stonewt::sto_mode(){
mode = STO;
}
std::ostream& operator<<(std::ostream &os, const Stonewt &s){
if(s.mode == Stonewt::STO){
double temp;
temp = s.stone + s.pds_left / Stonewt::Lbs_per_stn;
os<<"Stone mode: "<<temp <<" stone" <<std::endl;
}
else if(s.mode == Stonewt::POU){
os<<"Integer pounds mode: "<<s.pounds <<" pounds."<<std::endl;
}
else if(s.mode == Stonewt::FLO){
os<<"Float pounds mode: "<< s.stone <<" stone," <<s.pds_left<<std::endl;
}
return os;
}
Stonewt Stonewt::operator+(const Stonewt& n1){
Stonewt tmp;
tmp.pounds = pounds + n1.pounds;
tmp.stone = tmp.pounds / Lbs_per_stn;
tmp.pds_left = int(tmp.pounds)%Lbs_per_stn + tmp.pounds - int(tmp.pounds);
return tmp;
}
Stonewt Stonewt::operator -(const Stonewt& n1){
Stonewt tmp;
tmp.pounds = pounds - n1.pounds;
tmp.stone = tmp.pounds / Lbs_per_stn;
tmp.pds_left = int(tmp.pounds)%Lbs_per_stn + tmp.pounds - int(tmp.pounds);
return tmp;
}
Stonewt Stonewt::operator*(const double n) const{
Stonewt tmp;
tmp.pounds = pounds * n;
tmp.pds_left = int(tmp.pounds) % Lbs_per_stn + tmp.pounds - int(tmp.pounds);
tmp.stone = tmp.pounds / Lbs_per_stn;
return tmp;
}
测试文件
//
// main.cpp
// 11.5
//
// Created by apple on 2018/8/12.
// Copyright © 2018年 apple. All rights reserved.
//
#include <iostream>
using std::cout;
#include "stonewt.h"
void display(const Stonewt & st, int n){
for(int i =0 ; i < n; i++){
cout<<" Wow !";
// st.show_stn();
cout<<st<<std::endl;
}
}
int main(int argc, const char * argv[]) {
Stonewt incognito = 275;
Stonewt wolfe(285.7);
Stonewt taft(21,8);
Stonewt b(2,1.4);
double n = 2.8;
cout<<taft + b<<std::endl;
cout<<taft - b<<std::endl;
cout<<taft * n<<std::endl;
cout<<"The celebrity weighted.\n";
// incognito.show_stn();
cout<<incognito<<std::endl;
cout<<"The detective weigthed ";
// wolfe.show_stn();
cout<<wolfe<<std::endl;
cout<<"The president weighted ";
// taft.show_lbs();
cout<<taft<<std::endl;
incognito = 276.8;
taft = 325;
cout<<"After dinner, the celebrity weighted ";
// incognito.show_stn();
cout<<incognito<<std::endl;
cout<<"After dinner, the President weighted ";
// taft.show_lbs();
cout<<taft<<std::endl;
display(taft, 2);
cout<<"The wrestler weighted event more.\n";
display(422, 2);
cout<<"No stone left unearned\n";
return 0;
}
6.重新编写Stonewt类,重载全部6个关系运算符。运算符对pounds成员进行比较,并返回一个bool值。编写一个程序,它声明一个包含6个Stonewt对象的数组,并在数组声明中初始化前三个对象。然后使用循环来读取用于设置剩余3个数组元素的值。接着报告最小的元素,最大的元素以及大于或等于11英石的元素的数量
头文件
//
// stonewt.h
// 11.5
//
// Created by apple on 2018/8/12.
// Copyright © 2018年 apple. All rights reserved.
//
#ifndef stonewt_h
#define stonewt_h
class Stonewt{
private:
enum Mode{STO, POU, FLO};
Mode mode;
enum{Lbs_per_stn = 14}; //pounds per stone
int stone;
double pds_left;
double pounds;
public:
void sto_mode();
void pou_mode();
void flo_mode();
Stonewt(double lbs);
Stonewt(int stn, double lbs, Mode mode = FLO);
Stonewt();
~Stonewt();
Stonewt operator+(const Stonewt& n1);
Stonewt operator-(const Stonewt& n1);
Stonewt operator*(const double n) const;
bool operator >(const Stonewt &s);
bool operator <(const Stonewt &s);
bool operator ==(const Stonewt &s);
bool operator != (const Stonewt &s);
bool operator >= (const Stonewt &s);
bool operator <= (const Stonewt &s);
// void show_lbs() const;
// void show_stn() const;
friend std::ostream& operator<<(std::ostream &os, const Stonewt &s);
};
#endif /* stonewt_h */
头文件实现
//
// stonewt.cpp
// 11.5
//
// Created by apple on 2018/8/12.
// Copyright © 2018年 apple. All rights reserved.
//
#include <stdio.h>
#include <iostream>
using std::cout;
#include "stonewt.h"
Stonewt::Stonewt(double lbs){
stone = int(lbs) / Lbs_per_stn;
pds_left = int(lbs)%Lbs_per_stn + lbs - int(lbs);
pounds = lbs;
}
Stonewt::Stonewt(int stn, double lbs, Mode mode){
stone = stn;
pds_left = lbs;
pounds = stn * Lbs_per_stn + lbs;
}
Stonewt::Stonewt(){
stone = pounds = pds_left = 0;
}
Stonewt::~Stonewt(){
}
/*void Stonewt::show_stn() const{
cout<< stone<<" stone, "<< pds_left<<" pounds.\n";
}
void Stonewt::show_lbs() const{
cout<<pounds<<" pounds.\n";
}*/
void Stonewt::flo_mode(){
mode = FLO;
}
void Stonewt::pou_mode(){
mode = POU;
}
void Stonewt::sto_mode(){
mode = STO;
}
std::ostream& operator<<(std::ostream &os, const Stonewt &s){
if(s.mode == Stonewt::STO){
double temp;
temp = s.stone + s.pds_left / Stonewt::Lbs_per_stn;
os<<"Stone mode: "<<temp <<" stone" <<std::endl;
}
else if(s.mode == Stonewt::POU){
os<<"Integer pounds mode: "<<s.pounds <<" pounds."<<std::endl;
}
else if(s.mode == Stonewt::FLO){
os<<"Float pounds mode: "<< s.stone <<" stone," <<s.pds_left<<std::endl;
}
return os;
}
Stonewt Stonewt::operator+(const Stonewt& n1){
Stonewt tmp;
tmp.pounds = pounds + n1.pounds;
tmp.stone = tmp.pounds / Lbs_per_stn;
tmp.pds_left = int(tmp.pounds)%Lbs_per_stn + tmp.pounds - int(tmp.pounds);
return tmp;
}
Stonewt Stonewt::operator -(const Stonewt& n1){
Stonewt tmp;
tmp.pounds = pounds - n1.pounds;
tmp.stone = tmp.pounds / Lbs_per_stn;
tmp.pds_left = int(tmp.pounds)%Lbs_per_stn + tmp.pounds - int(tmp.pounds);
return tmp;
}
Stonewt Stonewt::operator*(const double n) const{
Stonewt tmp;
tmp.pounds = pounds * n;
tmp.pds_left = int(tmp.pounds) % Lbs_per_stn + tmp.pounds - int(tmp.pounds);
tmp.stone = tmp.pounds / Lbs_per_stn;
return tmp;
}
bool Stonewt::operator >(const Stonewt &s){
return pounds > s.pounds ? true : false;
}
bool Stonewt::operator <(const Stonewt &s){
return pounds < s.pounds ? true:false;
}
bool Stonewt::operator ==(const Stonewt &s){
return pounds == s.pounds ? true:false;
}
bool Stonewt::operator != (const Stonewt &s){
return pounds != s.pounds ? true:false;
}
bool Stonewt::operator >= (const Stonewt &s){
return pounds >= s.pounds ? true : false;
}
bool Stonewt::operator <= (const Stonewt &s){
return pounds <= s.pounds ? true:false;
}