#include <stdio.h>
#include <malloc.h>
#include <math.h>
#include <iostream.h>
#include <fstream.h>
#include <iomanip.h>
#define complex Complex
class Complex
{
public:
    double real;
    double image;

    ~Complex(void) {
    };
    Complex & operator = (Complex);
    friend Complex operator + (const Complex &, const Complex &);
    friend Complex operator * (const Complex &, const Complex &);
    friend Complex operator - (const Complex &, const Complex &);
    friend Complex operator / (const Complex &, const Complex &);
    friend ostream & operator << (ostream & a, const Complex b);
    Complex operator[](int index);
    void print();

    Complex(double r = 0, double i = 0) {
        real = r;
        image = i;
    }
    Complex(const Complex &);
};

//********************end of class Complex definition**************************

Complex::Complex(const Complex & z) {
    real = z.real;
    image = z.image;
}

Complex & Complex::operator = (Complex c){this->real = c.real;
    this->image = c.image;
    return *this;};

Complex operator + (const Complex & b, const Complex & c) {
    return Complex(b.real + c.real, b.image + c.image);
}

Complex operator - (const Complex & b, const Complex & c) {
    Complex temp(0, 0);
    temp.real = b.real - c.real;
    temp.image = b.image - c.image;
    return temp;
}

Complex operator*(const Complex & b, const Complex & c) {
    Complex temp(0, 0);
    temp.real = b.real * c.real - b.image * c.image;
    temp.image = b.image * c.real + b.real * c.image;
    return temp;
}

Complex operator / (const Complex& lhs, const Complex& rhs) {
    double ratio, den;
    if (fabs(rhs.real) >= fabs(rhs.image)) {
        ratio = rhs.image / rhs.real;
        den = rhs.real + ratio * rhs.image;
        return Complex((lhs.real + lhs.image * ratio) / den,
                (lhs.image - lhs.real * ratio) / den);
    } else {
        ratio = rhs.real / rhs.image;
        den = rhs.image + ratio * rhs.real;
        return Complex((lhs.real * ratio + lhs.image) / den,
                (lhs.image * ratio - lhs.real) / den);
    }
}

Complex Complex::operator[](int index) {
    Complex temp(0, 0);
    temp.real = (this + index)->real;
    temp.image = (this + index)->image;
    return temp;
}

void Complex::print() {
    printf("(%11.4e,%11.4e)\n", real, image);
}

ostream & operator << (ostream & a, const Complex b) {
    return a << "(" << b.real << "," << b.image << ")";
}

//**************  template for class Vector ***************************

template <class A, int number> class Vector
{
private:
    A *b;
    int n;
    //* All templates member-functions of class describe outside of class *******
public:
    // constructors
    Vector();
    Vector(A * x);
    Vector(const Vector &);
    Vector<A, number> operator + (const Vector<A, number> &);
    Vector<A, number> operator = (const Vector<A, number> &);

    //*************  Prefix operator++
    Vector<A, number> operator++();

    //************** Postfix operator++
    Vector<A, number> operator++(int);
    friend ostream & operator << (ostream &, const Vector<A, number> &);

    A sum(int);
    void print();
    // destructor

    ~Vector() {
        delete b;
    };
};

//******************* templates for member-function *********************                           

template<class A, int number> Vector<A, number>::Vector() {
    n = number;
    b = new A[number];
    for (int i = 0; i < number; i++) b[i] = 0;
};

template<class A, int number> Vector<A, number>::Vector(A *x) {
    n = number;
    b = new A[number];
    for (int i = 0; i < number; i++)b[i] = x[i];
}

template<class A, int number> Vector<A, number>::Vector(const Vector<A, number>& a) {
    n = a.number;
    b = new A[number];
    for (int i = 0; i < number; i++)b[i] = a.b[i];
}

template<class A, int number> Vector<A, number>
Vector<A, number>::operator + (const Vector<A, number> & b1) {
    Vector<A, number> c;
    int i;
    c.b[0] = this->b[0] + b1.b[0];
    for (i = 1; i <= number - 1; i++) c.b[i] = this->b[i] + b1.b[i];
    return c;
};

template<class A, int number> Vector<A, number> Vector<A, number>::operator = \
(const Vector<A, number> & b1){
    int i;
    Vector<A, number> c(b1.b);
    for (i = 0; i <= number; i++) this->b[i] = b1.b[i];
    return c;
};

template<class A, int number> Vector<A, number> Vector<A, number>::operator++() {
    for (int i = 0; i < number; i++) b[i] = b[i] + 1;
    Vector<A, number> t(b);
    return t;
}

template<class A, int number> Vector<A, number> Vector<A, number>::operator++(int) {
    Vector<A, number> t(b);
    for (int i = 0; i < number; i++) b[i] = b[i] + 1;
    return t;
}

template<class A, int number> ostream & operator << (ostream & a, const Vector<A, number> & c) {
    for (int i = 0; i < c.n; i++) a << c.b[i] << "\n";
    return a;
}

template <class A, int number> A Vector<A, number>::sum(int i) {
    int j;
    A c;
    c = b[0];
    for (j = 1; j <= i - 1; j++) c = c + b[j];
    return c;
};

template<class A, int number> void Vector<A, number>::print() {
    for (int i = 0; i < number; i++) cout << b[i];
};

void main() {
    ofstream out("c.dat");
    Complex z[10];
    Vector<Complex, 4 > v1, v2, v3;
    Vector<double, 5 > a1, a2, a3;
    Vector<char, 25 > c1, c2, c3;
    for (int i = 0; i < 4; i++) {
        z[i] = i;
        z[i].print();
    }
    v1 = z;
    v2 = z;
    //** Attention to v3!  Postfix operator++
    v3 = v1 + v2++;
    cout << "v1\n" << v1;
    cout << "v2\n" << v2;
    cout << "Attention to result(postfix operator++) v3=v1+v2++\n" << v3;
    cout << "a2\n" << a2;
    out << z[1] << "\n" << z[2];
    out.close();

}