#include <iostream>

class String
{
  char *s;

  void assign_empty() { s=nullptr; }

  void assign(const char*str_ptr){
    size_t length = 0;
    while(str_ptr[length]) length++;
    if(length){
      s = static_cast<char*>(malloc(length + 1));
      for (size_t i = 0; i <= length; i++) s[i] = str_ptr[i];
    } else {
      s = nullptr;
    }
  }



public:
  String()
  {
    assign_empty();
  }

  String(const char *str_ptr)
  {
    assign(str_ptr);
  }

  String(const String &o){
    if(o.empty()){
      assign_empty();
    } else {
      assign(o.s);
    }
  }

  void clear() {
    if (s) {
      free(s);
    }
    s = nullptr;
  }

  // a=b=c=d="asd";
  String&operator=(const String &other) {
    clear();
    if(other.empty()){
      assign_empty();
    } else {
      assign(other.s);
    }
    return *this;
  }

  size_t length() const
  {
    if(s)
    {
      size_t length = 0;
      while(s[length]) length++;
      return length;
    }else return 0; 
  }

  String &operator += (const String &other)
  {
    size_t length1 = length();
    size_t length2 = other.length();

    if(!length2)
      return *this;

    char *result = new char[length1 + length2 + 1];
    for(size_t i = 0; i < length1; i++)
    {
      result[i] = s[i];
    }
    for(size_t i = 0; i < length2; i++)
    {
      result[i+length1] = other.s[i]; 
    }

    result[length1 + length2] = 0;

    clear();
    s = result;
    
    return *this;
  }

  String operator+ (const String &other) const
  {
    String result;

    result += *this;
    result += other;
    
    return result;
  }
  
  friend std::ostream& operator<<(std::ostream &o, const String &s){
    if(!s.empty()) o << s.s;
    return o;
  }

  char &operator[](size_t number){
    return s[number];
  }

  char operator[](size_t number) const {
    return s[number];
  }

  ~String()
  {
    clear();
  }

  bool empty() const {return !s;}
};

int main() {
  String a("hello");
  String x(" world!");
  x[1]='W';
  String b(a);
  String c;
  c=a+a;
  b=c;
  c+=x;
  std::cout << c+c << std::endl;
  std::cout << (c+c)[11] << std::endl;
  return 0;
}
