Objectives
You will implement and test a class called MyString. Each MyString object keeps track of a sequence of characters, similar to the standard C++ string class but with fewer operations. The objectives of this programming assignment are as follows.
· Ensure that you can write a class that uses dynamic memory to store a sequence whose length is unspecified. (Keep in mind that if you were actually writing a program that needs a string, you would use the C++ standard string class, so this is mostly a learning experience to teach yourself the kind of things that go on in the implementation of the C++ standard string class.)
· Continue to practice incremental development and testing of your classes.
Problem Description
In this programming assignment, you will implement a new class called MyString, using a header file (most of which is written for you) and an implementation file (which you will write by yourself). The string that you implement is consistent with the C++ standard library string class (but with fewer operations). You are to write the following files:
1. MyString.h: The header file for the MyString class. Actually, you don't have to write much of this file. Just start with the given MyString.h file (available on Blackboard) and add your name and other information at the top, and then fill in the necessary information. If some of your member functions are implemented as inline functions, then you may put those implementations in this file too.
2. MyString.cpp: The implementation file for the MyString class. You will write all of this file, which will have the implementations of all the MyString's member functions.
In the development of this program, you may use functions from the #include <cstring> facility such as strlen, strcpy, strcat, strcmp, and so on (an introduction to C-strings is available as a Supplementary Reading on Blackboard under Content). Do NOT use the built-in C++ standard string class at any point in your implementation. Your member functions must NOT write any output to cout, nor expect any input from cin. All the interaction with the member functions should occur through their parameters.
You are to implement and test the following operations for the MyString class. The precondition/postcondition contract for all the MyString’s member functions is specified in the given header file.
· A constructor.
· An overloaded copy constructor.
· A destructor.
· The getLength member function.
· The operator [].
· The reserve function.
· The assignment operator.
· Three different versions of the operator +=.
· The operator + (as a friend function).
· The six comparison operators (as friend functions).
· The operator < (as a friend function).
· The operator > (as a friend function).
· The getline function (as a friend function).
Additional Requirements and Hints
The Private Member Variables
Carefully read the class definition in MyString.h. The MyString has a private member sequence to store the string as a null-terminated dynamic character array (so sequence is a pointer to char), and has a private member allocated to keep track of the total number of bytes allocated for the dynamic character array (each character takes one byte).
Notice here allocated is of type size_t. In C++, size_t is defined as an unsigned int type. Using size_t rather than unsigned int for string length leads to better portability of the code on different computer platforms. Also note that the total number of characters prior to the null character in sequence should always be less than allocated. We do not need to define a variable to hold the actual length of the string in sequence (i.e., the number of characters before the null character) since we may directly use the strlen function to obtain it.
The reserve Function
Programmers who use our string class never need to activate reserve, but they may wish to, for better efficiency. Our own implementations of other member functions (except for the constructors) can also activate reserve whenever a larger array is needed. When a member function activates reserve, the activation should occur before any other changes are made to the string. This follows the programming guideline of allocating new memory before changing an object. When reserving memory locations, you must make sure that you allow room for the null terminator. In the implementation of the reserve function, when new memory locations are reserved to hold the string, do not forget to deallocate the currently allocated memory locations.
The operator <, >, and getline Functions
In the implementation of the operator <, >, and getline functions, you may use the ostream operator <, the istream operator >, the isspace, and the istream peek, ignore, and get functions. The following is some hints.
The operator > begins by skipping any white space in the input stream. (All the standard operators in C++ start by skipping white spaces.) After skipping the initial white spaces, our string input operator reads a string – reading up to but not including the next white space character (or until the input stream fails, which might occur from several causes, such as reaching the end of the file). The function isspace from <cctype> library facility can help. This function has one argument (a character); it returns true if its argument is one of the white space characters. With this in mind, we can skip any initial white space with this loop:
// peek returns next char to be read without actually reading it.
while ( ins & isspace(ins.peek()) )
ins.ignore(); // ignore the next character
The loop also uses three istream features:
1. In a Boolean expression, the name of the istream (which is ins here) acts as a test of whether the input stream has failed. If ins results in a true value, then the stream is OK; a false value indicates a failure.
2. The peek member function returns the next character to be read (without actually reading it).
3. The ignore member function reads and discards the next character.
After skipping the initial white spaces, your implementation should set the string to be an empty string, and then read the input characters one at a time, adding each character to the end of the string. The reading stops when you reach more white space (or the end of file).
Once the target string (i.e., the MyString instance to receive the input) reaches its current capacity, our approach continues to work correctly, although it is inefficient because target is probably resized by the += operator each time that we add another character. Your comments in the program should warn programmers of this inefficiency so that a programmer can explicitly resize the target before calling the input operator.
For the getline function, you may also want to read one character at a time. You may use the following istream member function get in your program.
istream& get ( char& c ); // Extracts a character from the
// stream and stores it in c.
Check Preconditions
Your implementations should check preconditions of all functions. If the preconditions are not satisfied, you may simply terminate the program. Of course, if you want to write a more robust program, a better way to handle the violation of preconditions is to use try … catch … statements (see the corresponding Supplementary Reading available on Blackboard).
Input and Output
Your implementations must NOT produce any output to cout, nor expect any input from cin. All the interaction with the member functions occurs through their parameters.
Implement and Test Small Pieces
Don't tackle the whole project all at once. Start by implementing what you can, using one or several member functions together with a simple test driver client program to test the functionality of the functions.
Test the Completed Programs
After you have tested your programs using your own test driver code, you may test your programs using the given testing program MyStringTest.cpp (available on Blackboard).
What to Turn in
Make sure you name the .h and .cpp files as MyString.h and MyString.cpp. Then zip the two files and save it as project2_your_lastname.zip (if you have modified MyStringTest.cpp file, also include it in your .zip file)
2