実験4演算子のリロード

10193 ワード

1、実験目的と要求
(1)演算子のリロードの文法的要点を把握し,メンバー関数と友元関数のリロード演算子の違いを理解する.
(2)各種演算子のリロード方法を把握し,参照形式がパラメータと戻り値としての特徴を理解する.
2、実験内容
(1)平面点クラスPointを記述し、リロードマイナス演算子は2点の距離を計算し、それぞれメンバー関数と友元関数で実現する.リロード演算子<<出力点の座標[x,y]は、クラスおよび関連関数の定義を与える.
#include <iostream>
#include <cmath>
using namespace std;
class Point
{
public:
    Point(int a= 0, int b = 0):x(a),y(b) {}
    void setPoint(int a, int b)
    {
        x=a;
        y=b;
    }
    double operator -(const Point& p);
    friend double operator -(Point& p1,Point& p2);
    friend ostream& operator <<(ostream& out,const Point& p);// "<<"         
private:
    int x, y;	//     
};
double Point::operator -(const Point& p)
{
    return sqrt((x-p.x)*(x-p.x)+(y-p.y)*(y-p.y));
}
double operator -(Point& p1,Point& p2)
{
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
ostream& operator <<(ostream& out,const Point& p)
{
    cout<<"["<<p.x<<","<<p.y<<"]";
    return out;
}
int main()
{
    Point p1(2,1),p2;
    double d=p1-p2;   //      
    cout<<p1<<"->"<<p2<<"="<<d<<endl;  //    [2,1]->[0,0]=2.23
    return 0;
}

(2)有理数を記述するRationalクラスは以下のようになりますが,クラスの他のメンバーが様々な演算を実行できるように補足してください.
Class Rational
{
   long  numerator ;//分子
   long  denominator ;//分母
........
};
1)算術演算子「+」、「-」、「*」、「/」を再ロードし、有理数の4則演算に適用できるようにする.
2)2つの有理数を比較できるように、比較演算子">"、"<="と"=="を再ロードします.
3)1/2,-1/3のような正規の方法でスコアを出力できるように、演算子「<<」をリロードします.分母は0にできません.
#include<iostream>
#include<cmath>
using namespace std;
class Rational
{
public:
    Rational(int n=1,int d=1);
    Rational operator +(const Rational &a);//      
    Rational operator -(const Rational &a);
    Rational operator *(const Rational &a);
    Rational operator /(const Rational &a);
    bool operator <(const Rational &a)const;
    bool operator >(const Rational &a)const;
    bool operator ==(const Rational &a)const;
    friend ostream& operator << (ostream& out,const Rational &a);
    void simple();//    
private:
    int  numerator ;  //   
    int  denominator ; //   
};
Rational::Rational(int n,int d):numerator(n),denominator(d) {}
Rational Rational::operator +(const Rational &a)
{
    Rational temp;
    temp.numerator=this->numerator*a.denominator+a.numerator*this->denominator;
    temp.denominator=this->denominator*a.denominator;
    temp.simple();
    return temp;
}
Rational Rational::operator-(const Rational &a)
{
    Rational temp;
    temp.numerator=this->numerator*a.denominator-this->denominator*a.numerator;
    temp.denominator=this->denominator*a.denominator;
    temp.simple();
    return temp;
}
Rational Rational::operator*(const Rational &a)
{
    Rational temp;
    temp.numerator=this->numerator*a.numerator;
    temp.denominator=this->denominator*a.denominator;
    temp.simple();
    return temp;
}
Rational Rational::operator/(const Rational &a)
{
    Rational temp;
    temp.numerator=this->numerator*a.denominator;
    temp.denominator=this->denominator*a.numerator;
    temp.simple();
    return temp;
}
bool Rational::operator <(const Rational &a)const
{
    if(this->numerator*a.denominator<this->denominator*a.numerator)return true;
    else return false;
}
bool Rational::operator >(const Rational &a)const
{
    if(this->numerator*a.denominator>this->denominator*a.numerator)return true;
    else return false;
}
bool Rational::operator ==(const Rational &a)const
{
    if(this->numerator*a.denominator==this->denominator*a.numerator)return true;
    else return false;
}
ostream& operator<<(ostream& out,const Rational &a)
{
    if(a.denominator!=0)out<<a.numerator<<'/'<<a.denominator;
    else out<<'0';
    return out;
}
void Rational::simple()
{
    int temp=numerator,a=numerator,b=denominator;
    while(temp!=0)//    
    {
        temp=b%a;
        b=a;
        a=temp;
    }
    numerator=numerator/b;
    denominator=denominator/b;
}

int main()
{
    Rational a(1,2);
    Rational b(1,3);;
    cout<<"a+b="<<a+b<<endl;
    cout<<"a-b="<<a-b<<endl;
    cout<<"a*b="<<a*b<<endl;
    cout<<"a/b="<<a/b<<endl;
    if(a>b)
    {
        cout<<"a>b"<<endl;
    }
    else if(a<b)
    {
        cout<<"a<b"<<endl;
    }
    else if(a==b)
    {
        cout<<"a==b"<<endl;
    }
    return 0;
}

(3)集合クラスSetを定義し、最大100個の重複しない整数を格納し、集合の以下の操作を実現する.
1)ある整数要素を追加する場合、集合に重複要素がないことを保証する.指定した要素を削除し、その要素を検索すると、集合からその要素を削除します.
2)演算子「+」を再ロードし、2つの集合オブジェクトの連結操作を実現し、演算子「*」を再ロードし、2つの集合オブジェクトの交差を求める.例えばSet s,s 1,s 2;s =s1+s2; s = s1* s2;
3)賦値演算子=と複合賦値演算子-=を再ロードし、2つの集合オブジェクトの賦値操作と差セット操作を実現する.例えば、Set s 1,s 2;s1 = s2;   s1-=s2; 集合S 1では、S 2に存在する要素を削除する.
#include<iostream>
#include<cstring>
using namespace std;
class Set
{
public:
    Set(int p_size = 1);
    Set(const Set& p_Set);
    ~Set();
    int getLength()
    {
        return length ;
    }
    void addItem(int p_item);
    void delItem(int p_item);
    Set operator + (Set& p_set);
    Set operator * (Set& p_set);
    Set& operator = (const Set& p_set);
    Set& operator -= (Set& p_set);
    friend ostream& operator << (ostream& x , Set& p_set);
    int operator [](int index) const;
private:
    int size;
    int length;
    int* data;
};
Set::Set(int p_size)
{
    size = (p_size <= 0) ? 1 : ((p_size > 100) ? 100 : p_size);
    data=new int[ size ];
    length=0;
    memset(data,0,sizeof(data));
}
Set::Set(const Set &p_Set)
{
    size = p_Set.size;
    length = p_Set.length;
    data = new int[size];
    for(int i = 0 ; i < length ; i ++)
        data[i] = p_Set[i];
}
Set::~Set()
{
    if(data)
        delete []data;
    size = 0;
    length = 0;
}
int Set::operator [](int index) const
{
    return data[(index < 0) ? 0 : ((index >= length) ? length - 1 : index) ];
}
void Set::addItem(int p_item)
{
    if(size == 100)
    {
        cout << "    !" << endl;
        return;
    }
    if(length == size && size < 100)
    {
        size = ((size + 20) > 100) ? 100 : (size + 20);
        int* temp = new int[size];
        for(int i = 0 ; i < length ; i ++)
            temp[i] = data[i];
        if(data)
            delete []data;
        data = temp;
    }
    for(int i = 0 ; i < length ; i ++)
    {
        if(p_item == data[i])
        {
            cout << "      !" << endl;
            return;
        }
    }
    data[ length ] = p_item;
    length ++;
}
;
void Set::delItem(int p_item)
{
    for(int i = 0 ; i < length ; i ++)
    {
        if(p_item == data[i])
        {
            if(i < length - 1)
                for(int j = i ; j < length - 1 ; j ++)
                    data[j] = data[j +1];
            length --;
        }
    }
}
Set Set::operator +(Set &p_set)
{
    Set s(*this);
    int flag ;
    for(int i = 0 ; i < p_set.length ; i ++)
    {
        flag = 1;
        for(int j = 0 ; j < s.length ; j ++)
            if(s[j] == p_set[i])
            {
                flag = 0;
                break;
            }
        if(flag)
            s.addItem(p_set[i]);
    }
    return s;
}
Set Set::operator * (Set &p_set)
{
    Set s(50);
    for(int i = 0 ; i < p_set.length ; i ++)
    {
        for(int j = 0 ; j < length ; j ++)
            if(data[j] == p_set[i])
            {
                s.addItem(data[j]);
            }
    }
    return s;
}
Set& Set::operator = (const Set &p_set)
{
    size = p_set.size;
    length = p_set.length;
    if(data)
        delete []data;
    data = new int[size];
    for(int i = 0 ; i < length ; i ++)
        data[i] = p_set[i];
    return *this;
}
Set& Set::operator -=(Set &p_set)
{
    for(int i = 0 ; i < p_set.length ; i ++)
    {
        for(int j = 0 ; j < length ; j ++)
            if(data[j] == p_set[i])
            {
                this->delItem(data[j]);
            }
    }
    return *this;
}
ostream& operator << (ostream& out , Set &p_set)
{
    for(int i = 0 ; i < p_set.length ; i ++)
        out << p_set[i] << ' ';
    return out;
}

int main()
{
    Set s1(5),s2(4),s3;
    for(int i = 0 ; i < 5 ; i ++)
        s1.addItem(i + 1);
    s1.addItem(5);
    cout << s1 << endl;
    for(int i = 1 ; i <= 4 ; i ++)
        s2.addItem(i * 2);
    cout<<s2<<endl;
    Set s=s1+s2;
    cout<<s<<endl;
    s=s1*s2;
    cout<<s<<endl;
    s1 -= s2;
    cout << s1 << endl;
    s3 = s2;
    cout << s3 << endl;
    return 0;
}

(4)データメンバーの時間hour、分minute、秒secondを含む時間を記述するTimeクラスを定義し、関連関数を定義して以下の操作を実現する.
1)演算子「+」と「-」をリロードし、時間オブジェクトと整数秒の加減を実現します.
2)リロード演算子「<<<」は時間オブジェクトを出力し、「時間:分:秒」のように時間を表示することができる.
3)演算子「+」と「--」を再ロードし、時間の合理的な自増自減機能(秒数の増減)を実現することを要求する.
 
(5)文字列クラスStringを設計し、Stringクラスオブジェクトs 1、s 2、s 3があれば、リロード演算子は以下の操作を実現する.
1)「+」を再ロードして文字列接続機能を実現し、式s 1=s 2+s 3を成立させる.
2)if(s 13)「<<」>「>」を再ロードし、cin>>s 2のような文字列の入力と出力操作を実現する.cout<4)演算子「()」をリロードし、文字列オブジェクトからサブストリングを返します.s 1(2,4)のように、s[2](s 1[2](s 1)から始まるサブ列(s 1[2]、s 1[3]およびs 1[4]の3文字を含む)を返す. 
(6)【オプション】多項式クラスPolynomialを開発します.多項式の各項目は配列または構造体で表され、各項目は1つの係数と1つの指数を含みます.たとえば、2 x 4の指数は4で、係数は2です.構造関数、構造関数、get関数、set関数を含む完全なPolynomialクラスを開発してください.このクラスには、次のようなリロード演算子も用意されています.
1)演算子「+」と「-」を再ロードし、2つの多項式を加算または減算します.
2)乗算演算子「*」を再ロードし、2つの多項式を乗算します.
3)代入演算子"="を再ロードし、1つの多項式を別の多項式に割り当てます.