Homework 6: String Objects

Educational Objectives: Experiencing upgrading a utility class; more experience working with dynamic memory; and experience using a generic sort algorithm.

Operational Objectives: Create the full fsu::String class as an upgrade to AString. Fully test the class with fstring.cpp, bfstring.cpp, and stringsort.cpp.

Deliverables: Two files xstring.cpp and stringsort.cpp.

Expandable String Objects

The class String is a kind of upgrade, actually a re-write, of the assignable string type AString created in a previous assignment. The new type String will have these features added to those already possessed by AString:

The class name is changed from AString to String, so code written for one class will not compile for the new type without an editorial change. But such a change would be necessary anyway to resolve the namespace for String. The actual interface, that is, the names of the public methods, will remain the same, except of course that String will have some added methods and more operators will be overloaded for the type. Keeping the old names from AString will ensure that client code for AString will need only changes of the declared types to function with fsu::String.

Implementation Plan

The implementation plan for fsu::String begins with the existing implementation of AString. Two private variables are used:

size_t size_;
char * data_;

The class has the responsibility for maintaining these variables in a consistent manner and for allocating and de-allocating resources (i.e., memory assigned to data_). In general, a String object will have size_ + 1 bytes allocated and will maintain null-termination of data_, which leaves size_ elements of data_ where client characters can be stored.

There is a safe allocator method intended to be used by constructors, copy constructor, assignment operator, the input operator, and any other methods or functions that need to create a new object:

static char* Newstr(size_t size)

This method returns a pointer to allocated memory after (1) checking that the allocation request was fullfilled and (2) null-terminating the allocated character array. The destructor de-allocates this resource.

Generic Sort Algorithm

The file tsort.h contains the following template function:

namespace fsu
{
  template < typename T >
  void g_insertion_sort (T* beg, T* end)
  {
    T *i, *j, *k;
    T t;
    for (i = beg; i != end; ++i)
      {
        t = *i;
        for (k = i, j = k--; j != beg && t < *k; --j, --k)
          *j = *k;
        *j = t;
      }
  }
} // namespace fsu

This is one case of a generic algorithm. Generic algorithms accomplish code re-use in at least two important ways: they are applicable across a wide variety of applications, and they encapsulate a complex algorithm in actual code, where it can be debugged, optimized, and stored away for safekeeping. The code implementing this algorithm is left somewhat dense and undocumented to make the point: you don't want to have to re-invent this when writing an application that needs some data sorted.

fsu::g_insertion_sort() is called in client code with two arguments: the first is a pointer to the beginning of the range being sorted, the second is a pointer "one past the end" of the range being sorted. A typical client call would appear as:

#include <tsort.h>
...
fsu::g_insertion_sort(A, A + n);
...

which results in the range [A, A + n) being sorted. It is up to the client code to ensure that this range is properly defined. Be sure you understand the role pointer arithmetic is playing here.

Note that this sort algorithm works on any array where the elements of the array have an overload of the less-than operator. (The call to this operator is shown in color above, in the header of the for loop.) The fsu::String class will have this operator overloaded, so that fsu::g_insertion_sort() can be applied to arrays of this type.

A String Sort Application

We are getting to the point that we have significantly useful technology. The fsu::String class has the less-than operator overloaded (to mean lexicographical order), and fsu::g_insertion_sort() is a generic sort algorithm that should apply to arrays of such objects. We can now create a very simple application to sort strings using OS redirect:

stringsort.x < infile > outfile

reads the strings from infile, sorts them, and then writes them in order to outfile. This program could be upgraded to take file names as command line arguments and become a useful desktop tool.

Procedural Requirements

  1. Create and work within a separate subdirectory cop3330/hw6. Review the COP 3330 rules found in Introduction/Work Rules.

  2. Begin by copying the following files from the course directory /home/courses/cop3330p/fall06/ into your hw6 directory:

    hw6/xstring.h              // complete header file for fsu::String 
    hw6/xstring.cpp-partial    // partial implementation file
    hw6/fstring.cpp            // command-line functionality test
    hw6/bfstring.cpp           // command-file functionality test
    hw6/tsort.h                // g_insertion_sort
    

    These files contain the header file in which class fsu::String is defined, a start for the implementation file xstring.cpp, two functionality test clients for class fsu::String (one is designed to take a file of commands), and the generic sort algorithm discussed above.

  3. Copy the distribution file xstring.cpp-partial to xstring.cpp.

  4. Modify the file xstring.cpp according to the requirements and specifications below.

  5. Create a string sort application stringsort.cpp using the ideas above. This should read strings from standard input into an array, sort the array, then write the strings to standard output. Use one call to g_insertion_sort to sort the array. Be sure the program works with OS redirect as shown above. Keep it simple!

  6. Test your code thoroughly using fstring.cpp, bfstring.cpp, and stringsort.cpp.

  7. Turn in two files xstring.cpp and stringsort.cpp using the hw6submit.sh submit script.

    Warning: Submit scripts do not work on the program and linprog servers. Use shell.cs.fsu.edu to submit projects. If you do not receive the second confirmation with the contents of your project, there has been a malfunction.

Code Requirements and Specifications

  1. Your implementation file should use the distributed header file xstring.h (not a modified version).

  2. Your implementation file should use the function headers as distributed in xstring.cpp-partial.

  3. Your code should compile without errors or warnings using the command:

    g++ -c -I. -Wall -Wextra xstring.cpp
    

  4. Your code function should correctly with any (legal) sequence of commands for the test harnesses.

Hints