Create a class called MyString -- this will be a string class, which allows creation of string objects that have flexible sizes, intuitive operator syntax (through operator overloads), and other useful features. Your class will need to maintain the string internally as an array of characters, and since string sizes are not fixed, dynamic allocation techniques will need to be used in the class. Your class should maintain any string ojbect in a valid state at all times, and it should not allow any memory leaks.
The class should be written in the files mystring.h and mystring.cpp. I have provided a starter version of the file mystring.h, which already has many of the required features (i.e. the interface for users) declared. Do not change the prototypes of the already-declared functions.
Important Note: Since the intention of this is for you to write a string class, you may NOT use the < string> class library in the creation of this!
Data
Your class must allow for storage of a flexibly-sized string of characters. Make sure to declare any appropriate member data variables in the header file. All member data of your class must be private.
Function descriptions
1. Standard Constructors
Note that these last two constructors will allow automatic type conversions to take place -- in this case, conversions from int to MyString and from c-style strings to type MyString -- when appropriate. This makes our operator overloads more versatile, as well. For example, the conversion constructor allows the following statements to work (assuming appropriate definitions of the assignment operator and + overloads described later):
MyString s1 = "Hello, World";
MyString s2 = 12345;
MyString s3 = s1 + 15; // concatenation "Hello, World15"
2. Automatics
Since dynamic allocation is necessary, you will need to write appropriate definitions of the special functions (the "automatics"): destructor, copy constructor, assignment operator. The destructor should clean up any dynamic memory when a MyString object is deallocated. The copy constructor and assignment operator should both be defined to make a "deep copy" of the object (copying all dynamic data, in addition to regular member data), using appropriate techniques. Make sure that none of these functions will ever allow memory "leaks" in a program.
3. I/O functions
4. Comparison operators
Write overloads for all 6 of the comparison operators ( < , > , <= , >= , == , != ). Each of these operations should test two objects of type MyString and return an indication of true or false. You are testing the MyString objects for order and/or equality based on the usual meaning of order and equality for c- strings, which is lexicographic ordering. Remember that this is based on the order of the ascii characters themselves, so it's not exactly the same as pure "alphabetical" ordering.
Examples:
"apple" < "apply"
"Zebra" < "apple" // uppercase letters come before lowercase
"apple" == "apple" // same strings
5. Concatenation operators
Examples:
MyString s1 = "Dog";
MyString s2 = "food";
MyString s3 = s1 + s2; // s3 is "Dogfood" and s1, s2 are not changed
s1 += s2; // s1 is now "Dogfood"
6. Bracket operators
The bracket operator overloads have these prototypes:
char& operator[] (unsigned int index); // returns L-value
const char& operator[] (unsigned int index) const; // read-only return
Both of these should return the character at the given index position. Note that the first one returns the character by reference, so it allows the slot to be changed. The second returns by const reference and is a const member function and will run in read-only situations -- calls on const objects. Example calls:
const MyString s = "I love Java";
MyString t = "I love C++";
// these two calls use the const version above
char ch = s[4]; // ch now stores 'v'
ch = s[7]; // ch now stores 'J'
// these calls use the non-const version above
t[0] = 'U'; // s is now "U love C++"
t[3] = 'i'; // s is now "U live C++"
Note that since the parameter in each is an unsigned int, it's not possible to have a negative array index passed in. If the index passed to the function is too big (out of bounds for what's currently stored), then:
Examples:
const MyString s = "Howdy"; // length of s is 5 characters
char ch = s[10]; // ch now stores ' '
MyString t = "Hello"; // length of t is 5 characters
t[7] = 'b'; // t is now "Hello b" (length is now 8)
7. Standard accessors
getLength should return the length of the stored string (i.e. number of characters). For example, "Hello" has 5 characters getCString should return the actual stored data as a c-string (i.e. null- terminated char array)
8. substring functions
There are two versions of substring -- a 1 parameter version and a 2-parameter version. Both should return a MyString object that consists of a portion (or "substring") of the original string. Neither should change the calling object. The first parameter represents the starting index of the substring. In the 2-parameter version, the second parameter gives the length of the substring to return (if the length is too long, default to the rest of the string ). In the 1-parameter version, the substring consists of the characters from the start index to the end of the string.
Examples:
MyString s = "Greetings, Earthling!";
MyString x, y, z;
x = s.substring(4); // x is now "tings, Earthling!"
y = s.substring(3, 5); // y is now "eting"
z = s.substring(16, 10); // z is now "ling!"
9. insert() function
This function should change the calling object by inserting the data from the second parameter AT the index given by the first parameter. If the index is out of bounds (longer than the string's length), then just insert at the end. This function should also return the calling object.
Examples:
MyString s = "Hello world";
s.insert(6, "cruel "); // s is now "Hello cruel world"
s.insert(20, "!!!"); // s is now "Hello cruel world!!!"
10. indexOf function
This function should search through the MyString to find the first occurence of the pattern or substring given in the parameter. The function should return the first index where it was found, or it should return -1 if the pattern is NOT found.
Examples:
MyString s = "The bobcat likes to concatenate";
int x = s.indexOf("cat"); // x is now 7
x = s.indexOf("dog"); // x is now -1
Create an overloaded version of the - operator to "subtract" two MyString objects. The meaning of - is that it should return a MyString object that is the result of taking the first string and removing all instances of the second string from it.
Examples:
MyString s = "The bobcat concatenated the catapult with the catamaran";
MyString t = "cat";
MyString result = s - t;
// result now stores "The bob conenated the apult with the amaran";