#include <iostream>
#include <string>
#include <sstream>

using namespace std;

class Fraction {
public:
    Fraction(int n = 0, int d = 1);

    bool setValue(int n, int d = 1);
    double getValue() const;

    int getNumerator() const;       // interface
    int getDenominator() const;     // interface

    void input();

    Fraction &operator=(const Fraction &rhs);
    Fraction &operator+=(const Fraction &rhs);
    Fraction &operator*=(const Fraction &rhs);

    Fraction &operator++();
    Fraction operator++(int);

    Fraction operator+(const Fraction &rhs) const;
//    Fraction operator+(const double rhs) const;
    Fraction operator*(const Fraction &rhs) const;

    bool operator==(const Fraction &rhs) const;

private:
    int numerator;      // any integer  (encapsulation, hermetization)
    int denominator;    // always > 0   (encapsulation, hermetization)
};

ostream &operator<<(ostream &s, const Fraction &f) {
    s << f.getNumerator() <<  "/" << f.getDenominator();

    return s;
}


Fraction::Fraction(int n, int d) {
    if (setValue(n, d) == false)
        setValue(0, 1);
}

bool Fraction::setValue(int n, int d) {
    if (d <= 0) {
        cerr << "Denominator may not be <= 0." << endl;
        return false;
    }
    this->numerator = n;
    this->denominator = d;

    return true;
}

double Fraction::getValue() const {
    return (double)this->numerator / this->denominator;
}


int Fraction::getNumerator() const {
    return this->numerator;
}

int Fraction::getDenominator() const {
    return this->denominator;
}

void Fraction::input() {
    int n, d;

    cout << "Enter fraction numerator: " << endl;
    cin >> n;
    do {
        cout << "Enter denominator: " << endl;
        cin >> d;
    } while (! setValue(n, d));
}

Fraction &Fraction::operator=(const Fraction &rhs) {

    if (this == &rhs)
        return *this;

    this->numerator = rhs.numerator;
    this->denominator = rhs.denominator;

    return *this;
}

Fraction &Fraction::operator+=(const Fraction &rhs) {

    this->numerator = this->numerator * rhs.denominator + rhs.numerator * this->denominator;
    this->denominator = this->denominator * rhs.denominator;

    return *this;
}

Fraction &Fraction::operator*=(const Fraction &rhs) {

    this->numerator = this->numerator * rhs.numerator;
    this->denominator = this->denominator * rhs.denominator;

    return *this;
}

Fraction Fraction::operator+(const Fraction &rhs) const {
    int n, d;

    n = this->numerator * rhs.denominator + rhs.numerator * this->denominator;
    d = this->denominator * rhs.denominator;

    return Fraction(n, d);
}

Fraction Fraction::operator*(const Fraction &rhs) const {
    int n, d;

    n = this->numerator * rhs.numerator;
    d = this->denominator * rhs.denominator;

    return Fraction(n, d);
}

Fraction &Fraction::operator++() {

    this->numerator += this->denominator;

    return *this;
}

Fraction Fraction::operator++(int) {
    Fraction old = *this;

    this->operator++();

    return old;
}

bool Fraction::operator==(const Fraction &rhs) const {
    bool result;

    result = (this->numerator * rhs.denominator == rhs.numerator * this->denominator);

    return result;
}


int main () {
    Fraction f1(1, 2), f2(1, 3), f3;

    // Testing input
    
 //   f3.input();  // cin >> f3; // How to achieve that???
    
 //   return 0;
    
    // Testing output

 //   cout << f1 << endl;

//    return 0;

    // Testing arithmetic addition + operator

    cout << f1 << " + " << f2 << " = " << f1 + f2 << endl;

    // Testing arithmetic multiplication * operator

    cout << f1 << " * " << f2 << " = " << f1 * f2 << endl;
    
    return 0;

    // Testing arithmetic addition + and assignment = operators

    f3 = f1 + f2;

    cout << f3 << " = " << f1 << " + " << f2 << endl;
    
    return 0;

//    cout << f3 << endl;
//    cout << f1 << endl;

//    int n = 3;
//    f3 = n + f1;
//    f3 = f1 + 3.14;
    
    cout << f3 << endl;

    return 0;

    
    // Testing assignment += operators

    f1 += f2;

    cout << f3 << " += " << f2 << " --> " << f1 << endl;

    // Testing assignment *= operators

    f3 = f1;
    f1 *= f2;

    cout << f3 << " *= " << f2 << " --> " << f1 << endl;

    // Testing pre-increment operator

    cout << "++" << f1 << " --> " << ++f1 << " --> " << f1 << endl;

    // Testing post-increment operator

    cout << f1 << "++" << " --> " << f1++ << " --> " << f1 << endl;

    // Testing logical equality == operator

    if (f1 == f2)
        cout << "Fractions " << f1 << " and " << f2 << " are equal" << endl;
    else
        cout << "Fractions " << f1 << " and " << f2 << " are not equal" << endl;
}
