#include <iostream.h>
#include <assert.h>
#include <string>
using namespace std;
class ray
   {
      private:
      public:
         char *data;
      int len;      //unsigned goes form 0 to 4 billion

      ray()
         {
         len = 0;
         data = 0;
         }
      ray(char *input)
         {
         len  = strlen(input);
         data = new char[len];
         copyString(input, data);
         }

      ~ray()
         {
         delete[] data;
         }

      void copyString(char *in, char *out)
         {
         char *p = in, *o = out;
         while (*p != 0)
            {
            *o = *p;
            p++;
            o++;
            }
         }

      friend ostream &operator<<(ostream &os, ray &r)
         {
         for(int i = 0; i < r.len; i++)
            {
            os << r.data[i];
            }
         return os;
         }


      char &operator[](int index)         //this thing returns a pointer to a[index], so other code can work w/ the pointer
         {
         assert(index >= 0 && index < len);
         return data[index];
         }

      ray &operator+(ray &other)
         {
         ray *temp = new ray();
         ray &result = *temp;
         temp->data = new char[len+other.len];
         temp->len = len + other.len;
         char *beginning;
         beginning = &temp->data[0];
         char *otherdata;
         otherdata = &other.data[0];
         char *mydata;
         mydata = &data[0];
         for(int i = 0; i < len; i++)
            {
            *beginning = *mydata;
            beginning++;
            mydata++;
            }
         for(int i = 0; i < other.len; i++)
            {
            *beginning = *otherdata;
            beginning++;
            otherdata++;
            }
         return result;
         }

      ray &operator++()
         {
         char *mydata;
         mydata = &data[0];
         for(int i = 0; i < len; i++)
            {
            if(*mydata > 90)
               *mydata = *mydata-32;
            mydata++;
            }
         return *this;
         }

      ray &operator-(int subtract)
         {
         ray *temp = new ray();
         ray &result = *temp;
         temp->data = new char[len - subtract];
         temp->len = len -subtract;
         char *beginning;
         beginning = &temp->data[0];
         char *mydata;
         mydata = &data[0];
         for(int i = 0; i < len - subtract; i++)
            {
            *beginning = *mydata;
            beginning++;
            mydata++;
            }
         return result;
         }

      ray &operator=(ray &other)
         {
         if(data != 0)
            delete [] data;
         len = other.len;
         data = new char[len];
         assert(data != 0);
         copyString(other.data, data);
         return *this;
         }

      ray &operator=(char *input)
         {
         if(data != 0)
            delete [] data;
         len = strlen(input);
         data = new char[len];
         copyString(input, data);
         }

      bool operator%(char a)
         {
         char *mydata;
         mydata = &data[0];
         for(int i = 0; i < len; i++)
            {
            if(*mydata == a)
               return true;
            mydata++;
            }
         return false;
         }

      bool operator%(char *input)
         {
         char *mydata;
         mydata = &data[0];
         for(int i = 0; i < len; i++)
            {
            if(*mydata == *input)
               {
               mydata++;
               input++;
               }
            else
               mydata++;
            if(*input == 0)
               return true;
            }
         return false;
         }
   };

class String
   {
      private:
      char *data;
      public:
         String()
         {
         data = 0;
         }
      ~String()
         {
         if(data != 0)
            delete [] data;
         }
      String(char *input)
         {
         int length = strlen(input);
         data = new char[length+1];
         copyString(input, data);
         }
      void copyString(char *in, char *out)
         {
         char *i = in, *o = out;
         while (*i != 0)
            {
            *o = *i;
            i++;
            o++;
            }
         *o = 0;
         }

      friend ostream &operator<<(ostream &os, String &s)
         {
         if(s.data != 0)
            {
            int p = 0;
            while(s.data[p] != '\0')
               {
               os<< s.data[p];
               p++;
               }
            }
         else
            {
            os << "EMTPY STRING";
            }
         return os;
         }

      char &operator[](int index)         //this thing returns a pointer to a[index], so other code can work w/ the pointer
         {
         assert(index >= 0 && index < strlen(data));
         return data[index];
         }

      String &operator=(char *input)
         {
         if(data != 0)
            delete [] data;
         int length = strlen(input);
         data = new char[length+1];
         copyString(input, data);
         return *this;
         }

      String &operator=(String &other)
         {
         if(data != 0)
            delete [] data;
         int length = strlen(other.data);
         data = new char[length+1];
         copyString(other.data, data);
         return *this;
         }


      String &operator+(String &other)
         {
         String *temp = new String();
         temp->data = new char[strlen(other.data)+strlen(data)-1];
         String &result = *temp;
         char *beginning;
         beginning = &temp->data[0];
         char *otherdata;
         otherdata = &other.data[0];
         char *mydata;
         mydata = &data[0];
         //gets here
         for(int i = 0; i < strlen(data); i++)
            {
            //gets here
            *beginning = *mydata;
            //does not get here
            beginning++;
            mydata++;
            }
         for(int t = 0; t < strlen(other.data); t++)
            {
            *beginning = *otherdata;
            beginning++;
            otherdata++;
            }
         *beginning = 0;
         return result;
         }

      String &operator-(int subtract)
         {
         String *temp = new String();
         String &result = *temp;
         temp->data = new char[strlen(data)-subtract];
         char *beginning;
         beginning = &temp->data[0];
         char *mydata;
         mydata = &data[0];
         for(int i = 0; i < strlen(data)-subtract; i++)
            {
            *beginning = *mydata;
            beginning++;
            mydata++;
            }
         *beginning = 0;
         return result;
         }

      bool operator%(char a)
         {
         char *mydata;
         mydata = &data[0];
         while(*mydata != 0)
            {
            if(*mydata == a)
               return true;
            mydata++;
            }
         return false;
         }

      bool operator%(char *input)
         {
         char *mydata;
         mydata = &data[0];
         while(*mydata != 0)
            {
            if(*mydata == *input)
               {
               mydata++;
               input++;
               }
            else
               mydata++;
            if(*input == 0)
               return true;
            }
         return false;
         }
   };

int main()
   {
   String s1, s2("hello");                     //tasks 1 and 2
   s1 = s2;                              //task 4
   cout << "s1: " << s1 << endl;                  //task 3
   s2[2] = 'b';                           //task 8
   cout << "s2: " << s2 << endl;
   String s4;
   s4 = "newstring";                        //task 5
   cout << "s4: " << s4 << endl;
   String s3;
   s3 = s1 + s2;                           //task 6
   cout << "s3 (add of s1 and s2):  " << s3 << endl;
   s3 = s3 - 3;                           //task 7
   cout << "s3 in all caps: " << s3 << endl;
   if(s1 % 'e')                           //task 10
      cout << "s1 contains an e" << endl;
   else
      cout << "s1 doesnt contain an e" << endl;
   if(s1 % 'q')                           //task 10 again
      cout << "s1 contains an q" << endl;
   else
      cout << "s1 doesnt contain an q" << endl;
   if(s1 % "elp")                           //task 11
      cout << "s1 contains elp" << endl;
   else
      cout << "s1 doesnt contain elp" << endl;
   if(s1 % "ell")                           //task 11 again
      cout << "s1 contains ell" << endl;
   else
      cout << "s1 doesnt contain ell" << endl;
   cout << endl;

   ray r1, r2("Hello");                        //tasks 1 and 2
   r1 = r2;                              //task 4
   cout << "r1: " << r1 << endl;                  //task 3
   r2[2] = 'b';                           //task 8
   cout << "r2: " << r2 << endl;
   ray r4;
   r4 = "newstring";                        //task 5
   cout << "r4: " << s4 << endl;
   ray r3;
   r3 = r1 + r2;                           //taks 6
   cout << "r3 (the add of r1 and r2): " << r3 <<endl;
   r3 = r3 - 3;                           //task 7
   cout << "r3 minus 3: "<<r3 << endl;
   ++r3;
   cout << "r3 in all caps: " <<r3 << endl;
   if(r1 % 'e')                           //task 10
      cout << "r1 contains an e" << endl;
   else
      cout << "r1 doesnt contain an e" << endl;
   if(r1 % 'q')                           //task 10 again
      cout << "r1 contains a q" << endl;
   else
      cout << "r1 doesnt contain a q" << endl;
   if(r1 % "elp")                           //task 11
      cout << "r1 contains elp" << endl;
   else
      cout << "r1 doesnt contain elp" << endl;
   if(r1 % "ell")                           //task 11 again
      cout << "r1 contains ell" << endl;
   else
      cout << "r1 doesnt contain ell" << endl;
   }