Second Review

After finishing the requirements to make the string class a concrete data type, we continued to add more facilities to this class; to be precise, we wanted to make it possible to modify the sorting program of Chapter 4 to handle strings rather than shorts. To do this, we had to be able to compare two strings to determine which of the two would come first in the dictionary and to read strings from an input stream (like cin) and write them to an output stream (like cout). Although the Display function provided a primitive mechanism for writing a string to cout, it's much nicer to be able to use the standard >> and << operators that can handle all of the native types so we resolved to make those operators available for strings as well.

We started out by implementing the < operator so that we could compare two strings x and y to see which would come before the other in the dictionary, simply by writing if (x < y). The implementation of this function turned out to be a bit complicated because of the possibility of "running off the end" of one of the strings, when the strings are of different lengths.

Once we worked out the appropriate handling for this situation, we examined two implementations of the algorithm for operator <. The first implementation compared characters from the two strings one at a time, while the second used memcmp, a C function that compares two sets of bytes and returns a different value depending on whether the first set is "less than", "equal to", or "greater than" the second one, using ASCII ordering to make this determination.

Then we developed an implementation of operator == for strings, which turned out to be considerably simpler than the second version of operator <, even though both functions used memcmp to do most of the work; the reason is that we have to compare the contents of the strings only if they are of the same length, because strings of different lengths cannot be equal.

Then we started looking beneath the covers of the output functions called operator<<, starting with the predefined versions of << that handle char and C string arguments. The simplest case of using this operator, of course, is to display one expression on the screen via cout. Next, we examined the mechanism by which several uses of this operator can be chained together to allow the displaying of a number of expressions with one statement.

The next issue was how to provide these handy facilities for the users of our string class. Would we have to modify the ostream classes to add support for strings? Luckily, the designers of the stream classes were foresightful enough to enable us to add support for our own data types without having to modify their code. The key is to create a global function that can add the contents of our string to an existing ostream variable and pass that ostream variable on to the next possible user, just as in “chaining” for native types.

The implementation of this function wasn't terribly complicated; it merely wrote each char of the string's data to the output stream. The unusual attribute of this function was that it wasn't a member function of string, but a global function, as is needed to maintain the same syntax as the output of native types. We used the friend specifier to allow this version of operator << to access private members of string such as m_Length and m_Data.

After we finished the examination of our version of operator << for sending strings to an ostream, we went through the parallel exercise of creating a version of operator >> to read strings from an istream. This turned out to be a bit more complicated, since we had to make room for the incoming data. This limited the maximum length of a string that we could read. In the process of defining this maximum length, we also encountered a new construct, the const. This is a data item that is declared just like a variable, except that its value is initialized once and cannot be changed . This makes the const ideal for specifying a constant size for an array, a constant loop limit, or another value that doesn't change from one execution of the program to the next. Next, we used this const value to declare an array of chars to hold the input data to be stored in the string, and filled the array with null bytes, by calling the C function memset. We followed this by using some member functions of the istream class to eliminate any newline (' ') character that might have been left over from a previous input operation.

Finally, we were ready to read the data into the array of chars, in preparation for assigning it to our string. After doing that assignment, we returned the original istream to the caller, to allow chaining of operations as is standard with operator << and operator >>.

That completes the review of this chapter. Now let's do some exercises to help it all sink in.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset