COP 3330 - Programming Assignment #5
Due: Thurs, Mar 27
Objective
Upon completion of this program, you should gain
experience with managing dynamic memory allocation inside a class, as
well as further experience with operator overloading.
The code for this assignment should be portable -- make sure you test
with g++ on linprog.cs.fsu.edu before you submit.
Task
Create a class called MyString -- this will be a string
class, which allows creation of string objects that have flexible sizes,
intuitive operator syntax (through operator overloads), and other useful
features. Your class will need to maintain the string internally as an
array of characters, and since string sizes are not fixed, dynamic
allocation techniques will need to be used in the class. Your class
should maintain any string ojbect in a valid state at all times, and it
should not allow any memory leaks.
The class should be written in the files mystring.h and
mystring.cpp. I have provided a starter version of the file
mystring.h, which already has many of the required features
(i.e. the interface for users) declared. Do not change the prototypes of
the already-declared functions. The following link is a copy of the
starter file -- right-click and "Save": mystring.h
Important Note: Since the intention of this assignment is for
you to write a string class, you may NOT use the
<string> class library in the creation of this
assignment! Use of the standard C++ <string> library
will result in an automatic 0 grade. The point here is to learn how to
go about building such a library yourself.
Details and Requirements
Data
Your class must allow for storage of a flexibly-sized string of
characters. Make sure to declare any appropriate member data variables
in the header file. All member data of your class must be private.
Function descriptions
- Standard Constructors
- The default constructor should set the object to
represent an empty string.
- MyString(const char* ) -- this is a conversion
constructor. A c-string will be passed as a parameter, and this
constructor should set up the string object to store that string
inside. This will enable type conversions from c-strings to MyString
objects.
- MyString(int ) -- this is a conversion constructor that
should convert an integer value to a string representation. For
example, if the value 1234 is passed in, the MyString object should now store
the same string data that would be represented by the c-string "1234"
Note that these last two constructors will allow automatic type
conversions to take place -- in this case, conversions from int
to MyString and from c-style strings to type MyString
-- when appropriate. This makes our operator overloads more versatile,
as well. For example, the conversion constructor allows the following
statements to work (assuming appropriate definitions of the assignment
operator and + overloads described later):
MyString s1 = "Hello, World";
MyString s2 = 12345;
MyString s3 = s1 + 15; // concatenation "Hello, World15"
- Automatics
Since dynamic allocation is necessary, you will need to write
appropriate definitions of the special functions (the "automatics"):
destructor, copy constructor, assignment operator. The destructor
should clean up any dynamic memory when a MyString object is
deallocated.
The copy constructor and assignment operator should both be defined to
make a "deep copy" of the object (copying all dynamic data, in addition
to regular member data), using appropriate techniques. Make sure
that none of these functions will ever allow memory "leaks" in a program.
- I/O functions
- operator << -- insertion operator. This should print
out the data from the MyString object, using the standard insertion
operator syntax. There should be no extra formatting -- only the
string stored in the object is printed (no newlines, extra spacing,
etc).
- operator >> -- extraction operator. This should read a
string from an input stream. This operator should ignore any leading
white space before the string data, then read until the next white
space is encountered. Prior data in the MyString object is
discarded. Note: Just like the operator>> for c-strings,
this will only read one word at time.
- getline functions. These should read a string from an input
stream. This operator should read everything from the input stream
(first parameter) into
the MyString object (second parameter) until the specified delimiter
character is
encountered. In the version of the function with 3 parameters, the
third parameter is the delimiter. In the version of the function with
2 parameters, the delimiter should be the newline '\n'. In
either case, prior data in the MyString object is discarded.
- Comparison operators
Write overloads for all 6 of the comparison operators (
< , > , <= , >= , == , != ). Each of these operations
should test two objects of type MyString and return an
indication of true or false.
You are testing the MyString objects for order and/or equality based
on the usual meaning of order and equality for c-strings, which is
lexicographic ordering. Remember that this is based on the order of the
ascii characters themselves, so it's not exactly the same as pure
"alphabetical" ordering.
Examples:
"apple" < "apply"
"Zebra" < "apple" // uppercase letters come before lowercase
"apple" == "apple" // same strings
- Concatenation operators
- operator+ -- this should concatenate the two operands
together and return a new MyString as a result.
- operator+= -- this should concatenate the second operand
onto the first one (i.e. changing the first one)
Examples:
MyString s1 = "Dog";
MyString s2 = "food";
MyString s3 = s1 + s2; // s3 is "Dogfood" and s1, s2 are not changed
s1 += s2; // s1 is now "Dogfood"
- Bracket operators
The bracket operator overloads have these prototypes:
char& operator[] (unsigned int index); // returns L-value
const char& operator[] (unsigned int index) const; // read-only return
Both of these should return the character at the given index position.
Note that the first one returns the character by reference, so it allows
the slot to be changed. The second returns by const reference
and is a const member function and will run in
read-only situations -- calls on const objects. Example calls:
const MyString s = "I love Java";
MyString t = "I love C++";
// these two calls use the const version above
char ch = s[4]; // ch now stores 'v'
ch = s[7]; // ch now stores 'J'
// these calls use the non-const version above
t[0] = 'U'; // s is now "U love C++"
t[3] = 'i'; // s is now "U live C++"
Note that since the parameter in each is an unsigned int, it's
not possible to have a negative array index passed in. If the index
passed to the function is too big (out of bounds for what's currently
stored), then:
- The read-only/const version should just return the null character '\0'
- The L-value version should resize the stored string to accomodate
the specified index. All new slots between the end of the prior
string and the new index location should be set to spaces
Examples:
const MyString s = "Howdy"; // length of s is 5 characters
char ch = s[10]; // ch now stores '\0'
MyString t = "Hello"; // length of t is 5 characters
t[7] = 'b'; // t is now "Hello b" (length is now 8)
- Standard accessors
getLength should return the length of the stored string
(i.e. number of characters). For example, "Hello" has 5 characters
getCString should return the actual stored data as a
c-string (i.e. null-terminated char array)
- substring functions
There are two versions of substring -- a 1 parameter
version and a 2-parameter version. Both should return a
MyString object that consists of a portion (or "substring") of
the original string. Neither should change the calling object. The
first parameter represents the starting index of the substring. In the
2-parameter version, the second parameter gives the length of the
substring to return (if the length is too long, default to the rest of
the string ). In the 1-parameter version, the substring consists of the
characters from the start index to the end of the string.
Examples:
MyString s = "Greetings, Earthling!";
MyString x, y, z;
x = s.substring(4); // x is now "tings, Earthling!"
y = s.substring(3, 5); // y is now "eting"
z = s.substring(16, 10); // z is now "ling!"
- insert() function
This function should change the calling object by inserting the data
from the second parameter AT the index given by the first parameter. If
the index is out of bounds (longer than the string's length), then just
insert at the end. This function should also return the calling object.
Examples:
MyString s = "Hello world";
s.insert(6, "cruel "); // s is now "Hello cruel world"
s.insert(20, "!!!"); // s is now "Hello cruel world!!!"
- indexOf function
This function should search through the MyString to find the first
occurence of the pattern or substring given in the parameter. The
function should return the first index where it was found, or it should
return -1 if the pattern is NOT found.
Examples:
MyString s = "The bobcat likes to concatenate";
int x = s.indexOf("cat"); // x is now 7
x = s.indexOf("dog"); // x is now -1
General Requirements
- As usual, no global variables. If you use any constants in the
class, make them static
- All member data should be private
- Use appropriate good programming practices as denoted on previous
assignments
- Since the only output involved with your class will be in the
<< overload, your output must match mine exactly when running test
programs.
- You may NOT use classes from the STL (Standard
Template Library) -- this includes class <string> -- as the
whole point of this assignment is for you to learn how to manage dynamic
memory issues inside of a class yourself, not rely on STL classes or the
string class to do it for you.
- You may use standard I/O libraries like iostream and
iomanip, as well as the common C libraries cstring and
cctype
Extra Credit:
Create an overloaded version of the - operator to "subtract" two
MyString objects. The meaning of - is that it should return a
MyString object that is the result of taking the first string and
removing all instances of the second string from it.
Examples:
MyString s = "The bobcat concatenated the catapult with the catamaran";
MyString t = "cat";
MyString result = s - t;
// result now stores "The bob conenated the apult with the amaran";
Hints and Tips:
Sample main program
It will be up to you to write 1 or more test programs to test out the
features of your class.
Here is a sample driver program where you can see a handful of tests
to various functions: driver.cpp.
Please note that this is not a complete and thorough set of tests, so
you
will still
need to write your own test calls to test your class more thoroughly.
This driver program is provided to give you a better idea of how some of
these functions can be called.
You can see the results from a sample run (on this driver program) at
this link: sampleout.txt.
Note that the one place that asks for user input, the input was:
John was here, but not there
The rest of the sample test cases are hard-coded calls.
Submit the following files (using the usual web submission procedure):
mystring.h
mystring.cpp