// Zahlen mit Addition und Gedächtnis
//
// Aufruf: adder
//
// Klaus Kusche, 2011

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

class Number
{
  friend ostream &operator<<(ostream &outFile, const Number &a);

  public:
    Number() : sum(0), vals(nullptr), size(0) {}
    Number(int x) : sum(x), vals(new int[1]), size(1) {
      vals[0] = x;
    }
    Number(const Number &a);

    ~Number() {
      delete[] vals;
    }

    int getSum() { return sum; }
//  Alternative: Typumwandlungs-Operator von einem Number-Objekt auf int
//  operator int() { return sum; }

    Number operator+(const Number &a) const;
    Number operator+(int a) const;

    Number &operator=(const Number &a);
    
  private:
    int sum;
    int *vals;
    int size;
};

Number::Number(const Number &a)
: sum(a.sum), vals(new int[a.size]), size(a.size)
{
  for (int i = 0; i < size; ++i) {
    vals[i] = a.vals[i];
  }
}

Number Number::operator+(const Number &a) const
{
  Number res;

  res.sum = sum + a.sum;
  res.size = size + a.size;
  res.vals = new int[res.size];
  
  for (int i = 0; i < size; ++i) {
    res.vals[i] = vals[i];
  }
  for (int i = 0; i < a.size; ++i) {
    res.vals[size + i] = a.vals[i];
  }

  return res;
}

Number Number::operator+(int val) const
{
  Number res;

  res.sum = sum + val;
  res.size = size + 1;
  res.vals = new int[res.size];
  
  for (int i = 0; i < size; ++i) {
    res.vals[i] = vals[i];
  }
  res.vals[size] = val;

  return res;
}

Number &Number::operator=(const Number &a)
{
  if (this != &a) {
    if (size != a.size) {
      delete[] vals;
      size = a.size;
      vals = new int[size];
    }
    sum = a.sum;
    for (int i = 0; i < size; ++i) {
      vals[i] = a.vals[i];
    }
  }

  return *this;
}

ostream &operator<<(ostream &outFile, const Number &a)
{
  outFile << a.sum << " [ ";
  for (int i = 0; i < a.size; ++i) {
    outFile << a.vals[i] << ' ';
  }
  outFile << ']';
  
  return outFile;
}

int main(void)
{
  Number pos, neg;

  srand(time(nullptr));

  for (int i = 0; i < 10; ++i) {
    pos = pos + rand() % 10;
    neg = neg + -(rand() % 10);
    cout << pos << endl << neg << endl << "Summe: " << pos + neg << endl;
    cout << "Kurz: " << pos.getSum() << " + " << neg.getSum()
     << " = " << (pos + neg).getSum() << endl;
// Alternative mit Typumwandlungs-Operator:
//    cout << "Kurz: " << int(pos) << " + " << int(neg)
//         << " = " << int(pos + neg) << endl;
  }
  
  exit(EXIT_SUCCESS);
}
