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.
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 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. 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 MyStrings member functions is specified in the given header file.
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
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)
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.