- 修改书本例子程序‘随机漫步者’,使之记录位置到文件中,每个位置都用步号标示
Vector类声明头文件(此vector非彼vector,这个只是书本中例子自己定义的一个vector类)
#include <iostream>
namespace VECTOR
{
class Vector
{
public:
enum Mode
{
RECT,
POL
};
private:
double x;
double y;
double mag;
double ang;
Mode mode;
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();
//overloaded function
Vector operator+(const Vector &b) const;
Vector operator-(const Vector &b) const;
Vector operator-() const;
Vector operator*(double n) const;
//friend function
friend Vector operator*(double n, const Vector &a);
friend std::ostream &operator<<(std::ostream &os, const Vector &v);
};
} // namespace VECTOR
上面的声明及下面的函数声明在书本有实例,设计得很好了,不过最好自己敲一个对照一个加深印象。
vector类声明文件
#include <cmath>
#include "vector.h"
using std::atan;
using std::atan2;
using std::cos;
using std::cout;
using std::endl;
using std::sin;
using std::sqrt;
namespace VECTOR
{
const double rad_to_deg = 45.0 / atan(1.0);
void Vector::set_mag()
{
mag = sqrt(x * x + y * y);
}
void Vector::set_ang()
{
if (x == 0 && y == 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 interface
Vector::Vector()
{
x = y = mag = ang = 0.0;
mode = RECT;
}
Vector::Vector(double n1, double n2, Mode form)
{
mode = form;
if (mode == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (mode == POL)
{
mag = n1;
ang = n2;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector" << endl;
cout << "Argument of Vector set to 0 and mode set to RECT." << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
void Vector::reset(double n1, double n2, Mode form)
{
mode = form;
if (mode == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (mode == POL)
{
mag = n1;
ang = n2;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector" << endl;
cout << "Argument of Vector set to 0 and mode set to RECT." << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
Vector::~Vector()
{
}
void Vector::polar_mode()
{
mode = POL;
}
void Vector::rect_mode()
{
mode = RECT;
}
//overloaded function
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(x * n, y * n);
}
//friend function
Vector operator*(double n, const Vector &a)
{
return Vector(n * a.x, n * a.y);
}
std::ostream &operator<<(std::ostream &os, const Vector &v)
{
if (v.mode == Vector::RECT)
{
os << "(x,y)=(" << v.x << " ," << v.y << ")" << endl;
}
else if (v.mode == Vector::POL)
{
os << "(m,a)=(" << v.mag << " ," << v.ang << ")" << endl;
}
else
os << "Invalid mode of Vector object." << endl;
return os;
}
} // namespace VECTOR
原测试文件
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "vector.h"
using std::cin;
using std::cout;
using std::endl;
using VECTOR::Vector;
int main()
{
std::srand(time(0)); //randomly generated seed
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 the length of step:";
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:" << endl;
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." << endl;
cin.clear();
while (cin.get() != '\n')
continue;
system("pause");
return 0;
}
原测试程序测试结果
测试程序改动方案
#include<fstream>
...
ofstream ffile;
ffile.open("vector_test.txt");
ffile<<result<<endl;
ffile.close();
根据上面样式把需要输出的语句用ofstream对象ffile改写,并且事先在工作目录下编写一个"vector_test.txt"的样式文件(也可以是其他地方,不过要加上路径),不然就没有输出结果了。
进一步改进达到习题效果,就只需要在循环计数result和steps的while循环里面加上输出到文件的语句即可。如下:
#include<fstream>
...
ofstream ffile;
ffile.open("vector_test.txt");
...
ffile << "Target Distance: " << target << ", Step Size:" << dstep << endl;
ffile << "#" << int(steps) << ": " << result << endl;
while (result.magval() < target)
{
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result + step;
steps++;
ffile << "#" << int(steps) << ": " << result << endl;
}
...
ffile<<result<<endl;
ffile.close();
得到的效果就是这个了,还是很简单的。
- 对vector类头文件和实现文件进行修改,使其不再存储矢量的长度和角度,而是在调用magval()和angval()时计算他们,然后对修改后的版本进行测试。
......
void Vector::set_mag()
{
mag = 0.0;
}
void Vector::set_ang()
{
ang = 0.0;
}
......
double Vector::magval()
{
return mag = sqrt(x * x + y * y);
}
double Vector::angval()
{
if (x == 0 && y == 0)
return ang = 0.0;
else
return ang = atan2(y, x);
}
......
类函数实现我就做这样修改,并且在后面需要使用到mag和ang值时才调用magval()和angval()函数,也就是输出语句那里:
......
ffile << "After " << steps << " steps,the subject has the following location:" << endl;
ffile << result << endl;
result.polar_mode();
ffile << "or\n("
<< result.magval() << ", " << result.angval() << ")" << endl;
.......
然后就是这个效果(真想吐槽题目的不存储mag和ang值,搞得脑袋嗡嗡的)。
输入100distance和3步长,结果如下:
- 同上题,修改测试程序,要求输出n次测试中最高、最低和平均步数,不输出每次测试结果。这里的vector用回最初的类声明和实现。
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
#include "vector.h"
using std::cin;
using std::cout;
using std::endl;
using VECTOR::Vector;
const int test_n = 5;
int main()
{
std::srand(time(0)); //randomly generated seed
std::fstream ffile;
ffile.open("vector_test.txt");
double direction;
Vector step;
Vector result(0.0, 0.0);
long steps = 0;
double target;
double dstep;
long total = 0;
long steps_record[test_n];
int i = 0;
while (i != test_n)
{
cout << "Enter target distance (q to quit):";
if (!(cin >> target))
break;
cout << "Enter the length of step:";
if (!(cin >> dstep))
break;
ffile << "Target Distance: " << target << ", Step Size:" << dstep << endl;
while (result.magval() < target)
{
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result + step;
steps++;
}
steps_record[i] = steps;
ffile << "After " << steps << " steps,the subject has the following location:" << endl;
ffile << result;
result.polar_mode();
ffile << "or\n"
<< result;
ffile << "Average outward distance per step="
<< result.magval() / steps << endl;
ffile << endl;
i++;
steps = 0;
result.reset(0.0, 0.0);
}
long max = steps_record[0];
long min = steps_record[0];
for (int j = 0; j < i; j++)
{
max = (steps_record[j] > max) ? steps_record[j] : max;
min = (steps_record[j] > min) ? min : steps_record[j];
total += steps_record[j];
}
for (int z = 0; z < test_n; z++)
ffile << steps_record[z] << " ";
ffile << endl;
ffile << "The max of steps is:" << max << ",and the minimum is :" << min << endl;
ffile << "The average of all the steps is:" << double(total) / i << "." << endl;
ffile << "Bye." << endl;
cout << "Bye." << endl;
ffile.close();
cin.clear();
while (cin.get() != '\n')
continue;
system("pause");
return 0;
}
思路很简单,把原本输出每次测试结果的语句删掉,然后用一个数组进行每次测试的步数的记录,后面再进行比较输出,为了验证结果正确性,保留了原本的部分输出,所以语句很胖!将就一下吧。
我在即将满5次测试的时候退出了,检验可行性,结果如下:
- 重写书中time类,用友元函数实现所有的重载运算符
time类声明头文件
#include <iostream>
class time
{
private:
int hours;
int minutes;
public:
time();
time(int h, int m = 0);
void Addmin(int m);
void Addhour(int h);
void reset(int h = 0, int m = 0);
//friend function
friend time operator+(const time &m, const time &n);
friend time operator-(const time &m, const time &n);
friend time operator*(double m, const time &n);
friend time operator*(const time &n, double m);
friend std::ostream &operator<<(std::ostream &os, const time &t);
};
time类实现cpp文件
#include "time.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::Addhour(int h)
{
hours += h;
}
void time::reset(int h, int m)
{
hours = h;
minutes = m;
}
//friend function
time operator+(const time &m, const time &n)
{
time temp;
temp.minutes = m.minutes + n.minutes;
temp.hours = m.hours + n.hours + temp.minutes / 60;
temp.minutes %= 60;
return temp;
}
time operator-(const time &m, const time &n)
{
time temp;
int t1, t2;
t1 = m.minutes + m.hours * 60;
t2 = n.minutes + n.hours * 60;
temp.minutes = (t1 - t2) % 60;
temp.hours = (t1 - t2) / 60;
return temp;
}
time operator*(double m, const time &t)
{
time temp;
int total;
total = t.minutes * m + t.hours * m * 60;
temp.minutes = total % 60;
temp.hours = total / 60;
return temp;
}
time operator*(const time &t, double m)
{
time temp;
int total;
total = t.minutes * m + t.hours * m * 60;
temp.minutes = total % 60;
temp.hours = total / 60;
return temp;
}
std::ostream &operator<<(std::ostream &os, const time &t)
{
os << "time(h,m):" << t.hours << ":" << t.minutes << std::endl;
return os;
}
测试程序
#include <iostream>
#include "time.h"
using std::cin;
using std::cout;
using std::endl;
int main()
{
time a(3, 35);
time b(2, 48);
time temp_;
cout << "a and b:" << endl;
cout << a << ";" << b << endl;
temp_ = a + b;
cout << "a+b=" << temp_ << endl;
temp_ = a * 2.3;
cout << "a*2.3=" << temp_ << endl;
temp_ = 3.4 * b;
cout << "3.4*b=" << temp_ << endl;
system("pause");
return 0;
}
代码就用书本里面的就行了,稍微改一下数字
- 重写书本中stonewt类,加上一个状态成员,由其控制对象应转换成英石格式、整数磅格式还是浮点磅格式;另外重载<<运算符,重载加法、减法和乘法运算符,最后编写一个测试程序。
声明头文件
#include <iostream>
namespace Stonewt
{
class stonewt
{
public:
enum form
{
STO,
POUND,
POUNDF
};
private:
enum
{
Lbs_per_stn = 14
};
form ft;
double stone; //stones
double pounds; //fractional pounds
int pounds_I; //integral pounds
void set_stone();
void set_pounds();
void set_pounds_I();
public:
stonewt(double s, form ft = STO);
stonewt(); //default constructor
~stonewt();
void stone_mode() { ft = STO; }
void pound_mode() { ft = POUNDF; }
void poundi_mode() { ft = POUND; }
stonewt operator+(const stonewt &s) const;
stonewt operator-(const stonewt &s) const;
stonewt operator-() const;
stonewt operator*(double n) const;
//friend function
friend stonewt operator*(double n, const stonewt &s);
friend std::ostream &operator<<(std::ostream &os, const stonewt &s1);
};
} // namespace Stonewt
成员函数实现源文件
#include "stonewt.h"
using std::cout;
using std::endl;
namespace Stonewt
{
void stonewt::set_stone()
{
stone = pounds * Lbs_per_stn;
}
void stonewt::set_pounds()
{
pounds = stone / Lbs_per_stn;
}
void stonewt::set_pounds_I()
{
pounds_I = int(stone) / Lbs_per_stn;
}
//publice methods
stonewt::stonewt(double s, form f)
{
ft = f;
if (f == STO)
{
stone = s;
set_pounds();
set_pounds_I();
}
else if (f == POUNDF)
{
pounds = s;
set_stone();
set_pounds_I();
}
else
{
cout << "It is not valid for this." << endl;
stone = pounds = 0.0;
pounds_I = 0;
ft = STO;
}
} //constructor for double pounds
stonewt::stonewt()
{
stone = pounds = 0.0;
pounds_I = 0;
ft = STO;
} //default constructor
stonewt::~stonewt()
{
}
//friend function
stonewt stonewt::operator*(double n) const
{
return stonewt(n * stone);
}
stonewt stonewt::operator+(const stonewt &s) const
{
return stonewt(stone + s.stone);
}
stonewt stonewt::operator-(const stonewt &s) const
{
return stonewt(stone - s.stone);
}
stonewt stonewt::operator-() const
{
return stonewt(-stone);
}
stonewt operator*(double n, const stonewt &s)
{
return s * n;
}
std::ostream &operator<<(std::ostream &os, const stonewt &s1)
{
if (s1.ft == stonewt::STO)
os << "The weight is :" << s1.stone << " stones." << endl;
else if (s1.ft == stonewt::POUNDF)
os << "The weight is :" << s1.pounds << " pounds." << endl;
else if (s1.ft == stonewt::POUND)
os << "The weight is :" << s1.pounds_I << " pounds." << endl;
else
os << "Invalid object." << endl;
return os;
}
} // namespace Stonewt
测试程序
#include <iostream>
#include "stonewt.h"
using std::cin;
using std::cout;
using std::endl;
using namespace Stonewt;
int main()
{
stonewt s1(10);
stonewt s2(14.5);
stonewt s, total;
cout << s1 << s2 << s << total << endl;
s = s1 + s2;
total = s2 - s1;
cout << s1 << s2 << s << total << endl;
s = 2.3 * s1;
total = s2 * 2.3;
cout << s1 << s2 << s << total << endl;
system("pause");
return 0;
}
反思:一开始我是直接对乘法运算法进行重载的,但当我发现(sx2.3)这样的语句被标错后,我就开始修改,加了个成员函数的重载,友元可以调换前后顺序使用乘法运算符;这里要注意,在友元的定义中return s*n的顺序不能反过来,因为这里是其实是把乘法工作交给了成员函数的乘法重载,如果反过来就会出错,不过你不用这个语句可以进行计算返回对象也可以。
另外有一个地方就是,上面的各种运算符重载,我选用的是比较简单的return和构造函数构成,所以就算测试程序里面进行了状态转换,也会因为这里的重载函数里面调用的构造函数重新置换默认状态STO
#include <iostream>
#include "stonewt.h"
using std::cin;
using std::cout;
using std::endl;
using namespace Stonewt;
int main()
{
stonewt s1(10);
stonewt s2(14.5);
stonewt s, total;
cout << s1 << s2 << s << total << endl;
s = s1 + s2;
total = s2 - s1;
cout << s1 << s2 << s << total << endl;
s.pound_mode();
total.pound_mode();
cout << s1 << s2 << s << total << endl;
s = 2.3 * s1;
total = s2 * 2.3;
cout << s1 << s2 << s << total << endl;
system("pause");
return 0;
}
就像上面这个例子这样,我的预计解决方案是:在函数重载中添加条件,根据状态成员进行换算,这里我犯懒了,希望看官留个心眼自己上手一遍,告诉我可不可行就ok.
- 重载6个关系运算符,对pounds成员进行比较,返回bool值,测试程序包含6个stonewt对象的数组,初始化前三个,后面的循环读取。最后分别报告最小最大的元素以及大于11英石的元素数量。
声明头文件
#include <iostream>
namespace Stonewt
{
class stonewt
{
public:
enum form
{
STO,
POUND,
POUNDF
};
private:
enum
{
Lbs_per_stn = 14
};
form ft;
double stone; //whole stones
double pounds; //fractional pounds
int pounds_I; //integral pounds
void set_stone();
void set_pounds();
void set_pounds_I();
public:
stonewt(double s, form ft = STO);
stonewt(); //default constructor
~stonewt();
void stone_mode() { ft = STO; }
void pound_mode() { ft = POUNDF; }
void poundi_mode() { ft = POUND; }
stonewt operator+(const stonewt &s) const;
stonewt operator-(const stonewt &s) const;
stonewt operator-() const;
stonewt operator*(double n) const;
//friend function
friend stonewt operator*(double n, const stonewt &s);
friend std::ostream &operator<<(std::ostream &os, const stonewt &s1);
//overloading relational function
friend bool operator<(const stonewt &s1, const stonewt &s2);
friend bool operator>(const stonewt &s1, const stonewt &s2);
friend bool operator<=(const stonewt &s1, const stonewt &s2);
friend bool operator>=(const stonewt &s1, const stonewt &s2);
friend bool operator==(const stonewt &s1, const stonewt &s2);
friend bool operator!=(const stonewt &s1, const stonewt &s2);
};
} // namespace Stonewt
成员函数实现文件
#include "stonewt.h"
using std::cout;
using std::endl;
namespace Stonewt
{
void stonewt::set_stone()
{
stone = pounds * Lbs_per_stn;
}
void stonewt::set_pounds()
{
pounds = stone / Lbs_per_stn;
}
void stonewt::set_pounds_I()
{
pounds_I = int(stone) / Lbs_per_stn;
}
//publice methods
stonewt::stonewt(double s, form f)
{
ft = f;
if (f == STO)
{
stone = s;
set_pounds();
set_pounds_I();
}
else if (f == POUNDF)
{
pounds = s;
set_stone();
set_pounds_I();
}
else
{
cout << "It is not valid for this." << endl;
stone = pounds = 0.0;
pounds_I = 0;
ft = STO;
}
} //constructor for double pounds
stonewt::stonewt()
{
stone = pounds = 0.0;
pounds_I = 0;
ft = STO;
} //default constructor
stonewt::~stonewt()
{
}
//friend function
stonewt stonewt::operator*(double n) const
{
return stonewt(n * stone);
}
stonewt stonewt::operator+(const stonewt &s) const
{
return stonewt(stone + s.stone);
}
stonewt stonewt::operator-(const stonewt &s) const
{
return stonewt(stone - s.stone);
}
stonewt stonewt::operator-() const
{
return stonewt(-stone);
}
stonewt operator*(double n, const stonewt &s)
{
return s * n;
}
std::ostream &operator<<(std::ostream &os, const stonewt &s1)
{
if (s1.ft == stonewt::STO)
os << "The weight is :" << s1.stone << " stones." << endl;
else if (s1.ft == stonewt::POUNDF)
os << "The weight is :" << s1.pounds << " pounds." << endl;
else if (s1.ft == stonewt::POUND)
os << "The weight is :" << s1.pounds_I << " pounds." << endl;
else
os << "Invalid object." << endl;
return os;
}
//overloading of relational operators
bool operator<(const stonewt &s1, const stonewt &s2)
{
return (s1.stone < s2.stone) ? true : false;
}
bool operator>(const stonewt &s1, const stonewt &s2)
{
return (s1.stone > s2.stone) ? true : false;
}
bool operator<=(const stonewt &s1, const stonewt &s2)
{
return (s1.stone <= s2.stone) ? true : false;
}
bool operator>=(const stonewt &s1, const stonewt &s2)
{
return (s1.stone >= s2.stone) ? true : false;
}
bool operator==(const stonewt &s1, const stonewt &s2)
{
return (s1.stone == s2.stone) ? true : false;
}
bool operator!=(const stonewt &s1, const stonewt &s2)
{
return (s1.stone != s2.stone) ? true : false;
}
} // namespace Stonewt
测试程序
#include <iostream>
#include "stonewt.h"
using std::cin;
using std::cout;
using std::endl;
using namespace Stonewt;
int main()
{
int count = 0;
stonewt stand(11);
stonewt p[6] = {(8), (9), (20)};
stonewt max, min;
max = min = p[0];
double choice[3] = {3.4, 9.8, 19.8};
for (int i = 0; i < 3; i++)
p[i + 3] = choice[i];
for (int j = 0; j < 6; j++)
{
max = (max > p[j]) ? max : p[j];
min = (min < p[j]) ? min : p[j];
if (p[j] >= stand)
count++;
}
cout << "Max:" << endl;
cout << max;
cout << "Min:" << endl;
cout << min;
cout << "The number of stones with weight greater than or equal to 11 stone is:" << count << " ." << endl;
system("pause");
return 0;
}
一个测试我就不搞那么复杂了,证明简单可行就结束了,如果后面发现有问题请评论留言。
7.定义复数类,并使之实现简单复数计算和显示
复数类声明头文件
#include <iostream>
class plurality
{
private:
double x;
double y;
public:
plurality();
plurality(double m, double n=0.0);
~plurality();
//overloading arithmetic operators
//operations between complex numbers
plurality operator+(const plurality &s) const;
plurality operator-(const plurality &s) const;
plurality operator*(const plurality &s) const;
//operations between complex numbers and real numbers
plurality operator-() const;
plurality operator-(double n) const;
plurality operator+(double n) const;
plurality operator*(double n) const;
//friend function
friend plurality operator*(double n, const plurality &s);
friend std::ostream operator<<(std::ostream &os, const plurality &s);
friend std::istream &operator>>(std::istream &is, plurality &s);
};
成员函数实现
#include "plurality.h"
using std::cin;
using std::cout;
using std::endl;
plurality::plurality()
{
x = y = 0.0;
}
plurality::plurality(double m, double n)
{
x = m;
y = n;
}
plurality::~plurality()
{
}
//overloading arithmetic operators
//operations between complex numbers
plurality plurality::operator+(const plurality &s) const
{
return plurality(x + s.x, y + s.y);
}
plurality plurality::operator-(const plurality &s) const
{
return plurality(x - s.x, y - s.y);
}
plurality plurality::operator*(const plurality &s) const
{
return plurality(x * s.x - y * s.y, x * s.y + y * s.x);
}
//operations between complex numbers and real numbers
plurality plurality::operator-() const
{
return plurality(x, -y);
}
plurality plurality::operator-(double n) const
{
return plurality(x - n, y);
}
plurality plurality::operator+(double n) const
{
return plurality(x - n, y);
}
plurality plurality::operator*(double n) const
{
return plurality(n * x, n * y);
}
//friend function
plurality operator*(double n, const plurality &s)
{
return s * n;
}
std::ostream &operator<<(std::ostream &os, const plurality &s)
{
os << "(" << s.x << " ," << s.y << "i)" << endl;
return os;
}
std::istream &operator>>(std::istream &is, plurality &s)
{
cout << "Real:";
is >> s.x;
if (!is)
return is;
cout << "Imaginary:";
is >> s.y;
cin.get();
return is;
}
测试程序是书本的简单程序
#include <iostream>
#include "plurality.h"
using std::cin;
using std::cout;
using std::endl;
int main()
{
plurality a(3, 4);
plurality c;
cout << "Please enter the plurality (q to quit):" << endl;
while (cin >> c)
{
cout << "c is " << c << endl;
cout << "Conjugate plurality is " << -c << endl;
cout << "a is " << a << endl;
cout << "a+c=" << a + c << endl;
cout << "a-c=" << a - c << endl;
cout << "a*c=" << a * c << endl;
cout << "2*c=" << 2 * c << endl;
cout << "Please enter the plurality (q to quit):" << endl;
}
cout << "Bye." << endl;
system("pause");
return 0;
}
在这里,强烈建议大家重载>>运算法时声明const复数对象,会很有趣哦。