C++ Primier Plus(第六版) 第十一章 使用类 编程练习答案

1. 修改程序清单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.6794, -89.7309)
After 27 steps, the subject has the following location:
(x,y) = (58.6749, -89.7309)
or
(m,a) = (107.212, -56.8194)
本题比较容易,重新帮助熟练程序写入文件。vector.h和vector.cpp本章里都有,主函数的程序如下:

// ex1.cpp -- walk random problem
// compile with vector.cpp
#include <fstream>
#include <cstdlib>  // rand(), srand() protypes
#include <ctime> 	// time() protype
#include "vector.h"

int main()
{
	using namespace std;
	using VECTOR::Vector;
//	write in file
	ofstream fout;
	fout.open("walk_random.txt");

	srand(time(0));			//generate a seed of random
	double target;
	double dstep;
	unsigned long steps = 0;
	Vector step;
	Vector result(0.0,0.0);
	cout << "Enter the Target Distance(enter q to quit): ";
	while(cin >> target)
	{
		cout << "Enter the distance of every step: ";
		while(!(cin >> dstep))
		{
			cin.clear();
			while(cin.get() != '\n')
				continue;
			cout << "Bad input, please enter a double value: ";
		}

		fout << "Target Distance: " << target << ", Step Size: " << dstep << endl;
		while(result.mag_val() < target)
		{
			step.reset(dstep, rand() % 360, Vector::POL);
			step.rect_mode();
			fout << steps << ": " << step << endl;
			result = result + step;
			steps++;
		}
		fout << "After " << steps << " steps, the subject has the following location:\n";
		fout << result << endl;
		fout << "or\n";
		result.polar_mode();
		fout << result << endl;
		fout << "Average outward distance per step = " << result.mag_val() / steps << endl;
		cout << "Enter next Target Distance(enter q to quit): ";
	}
	fout.close();
	cout << "Bye\n";
	return 0;
}

运行结果如下:
image
生成的文件如下:
image

2. 对Vector类的头文件(程序清单11.13)和实现文件(程序清单11.14进行修改),使其不再存储矢量的长度和角度,而是在magval()和angvel()被调用时计算它们。
应保留公有接口不变(公有方法及其参数不变),但对私有部分,包括一些私有方法和实现进行修改。然后使用程序清单11.15对修改后的版本进行测试,结果应该与以前相同,因为Vector类的公有接口与原来的相同。
本题首先修改vector.h,将私有成员mag和ang删除,四个set函数删除,接着修改构造函数和reset()函数,修改完之后修改magval()和angvel()函数,最后修改一下友元输出函数,代码如下:

// vector1.h -- Vector class with <<, mode state
// store Vector use x and y
#ifndef VECTOR1_H_
#define VECTOR1_H_
#include <iostream>
namespace VECTOR
{
    class Vector
    {
    public:
        enum Mode{RECT, POL};
    // RECT for rectangular, POL for Polar modes
    private:
        double x;
        double y;
        Mode mode;
    // private methods for setting values;
    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;
        double angval() const;
        void polar_mode();                  // set mode to POL
        void rect_mode();                   // set mode to RECT
    // oprator 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, const Vector & a);
        friend std::ostream & 
                operator<<(std::ostream & os, const Vector & v);
    };
}   // end namespace VECTOR

#endif
// vector1.cpp -- methods for the Vector class
#include <cmath>
#include "vector1.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);
    // should be about 57.2957795130823

    Vector::Vector()
    {
        x = y = 0;
        mode = RECT;
    }

    Vector::Vector(double n1, double n2, Mode form )
    {
        mode = form;
        if(mode == RECT)
        {
            x = n1;
            y = n2;
        }
        else if(mode == POL)
        {
            double ang = n2 / Rad_to_deg;
            x = n1 * cos(ang);
            y = n1 * sin(ang);
        }
        else
        {
            cout << "Incorrect 3rd argument to Vector() --";
            cout << "vector set to 0\n";
            x = y = 0;
            mode = RECT;
        }
    }

    // reset vector from rectangular cooridinates if form is
    // RECT (the default) or else from polar coordinates if
    // form is POL
    void Vector::reset(double n1, double n2, Mode form)
    {
        mode = form;
        if(mode == RECT)
        {
            x = n1;
            y = n2;
        }
        else if(mode == POL)
        {
            double ang = n2 / Rad_to_deg;
            x = n1 * cos(ang);
            y = n1 * sin(ang);
        }
        else
        {
            cout << "Incorrect 3rd argument to Vector() --";
            cout << "vector set to 0\n";
            x = y = 0;
            mode = RECT;
        }
    }

    Vector::~Vector()               // destructor
    {
    }

    double Vector::magval() const
    {
        return sqrt(x * x + y * y);
    }

    double Vector::angval() const
    {
        if(x == 0.0 && y == 0.0)
            return 0;
        else
            return atan2(y,x);
    }

    void Vector::polar_mode()       // set to polar mode
    {
        mode = POL;
    }

    void Vector::rect_mode()        // set to rect mode
    {
        mode = RECT;
    }

    // operator overloading
    // add two Vectors
    Vector Vector::operator+(const Vector & b) const
    {
        return Vector(x + b.x, y + b.y);
    }

    // subtract Vector b from a
    Vector Vector::operator-(const Vector & b) const
    {
        return Vector(x - b.x, y - b.y);
    }

    // reverse sign of Vector
    Vector Vector::operator-() const
    {
        return Vector(-x, -y);
    }

    // multiply vector by n
    Vector Vector::operator*(double n) const 
    {
        return Vector(n * x, n * y);
    }

    // friend methods
    // mutiply n by Vector a
    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.magval() << ", " << v.angval() * Rad_to_deg << ")";
        }
        else
            os << "Vector object mode is invalid";
        return os;
    }

}       // end namespace VECTOR

运行结果如下:
image
3. 修改程序清单11.15,使之报告N次测试中的最高、最低和平均步数(其中N是用户输入的整数),而不是报告每次的结果。
本题首先要定义一个数组,存储每次实验的结果,然后再写三个函数,计算数组的平均值、最小值和最大值,利用一个循环执行输入times次数的实验,注意需要初始化result,代码如下:

// ex3.cpp -- rand walk problem
// compile with the vect.cpp file
#include <cstdlib>  // rand(), srand() protypes
#include <ctime>    // time() protype
#include "vector1.h"
unsigned long average(unsigned long arr[],int n);
unsigned long findmax(unsigned long arr[],int n);
unsigned long findmin(unsigned long arr[],int n);
int main()
{
    using namespace std;
    using VECTOR::Vector;
    srand(time(0));     // seed random-number generator
    double direction;
    Vector step;
    Vector result(0.0, 0.0);
    double target;
    double dstep;
    int times;
    cout << "Enter target distance: ";
    cin >> target;
    cout << "Enter step length: ";
    cin >> dstep;
    cout << "Enter the times you want to test: ";
    cin >> times;
    unsigned long steps[times];
    for(int i = 0; i < times; i++)
    {
        // initialize and reset result to 0
        steps[i] = 0;
        result.reset(0.0, 0.0); // is necessary

        while(result.magval() < target)
        {
            direction = rand() % 360;
            step.reset(dstep, direction, Vector::POL);
            result = result + step;
            steps[i]++;
        }
    }
    unsigned long steps_max = findmax(steps, times);
    unsigned long steps_min = findmin(steps, times);
    unsigned long steps_ave = average(steps, times);

    cout << "After " << times << " times test:\n";
    cout << "Maximum steps is " << steps_max << endl;
    cout << "Minimun steps is " << steps_min << endl;
    cout << "Average steps is " << steps_ave << endl;
    cout << "Bye!\n";
    cin.clear();
    while(cin.get() != '\n')
        continue;
    return 0;
}

unsigned long average(unsigned long arr[],int n)
{
    unsigned long long sum = 0;
    for(int i = 0; i < n; i++)
    {
        sum += arr[i];
    }
    return sum / n;
}

unsigned long findmax(unsigned long arr[],int n)
{
    unsigned long max = 0;
    for(int i = 0; i < n; i++)
        max = max < arr[i] ? arr[i] : max;
    return max;
}

unsigned long findmin(unsigned long arr[],int n)
{
    unsigned long min = arr[0];
    for(int i = 0; i < n; i++)
        min = min < arr[i] ? min : arr[i];
    return min;
}

运行结果如下:
image
可以看到结果接近100/2的平方,因此是正确的。
4. 重新编写最后的Time类示例(程序清单11.10、程序清单11.11和程序清单11.12),使用友元函数来实现所有的重载运算符。
本题不算难,需要注意的是由于函数到了类外,因此函数不能声明为const的函数。需要修改程序11.10和程序11.11,类使用程序无需修改,程序如下:

// mytime.h -- Time class operator * and << overloading
#ifndef MYTIME_H_
#define MYTIME_H_

#include <iostream>
class Time
{
private:
    int hours;
    int minutes;
public:
    Time();
    Time(int h, int m = 0);
    void AddMin(int m);
    void AddHr(int h);
    void Reset(int h = 0, int m = 0);
    // friend
    friend Time operator+(const Time & t1, const Time & t2);
    friend Time operator-(const Time & t1, const Time & t2);
    friend Time operator*(const Time & t, double n);
    friend Time operator*(double n, const Time & t) {return t * n;}
    friend std::ostream & operator<<(std::ostream & os,const Time & t);
};
#endif
// mytime.cpp -- implementing Time methods
#include <iostream>
#include "mytime.h"

Time::Time()
{
    hours = minutes = 0;
}

Time::Time(int h, int m)
{
    hours = h;
    minutes = m;
}

void Time::AddMin(int m)
{
    minutes += m;
    if(minutes > 60)
    {
        hours += minutes / 60;
        minutes %= 60;
    }
}

void Time::AddHr(int h)
{
    hours += h;
}

Time operator+(const Time & t1, const Time & t2) 
{
    Time sum;
    sum.hours = t1.hours;
    sum.minutes = t2.minutes;
    sum.AddMin(t2.minutes);
    sum.AddHr(t2.hours);
    return sum;
}

Time operator-(const Time & t1, const Time & t2)
{
    Time diff;
    diff.minutes = t1.minutes - t2.minutes;
    diff.hours = t1.hours - t2.hours;
    if(diff.minutes < 0)
    {
        diff.minutes = 60 - diff.minutes;
        diff.hours -= 1;
    }
    return diff;
}

Time operator*(const Time & t, double n)
{
    Time result;
    long totalminutes = (t.hours * 60 + t.minutes) * n;
    result.minutes = totalminutes % 60;
    result.hours = totalminutes / 60;
    return result;
}

std::ostream & operator<<(std::ostream & os,const Time & t)
{
    os << t.hours << " hours, " << t.minutes << " minutes";
    return os;  // is necessary
}
// usetime3_11_12.cpp -- using the third draft of the Time class
// compile usetime3.cpp and mytime0.cpp together
#include "mytime.h"

int main()
{
    using std::cout;
    using std::cin;
    using std::endl;
    Time weeding(4,35);
    Time waxing(2,47);
    Time total,diff,adjusted;
    cout << "weeding time = " << weeding << endl;
    
    cout << "waxing time = " << waxing << endl;

    total = weeding + waxing;
    cout << "total work time = " << total << endl;

    diff = weeding - waxing;
    cout << "weeding time - waxing time = " << diff << endl;

    adjusted = 1.5 * total;
    cout << "adjusted work time = " << adjusted << endl;

    return 0;
}

运行结果如下:
image
5. 重新编写Stonewt类(程序清单11.16和程序清单11.17),使它有一个状态成员,由该成员控制对象应转换为英石格式、整数磅格式还是浮点磅格式。重载<<运算符,使用它来替换show_stn()和show_lbs()方法。重载加法、减法和乘法运算符,以便可以对Stonewt值进行加、减、乘运算。编写一个使用所有类的小程序,来测试这个类。
本题有两种方式修改,一种是存储时,三种格式的数据都存储,利用mode来区分,需要那种格式的数据以对象成员调用即可;另一种方式是只选择一种格式存储,需要其他格式时,利用计算函数计算值返回。笔者采用的是第二种格式,编写过程中,构造函数遇到了问题,默认参数没有使用,导致出现了输出格式不正确的问题,加了mode = form之后解决,样例代码如下:

// stonewt.h -- definetion for the Stonewt class
#ifndef STONEWT_H_
#define STONEWT_H_
#include <iostream>

using std::ostream;
class Stonewt
{
    public:
    enum MODE {STONE, POUNDS, INT_POUNDS};
    private:
        enum{Lbs_per_stn = 14};     // pounds per stone
        double pounds;              // entire weight in pounds
        MODE mode;
    public:
        Stonewt(double lbs, MODE form = POUNDS);
        Stonewt(int stn, double lbs, MODE form = STONE);
        Stonewt(int lbs, MODE form = INT_POUNDS);
        Stonewt();
        ~Stonewt();
        //get value
        int stone_val() const;
        double pds_left_val() const;
        double pounds_val() const;
        int int_pounds_val() const;

        // set mode
        void pounds_mode();
        void int_pounds_mode();
        void stone_mode();


        // operator + - *
        Stonewt operator+(const Stonewt & st) const;
        Stonewt operator-(const Stonewt & st) const;
        Stonewt operator*(double n) const;
    //friend
        // operator*
        friend Stonewt operator*(double n, const Stonewt & st);

        //operator<<
        friend ostream & operator<<(ostream & os, const Stonewt & st);
};
#endif
// stonewt.cpp -- Stonewt methods
#include "stonewt.h"


// construct Stonewt object from double value
Stonewt::Stonewt(double lbs, MODE form)
{
    mode = form;        // is necessary
    pounds = lbs;
}

// construct Stonewt object from stone, double values
Stonewt::Stonewt(int stn, double lbs, MODE form)
{
    mode = form;
    pounds = stn * Lbs_per_stn + lbs;
}

// construct Stonewt object form int pounds vlaue
Stonewt::Stonewt(int lbs, MODE form)
{
    mode = form;
    pounds = double(lbs);
}

// default constructor, wt = 0
Stonewt::Stonewt()
{
    pounds = 0;
}

Stonewt::~Stonewt()         // destructor
{
}
// get value
int Stonewt::stone_val() const
{
    return int(pounds) / Lbs_per_stn; 
}

double Stonewt::pds_left_val() const
{
    return int(pounds) % Lbs_per_stn + pounds -int(pounds);
}

double Stonewt::pounds_val() const
{
    return pounds;
}

int Stonewt::int_pounds_val() const
{
    return int(pounds);
}

// set mode
void Stonewt::pounds_mode()
{
    mode = POUNDS;
}

void Stonewt::int_pounds_mode()
{
    mode = INT_POUNDS;
}

void Stonewt::stone_mode()
{
    mode = STONE;
}

// operator + - *
Stonewt Stonewt::operator+(const Stonewt & st) const
{
    return Stonewt(pounds + st.pounds);
}

Stonewt Stonewt::operator-(const Stonewt & st) const
{
    return Stonewt(pounds - st.pounds);
}

Stonewt Stonewt::operator*(double n) const
{
    return Stonewt(n * pounds);
}

// friend
Stonewt operator*(double n, const Stonewt & st)
{
    return st * n;
}

ostream & operator<<(ostream & os, const Stonewt & st)
{
    Stonewt::MODE mode;
    mode = st.mode;
    switch (mode)
    {
    case Stonewt::POUNDS: 
            os << "Double pounds: " << st.pounds << " pounds";
            break;
    case Stonewt::STONE:
            os << "Stone: " <<st.stone_val() << " stone, " << st.pds_left_val() << " pounds";
            break;
    case Stonewt::INT_POUNDS:
            os << "Int pounds: " << st.int_pounds_val() << " pounds";
            break;
    default:
            os << "Stonewt object mode is invalid";
            break;
    }
}

// ex5_main.cpp -- test the Stonewt class
// compile with stonewt.cpp
#include "stonewt.h"

int main()
{
	using std::cin;
	using std::cout;
	using std::endl;
	double pounds;
	int number;			// the number of egg
	Stonewt egg;
	Stonewt weight;
	egg = Stonewt(15.0);
	cout << "Enter your weight in pounds: ";
	cin >> pounds;
	weight = Stonewt(pounds);
	cout << "Before ate eggs, your weight:\n";
	cout << weight << endl;
	cout << "Enter the number of egg you eat: ";
	cin >> number;
	cout << "After ate " << number << " eggs, your weight:\n";
	weight = weight + number * egg;
	cout << weight << endl;
	weight.stone_mode();
	cout << weight << endl;
	weight.int_pounds_mode();
	cout << weight << endl;
	return 0;
}

运行结果如下:
image
6. 重新编写Stonewt类(程序清单11.16和程序清单11.17),重载全部6个关系运算符。运算符对pounds成员进行比较,并返回一个bool值。编写一个程序,它声明一个包含6个Stonewt对象的数组,并在数组声明中初始化前三个对象,然后,使用循环来读取用于设置剩余三个数组元素的值。接着报告最小的元素,最大的元素,以及大于或等于11英石元素的数量(最简单的方法是创建一个Stonewt对象,并将其初始化为11英石,然后同其他对象进行比较)
本题考查的重载运算符函数的知识,可以采用友元函数或者成员函数进行重载,笔者采用了友元函数重载的方式,代码如下:

// stonewt.h -- definetion for the Stonewt class
#ifndef STONEWT_H_
#define STONEWT_H_
#include <iostream>

using std::ostream;
class Stonewt
{
    public:
    enum MODE {STONE, POUNDS, INT_POUNDS};
    private:
        enum{Lbs_per_stn = 14};     // pounds per stone
        double pounds;              // entire weight in pounds
        MODE mode;
    public:
        Stonewt(double lbs, MODE form = POUNDS);
        Stonewt(int stn, double lbs, MODE form = STONE);
        Stonewt(int lbs, MODE form = INT_POUNDS);
        Stonewt();
        ~Stonewt();
        //get value
        int stone_val() const;
        double pds_left_val() const;
        double pounds_val() const;
        int int_pounds_val() const;

        // set mode
        void pounds_mode();
        void int_pounds_mode();
        void stone_mode();


        // operator + - *
        Stonewt operator+(const Stonewt & st) const;
        Stonewt operator-(const Stonewt & st) const;
        Stonewt operator*(double n) const;

    //friend
        // operator*
        friend Stonewt operator*(double n, const Stonewt & st);

        // oprator == != < > <= >=
        friend bool operator==(const Stonewt & st1, const Stonewt & st2);
        friend bool operator!=(const Stonewt & st1, const Stonewt & st2);
        friend bool operator>(const Stonewt & st1, const Stonewt & st2);
        friend bool operator<(const Stonewt & st1, const Stonewt & st2);
        friend bool operator<=(const Stonewt & st1, const Stonewt & st2);
        friend bool operator>=(const Stonewt & st1, const Stonewt & st2);
        //operator<<
        friend ostream & operator<<(ostream & os, const Stonewt & st);
};
#endif
// stonewt.cpp -- Stonewt methods
#include "stonewt.h"


// construct Stonewt object from double value
Stonewt::Stonewt(double lbs, MODE form)
{
    mode = form;        // is necessary
    pounds = lbs;
}

// construct Stonewt object from stone, double values
Stonewt::Stonewt(int stn, double lbs, MODE form)
{
    mode = form;
    pounds = stn * Lbs_per_stn + lbs;
}

// construct Stonewt object form int pounds vlaue
Stonewt::Stonewt(int lbs, MODE form)
{
    mode = form;
    pounds = double(lbs);
}

// default constructor, wt = 0
Stonewt::Stonewt()
{
    pounds = 0;
}

Stonewt::~Stonewt()         // destructor
{
}
// get value
int Stonewt::stone_val() const
{
    return int(pounds) / Lbs_per_stn; 
}

double Stonewt::pds_left_val() const
{
    return int(pounds) % Lbs_per_stn + pounds -int(pounds);
}

double Stonewt::pounds_val() const
{
    return pounds;
}

int Stonewt::int_pounds_val() const
{
    return int(pounds);
}

// set mode
void Stonewt::pounds_mode()
{
    mode = POUNDS;
}

void Stonewt::int_pounds_mode()
{
    mode = INT_POUNDS;
}

void Stonewt::stone_mode()
{
    mode = STONE;
}

// operator + - *
Stonewt Stonewt::operator+(const Stonewt & st) const
{
    return Stonewt(pounds + st.pounds);
}

Stonewt Stonewt::operator-(const Stonewt & st) const
{
    return Stonewt(pounds - st.pounds);
}

Stonewt Stonewt::operator*(double n) const
{
    return Stonewt(n * pounds);
}

// friend
Stonewt operator*(double n, const Stonewt & st)
{
    return st * n;
}

bool operator==(const Stonewt & st1, const Stonewt & st2)
{
    return st1.pounds == st2.pounds ? true : false;
}
bool operator!=(const Stonewt & st1, const Stonewt & st2)
{
    return st1.pounds != st2.pounds ? true : false;
}
bool operator>(const Stonewt & st1, const Stonewt & st2)
{
    return st1.pounds > st2.pounds ? true : false;
}
bool operator<(const Stonewt & st1, const Stonewt & st2)
{
    return st1.pounds < st2.pounds ? true : false;
}
bool operator>=(const Stonewt & st1, const Stonewt & st2)
{
    return st1.pounds >= st2.pounds ? true : false;
}
bool operator<=(const Stonewt & st1, const Stonewt & st2)
{
    return st1.pounds <= st2.pounds ? true : false;
}

ostream & operator<<(ostream & os, const Stonewt & st)
{
    Stonewt::MODE mode;
    mode = st.mode;
    switch (mode)
    {
    case Stonewt::POUNDS: 
            os << "Double pounds: " << st.pounds << " pounds";
            break;
    case Stonewt::STONE:
            os << "Stone: " <<st.stone_val() << " stone, " << st.pds_left_val() << " pounds";
            break;
    case Stonewt::INT_POUNDS:
            os << "Int pounds: " << st.int_pounds_val() << " pounds";
            break;
    default:
            os << "Stonewt object mode is invalid";
            break;
    }
}
#include "stonewt.h"

int main()
{
	const int Arsize = 6;
	using std::cin;
	using std::cout;
	using std::endl;
	double lbs;
	Stonewt max;
	Stonewt min;
	int count = 0;
	Stonewt starr[Arsize] = {
		100,200,300
	};
	for(int i = 3; i < Arsize; i++)
	{
		cout << "Enter the weight in pounds: ";
		cin >> lbs;
		starr[i] = Stonewt(lbs);
	}
	cout << "Stonewt array list:\n";
	for(int i = 0; i < Arsize; i++)
		cout << starr[i] << endl;
	cout << endl;
	max = starr[0];
	for(int i = 0; i < Arsize; i++)
	{
		max = max > starr[i] ? max : starr[i];
	}
	cout << "The maximum Stonewt object:\n" << max << endl;
	
	min = starr[0];
	for(int i = 0; i < Arsize; i++)
	{
		min = min < starr[i] ? min : starr[i];
	}
	cout << "The minimum Stonewt object:\n" << min << endl;

	Stonewt st11 = Stonewt(11,0.0);
	for(int i = 0; i < Arsize; i++)
	{
		if(starr[i] >= st11)
			count++;
	}

	cout << "The Stonewt array >= 11 stone number: " << count << endl;
	return 0;
}

运行结果如下:
image
7. 复数有两个部分组成:实数部分和虚数部分。复数的一种书写方式是:(3.0, 4.0),其中,3.0是实数部分,4.0是虚数部分。假设a = (A, Bi),c = (C,Di),则下面是一些复数计算。

  • 加法:a + c = (A + C, (B + D)i)
  • 减法:a - c = (A - C, (B - D)i)
  • 乘法:a * c = (AC-BD,(AD+BC)i)
  • 乘法::x c = (xC,x*Di),其中x为实数
  • 共轭: ~a = (A,-Bi)

请定义一个复数类,以便下面的程序可以使用它来获得正确的结果。

#include <iostream>
using namespace std;
#include "complex0.h"	// to avoid confusion with complex.h
int main()
{
	complex a(3.0, 4.0);
	complex 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;
}

注意,必须重载运算符<<和>>。标准C++使用头文件complex提供了比这个示例更广泛的复数支持,因此应将自定义的头文件命名为complex0.h,以免发生冲突,应尽可能使用const。
下面是该程序的运行情况。

Enter a complex number(q to quit):
real: 10
imaginary: 12
c is (10, 12i)
complex conjugate is (10, -12i)a is (3, 4i)a + c is (13, 16i)
a - c is (-7, -8i)
a * c is (-18, 76i)
2 * c is (20, 24i)
Enter a complex number(q to quit):
real: q
Done!

请注意,经过重载后,cin>>c将提示用户输入实数和虚数部分。
本题不算难实现上,对于加减乘运算,采用的是成员函数运算符重载,对于输出,之前输出过,因此没什么大问题,对于输入,重载函数定义时忘了输入不能用const引用,因此刚开始提示错误了,后面修改完善了,输入q离开刚开始没做处理,因此会输出imaginar:后面用if语句解决。
代码如下:

// complex0.h -- defination of complex class
#ifndef COMPLEX0_H_
#define COMPLEX0_H_
#include <iostream>
using std::ostream;
using std::istream;
class complex
{
private:
    double real;
    double imaginary;
public:
    complex(double i, double j);
    complex();
    ~complex();
    // overloading operator + - * and ~
    complex operator+(const complex & c) const;
    complex operator-(const complex & c) const;
    complex operator*(const complex & c) const;
    complex operator~() const;

    // friend 
    friend complex operator*(double n, const complex & c);
    friend istream & operator>>(istream & os, complex & c);
    friend ostream & operator<<(ostream & os, const complex & c);
};
#endif
// complex0.cpp -- methods for complex class
#include "complex0.h"

// constructor
complex::complex(double i, double j)
{
    real = i;
    imaginary = j;
}

complex::complex()  // default 
{
    real = imaginary = 0.0;
}

// deconstructor
complex::~complex()
{
}

// overloading operator
complex complex::operator+(const complex & c) const
{
    return complex(real + c.real, imaginary + c.imaginary);
}

complex complex::operator-(const complex & c) const
{
    return complex(real - c.real, imaginary - c.imaginary);
}

complex complex::operator*(const complex & c) const
{
    return complex(real * c.real - imaginary * c.imaginary, real * c.imaginary + imaginary * c.real);
}

complex complex::operator~() const
{
    return complex(real, -imaginary);
}

// friend
complex operator*(double n, const complex & c)
{
    return complex(n * c.real, n * c.imaginary);
}

std::istream & operator>>(std::istream & is, complex & c)
{
    std::cout << "real: ";
    if(is >> c.real)
    {
        std::cout << "imaginary: ";
        is >> c.imaginary;
    }
    return is;
}

std::ostream & operator<<(std::ostream & os, const complex & c)
{
    os << "(" << c.real << ", " << c.imaginary << "i)";
    return os;
}

运行结果如下:
image

posted @ 2021-12-27 13:17  Fight!GO  阅读(173)  评论(0编辑  收藏  举报