#include <iostream>
#include <cstring>

class MyString
{
 // class friends
 // You can specify other classes, methods of a class o functions
 // that can access the non-public member of this class.

 friend  ostream& operator<< (ostream& outStream, 
                              const MyString & rhs);
 friend bool operator< (const MyString &lhs, const MyString& rhs);

 private:
   int length;
   char *mstr;   // a char* is how a dynamic character array is
                 //  declared

 public:
   
   // default constructor
   // MyString word;
   MyString ()
     {
      length = 0;
      // mstr = new char;
      mstr = new char [1];
      mstr[0] = '\0';
     }

   // constructor that takes a quoted string
   // MyString word ("hello");
   MyString (char * pstr)
     {
      int i;

      // rewrite strlen to show the array access
      // length = strlen(pstr);
      i = 0;
      while (pstr[i] != '\0')
          i++;
      length = i;
 
      // dynamically allocate memory for the character array
      mstr = new char [length + 1];

      // copy the parameter string into the dynamic array
      // strcpy (mstr, pstr);
      for (i = 0; i < length + 1; i++)
          mstr[i] = pstr[i];
     }

   // create the copy constructor (should alays be written when
   //  a class has a dynamic data member).
   MyString (const MyString & msp)
     {
      // set the length based on the new string value
      length = msp.length;
      // allocate space for the new array
      mstr = new char [length + 1];
      // copy the parameter value into the new array
      strcpy (mstr, msp.mstr);
     }


   // create the destructor for the class
   ~MyString ()
     {
      cout << "In destructor: " << '\"' << mstr << '\"' << endl;
      delete [] mstr;
     }

   void output()
     {
      cout << "The string has " << length << " characters: ";
      cout << '\"' << mstr << '\"' << endl;
     }

   void assign (char * pstr)
     {
      // deallocate the existing character array
      delete [] mstr;

      // set the length based on the new string value
      length = strlen (pstr);
      // allocate space for the new array
      mstr = new char [length + 1];
      // copy the parameter value into the new array
      strcpy (mstr, pstr);
     }

   void assign (MyString &pstr)
     {
      // verfiy that the parameter is not the instance of the class
      if (this == &pstr)
         return;

      // deallocate the existing character array
      delete [] mstr;

      // set the length based on the new string value
      length =pstr.length;
      // allocate space for the new array
      mstr = new char [length + 1];
      // copy the parameter value into the new array
      strcpy (mstr, pstr.mstr);
     }

   MyString& operator= (const MyString &pstr)
     {
      // verfiy that the parameter is not the instance of the class
      if (this == &pstr)
         return *this;

      // deallocate the existing character array
      delete [] mstr;

      // set the length based on the new string value
      length =pstr.length;
      // allocate space for the new array
      mstr = new char [length + 1];
      // copy the parameter value into the new array
      strcpy (mstr, pstr.mstr);

      return *this;
     }

   int getLength()
     {
      return length;
     }

   char* getString()
     { 
      return mstr;
     }
};

bool operator< (const MyString &lhs, const MyString& rhs)
{
 // compare using lexicographical order using the ASCII character set
 if (strcmp(lhs.mstr, rhs.mstr) < 0)
    return true;
 else 
    return false;
}

ostream& operator<< (ostream& outStream, const MyString & rhs)
{
 // output to outStream the desired data members from the class
 // outStream << rhs.getString();
 outStream << rhs.mstr;

 // return outStream
 return outStream;
}

int main()
{
 MyString str1("hello"), str2("goodbye");
 MyString str3;

 cout << "str1 contains: " << str1 << endl;
 // ifstream << "str1 contains: " << str1 << endl;
 
 cout << "str1 contains: "; 
 str1.output();
 cout << endl;

 str2.output();
 cout << endl;

 str3.output();
 
 str3.assign("Good Morning");
 str3.output();

 str2.assign("Good Day");
 str2.output();

 str1.assign(str2);
 str1.output();

 str3 = str2;
 str3.output();

 // x = y = z = 0;
 str1.assign("hi");
 str3 = str2 = str1;
 str1.output();
 str2.output();
 str3.output();

 cout << "goodbye" << endl;
 
}