Educational Objectives: After completing this assignment the student should have the following knowledge, ability, and skills:
Operational Objectives: Create the full fsu::String class as an upgrade to AString. Fully test the class with fstring.cpp, fstringb.cpp, and stringsort.cpp.
Deliverables: Two files xstring.cpp and stringsort.cpp.
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.
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.
The file mergesort.h contains a template function with the following interface (prototype):
void fsu::g_merge_sort(RAIterator beg, RAIterator end);
This is a generic algorithm in the technical sense that it is a template function whose template arguments are intended to be "iterators" (in this case, random access iterators). The template parameter RAIterators is chosen as a self-documenting reminder of the type expected by the algorithm.
You already have some limited experience with two kinds of random access iterators: (1) pointers and (2) std::vector iterators.
is a loop that traverses the array a. Here the loop counter i is a pointer and the increment ++i is "pointer arithmetic". Note also that a is the (beginning address of) the array and that a + size is the address that is "one past the end" of the array. All this comes together in how you would call merge sort to sort the array:size_t size = 20; int a [size]; ... for (int* i = a; i != a + size; ++i) { // whatever }
Note how we pass a "range" in the half-open convention to the generic algorithm, which then makes its magic on the range you give it. The client programmer (i.e., you) has the responsibility to ensure that the expectations of the generic algorithm are met. The compiler will enforce this on you.// code setting up the array a ... fsu::g_merge_sort(a, a + size); // sorts the range [a, a+size) // now a is sorted ...
In this usage the standard vector has methods begin() and end() that return "iterators" pointing to the beginning and one-past-the-end of the vector range. Again we invoke the generic algorithm by passing a range in the half-open convention and allow the algorithm to work on the range specified.// code setting up the vector v ... fsu::g_merge_sort(v.begin(), v.end()); // sorts the range [v.begin(), v.end()) // now v is sorted ...
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_merge_sort() is a generic sort algorithm that should apply to both vectors and arrays of such objects. We can now create a very simple application to sort strings in a file and write the result to another file:
stringsort.x infile outfile
reads the strings from infile, sorts them, and then writes them in order to outfile. Depending on user preference, this program could be changed to use OS redirect at the command line instead of command line arguments, operating like this:
stringsort.x < infile > outfile
Either way, stringsort.x can be a useful desktop tool.
Create and work within a separate subdirectory cop3330/hw6. Review the COP 3330 rules found in Introduction/Work Rules.
Begin by copying the following files from the course directory /home/courses/cop3330p/fall08/ 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/fstringb.cpp // command-file functionality test hw6/mergesort.h // g_merge_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.
Copy the distribution file xstring.cpp-partial to xstring.cpp.
Modify the file xstring.cpp according to the requirements and specifications below.
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_merge_sort to sort the array. Be sure the program works command line file names as shown above. Keep it simple!
Test your code thoroughly using fstring.cpp, fstringb.cpp, and stringsort.cpp.
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.
Your implementation file xstring.cpp should use the distributed header file xstring.h (not a modified version).
Your implementation file should use the function headers as distributed in xstring.cpp-partial.
Your code should compile without errors or warnings using the command:
g++ -c -I. -Wall -Wextra xstring.cpp
Your code should function correctly with any (legal) sequence of commands for the test harnesses.
The command:
stringsort.x infile outfile
should result in outfile being a sorted permutation of the strings in infile.
Stringsort should call the template sorting function g_merge_sort from mergesort.h using one of these two calls:
#include <mergesort.h> ... fsu::g_merge_sort(a, a + n); // array case fsu::g_merge_sort(v.begin(), v.end()); // std::vector case ...
where a is an array of strings or v is a std::vector of strings, respectively. The choice of using arrays or vectors is yours.
All of your test code code can be compiled with the following makefile:
# makefile for assessing xstring.cpp all: fstring.x fstringb.x stringsort.x fstring.x: fstring.o xstring.h xstring.o g++ -ofstring.x fstring.o xstring.o fstringb.x: fstringb.o xstring.h xstring.o g++ -ofstringb.x fstringb.o xstring.o stringsort.x: stringsort.o xstring.h xstring.o g++ -ostringsort.x stringsort.o xstring.o stringsort.o: stringsort.cpp xstring.h mergesort.h g++ -Wall -Wextra -I. -c stringsort.cpp xstring.o: xstring.h xstring.cpp g++ -Wall -Wextra -I. -c xstring.cpp fstring.o: xstring.h fstring.cpp g++ -Wall -Wextra -I. -c fstring.cpp fstringb.o: xstring.h fstringb.cpp g++ -Wall -Wextra -I. -c fstringb.cpp
Be certain that you are using the distributed header file and test clients, as these will be provided independently for the assessment.
As is often the case, I/O poses some complexity. The reading of all strings from a file can be accomplished using either an array or a std::vector as the internal storage mechanism. The following loop reads strings and puts them in a vector:
fsu::String string; std::vector <fsu::String> v; // vector while (ifs >> string) v.push_back(string);
The following loop reads strings and puts them in an array:
fsu::String string; fsu::String a [maxArraySize]; // array size_t count = 0; while (ifs >> string && count < maxArraySize) { a[count] = string; ++count; }
The array method must deal with the "fixed size" nature of arrays and hence limit the maximum number of strings in the input file to maxArraySize, a constant declared at the top of the program. You may set this constant to 1000. The vector method has no such limitation and is arguably easier to code, nevertheless if you are more comfortable with arrays you may follow that direction.
Your code will be assessed using fstringb, stringsort, and a variety of command files. Be creative in testing your code: consider various commands and sequences of commands that exercise the most complex features of fsu::String.
The object code file xstring_i.o is released in the assignment directory. This gives a way to create and test your stringsort.cpp using a known correct implementation of xstring.h.
There are sample executables:
area51/fastring_i.x area51/fastring_s.x area51/stringsort_i.x area51/stringsort_s.x