String Class Implementation


Earlier in this book you were introduced to the C++ standard library
class. The string class automatically handles many of the tedious tasks involved in using strings,
string such as dynamic memory allocation, and bounds checking. It also overloads operators,
such as and , and offers many member functions that ease the job of working with + =
strings. In this section, however, you will learn to write your own string handling class. In
the process, you will see examples of the copy constructor and overloaded operators in
full action.

The MyString Class
The class defined in this section is an abstract data type for handling strings. It
MyString offers several advantages over standard C++ character array manipulation:

• Memory is dynamically allocated for any string stored in a object. The MyString programmer using this class doesn’t need to be concerned with how large to make
an array.
• Strings may be assigned to a object with the = operator. The program-
MyString mer using this class does not have to call the function.
strcpy
• One string may be concatenated to another with the += operator. This eliminates the need for the function.
strcat
• Strings may be tested with the relational operators. The programmer using this class doesn’t have to call the function.

strcmp

The following program listings show the class implementation.
Contents of
MyString.h

// Specification file for the MyString class

#ifndef MYSTRING_H

#define MYSTRING_H

#include

using namespace std;




Creating a String Class

class MyString; // Forward declaration.

ostream &operator<<(ostream &, const MyString &);

istream &operator>>(istream &, MyString &);


// MyString class. An abstract data type for handling strings.


class MyString

{

private:

char *str;

int len;

public:

// Default constructor

MyString()

{ str = NULL; len = ; }


// Copy constructor

MyString(MyString &right)

{ str = new char[right.length() + ];

strcpy(str, right.getValue());

len = right.length(); }


// The following constructor initializes the

// MyString object with a C-string

MyString(char *sptr)

{ len = strlen(sptr);

str = new char[len + ];

strcpy(str, sptr); }


// Destructor

~MyString()

{ if (len != ) delete [] str; }


// The length function returns the string length.

int length() const

{ return len; }


// The getValue function returns the string.

const char *getValue() const

{ return str; };


// Overloaded operators

const MyString operator+=(MyString &);

const char *operator+=(const char *);

const MyString operator=(MyString &);

const char *operator=(const char *);

int operator==(MyString &);

int operator==(const char *);

int operator!=(MyString &);

int operator!=(const char *);

bool operator>(MyString &);

bool operator>(const char *);

bool operator<(MyString &);


Creating a String Class

bool operator<(const char *);

bool operator>=(MyString &);

bool operator>=(const char*);

bool operator<=(MyString &);

bool operator<=(const char *);


// Friends

friend ostream &operator<<(ostream &, const MyString &);

friend istream &operator>>(istream &, MyString &);

};


#endif
Contents of
MyString.cpp

// Implementation file for the MyString class

#include // For string library functions

#include "MyString.h"

using namespace std;


//*************************************************

// Overloaded = operator. Called when operand *

// on the right is another MyString object. *

// Returns the calling object. *

//*************************************************


const MyString MyString::operator=(MyString &right)

{

if (len != )

delete [] str;

str = new char[right.length() + ];

strcpy(str, right.getValue());

len = right.length();

return *this;

}


//*************************************************

// Overloaded = operator. Called when operand *

// on the right is a C-string. *

// Returns the str member of the calling object. *

//*************************************************


const char *MyString::operator=(const char *right)

{

if (len != )

delete [] str;

len = strlen(right);

str = new char[len + ];

strcpy(str, right);

return str;

}



Creating a String Class

//*************************************************

// Overloaded += operator. Called when operand *

// on the right is another MyString object. *

// Concatenates the str member of right to the *

// str member of the calling object. *

// Returns the calling object. *

//*************************************************


const MyString MyString::operator+=(MyString &right)

{

char *temp = str;


str = new char[strlen(str) + right.length() + ];

strcpy(str, temp);

strcat(str, right.getValue());

if (len != )

delete [] temp;

len = strlen(str);

return *this;

}


//*************************************************

// Overloaded += operator. Called when operand *

// on the right is a string. Concatenates the *

// str member of right to the str member of *

// the calling object. *

// Returns the str member of the calling object. *

//*************************************************


const char *MyString::operator+=(const char *right)

{

char *temp = str;


str = new char[strlen(str) + strlen(right) + ];

strcpy(str, temp);

strcat(str, right);

if (len != )

delete [] temp;

return str;

}


//*****************************************************

// Overloaded == operator. *

// Called when the operand on the right is a MyString *

// object. Returns if right.str is the same as str. *

//*****************************************************


int MyString::operator==(MyString &right)

{

return !strcmp(str, right.getValue());

}



Creating a String Class

//****************************************************

// Overloaded == operator. *

// Called when the operand on the right is a string. *

// Returns if right is the same as str. *

//****************************************************


int MyString::operator==(const char *right)

{

return !strcmp(str, right);

}


//*********************************************************

// Overloaded != operator. *

// Called when the operand on the right is a MyString *

// object. Returns true if right.str is not equal to str. *

//*********************************************************


int MyString::operator!=(MyString &right)

{

return strcmp(str, right.getValue());

}


//****************************************************

// Overloaded != operator. *

// Called when the operand on the right is a string. *

// Returns true if right is not equal to str. *

//****************************************************


int MyString::operator!=(const char *right)

{

return strcmp(str, right);

}


//*********************************************************

// Overloaded > operator. *

// Called when the operand on the right is a MyString *

// object. Returns true if str is greater than right.str. *

//*********************************************************


bool MyString::operator>(MyString &right)

{

bool status;


if (strcmp(str, right.getValue()) > )

status = true;

else

status = false;

return status;

}


//****************************************************

// Overloaded > operator. *

// Called when the operand on the right is a string. *

// Returns true if str is greater than right. *

//****************************************************



Creating a String Class

bool MyString::operator>(const char *right)

{

bool status;


if (strcmp(str, right) > )

status = true;

else

status = false;

return status;

}


//******************************************************

// Overloaded < operator. *

// Called when the operand on the right is a MyString *

// object. Returns true if str is less than right.str. *

//******************************************************


bool MyString::operator<(MyString &right)

{

bool status;


if (strcmp(str, right.getValue()) < )

status = true;

else

status = false;

return status;

}


//****************************************************

// Overloaded < operator. *

// Called when the operand on the right is a string. *

// Returns true if str is less than right. *

//****************************************************


bool MyString::operator<(const char *right)

{

bool status;


if (strcmp(str, right) < )

status = true;

else

status = false;

return status;

}


//*****************************************************

// Overloaded >= operator. *

// Called when the operand on the right is a MyString *

// object. Returns true if str is greater than or *

// equal to right.str *

//*****************************************************


bool MyString::operator>=(MyString &right)

{

bool status;



Creating a String Class

if (strcmp(str, right.getValue()) >= )

status = true;

else

status = false;

return status;

}


//*********************************************************

// Overloaded >= operator. *

// Called when the operand on the right is a string. *

// Returns true if str is greater than or equal to right. *

//*********************************************************


bool MyString::operator>=(const char *right)

{

bool status;


if (strcmp(str, right) >= )

status = true;

else

status = false;

return status;

}


//**********************************************************

// Overloaded <= operator. *

// Called when the operand on the right is a MyString *

// object. Returns true if right.str is less than or equal *

// to right.str. *

//**********************************************************


bool MyString::operator<=(MyString &right)

{

bool status;


if (strcmp(str, right.getValue()) <= )

status = true;

else

status = false;

return status;

}


//******************************************************

// Overloaded <= operator. *

// Called when the operand on the right is a string. *

// Returns true if str is less than or equal to right. *

//******************************************************


bool MyString::operator<=(const char *right)

{

bool status;


if (strcmp(str, right) <= )

status = true;

else

status = false;


Creating a String Class

return status;

}


//*************************************************

// Overloaded stream insertion operator (<<). *

//*************************************************


ostream &operator<<(ostream &strm, const MyString &obj)

{

strm << obj.str;

return strm;

}


//*************************************************

// Overloaded stream extraction operator (>>). *

//*************************************************


istream &operator>>(istream &strm, MyString &obj)

{

strm.getline(obj.str, obj.len);

strm.ignore();

return strm;

}
The Copy Constructor
Because the
class has a pointer as a member and dynamically allocates memory
MyString
to store its string value, a copy constructor is provided. This function will cause the object
to properly set up its data when initialized with another
object.
MyString
The Overloaded = Operators
The
class has two overloaded = operators. The first is for assigning one
MyString
object to another. This operator function is called when the operand on the
MyString
right of the = sign is a
object, as shown in the following code segment:
MyString
MyString first("Hello"), second;
second = first;
The second version of
’s = operator is for assigning a traditional C-string to a
MyString
object. This operator function is called when the operand on the right of = is a
MyString
string literal or any pointer to a C-string (such as the name of a char array). This is shown
in the following program segment:
MyString name;
char who[] = "Jimmy";
name = who;
The Overloaded += Operators
The += operator is designed to concatenate the string on its right to the
object
MyString
on its left. Like the = operators,
has two versions of +=. The first version is
MyString
designed to work when the right operand is another
object, as shown in the fol-
MyString
lowing program segment:


Creating a String Class
MyString first("Hello "), second("world");
first += second;
The second version of the += operator will be called when the right operand is a literal
string or any pointer to a character. It is shown here:
MyString first("Hello ");
first += "World";
The Overloaded == Operators
The
object has overloaded versions of the == operator for performing equality
MyString
tests. Like the other operators, the first version is designed to work with another
object and the second is designed to work with a traditional C-string.
MyString
The
operator functions return an integer that can be treated as a Boolean value. Both
==
functions use
to compare the operands, and then returns the negative of
’s
strcmp
strcmp
return value. (Recall that
uses inverted logic: It returns when its arguments are
strcmp
equal, and returns a nonzero value when they are not equal.) So, these operator functions
return
if the string contained in the right operand matches the
member of the
true
str
calling object. If the strings of the two operands do not match, the functions return
.
false
These operator functions allow the programmer using this class to construct relational
expressions such as those shown in the following program segments:
MyString name("John"), name("John");
if (name == name)
cout << "The names are the same.\n";
else
cout << "The names are different.\n";
MyString name("John");
if (name == "Jon")
cout << "The names are the same.\n";
else
cout << "The names are different.\n";
The Overloaded > and < Operators
The
object has two overloaded versions of the
operator for performing
MyString
>
greater-than tests, and the < operator for performing less-than tests. The first version of
each is designed to work with another
object and the second is designed to
MyString
work with a traditional C-string. (The functions use the library function
to deter-
strcmp
mine if a greater-than or less-than relationship exists.)
The > functions return a
if the
member of the calling object is greater than the
true
str
string contained in the right operand. Otherwise, the functions return
. The < func-
false
tions return a
if the
member of the calling object is less than the string contained
true
str
in the right operand. Otherwise, they return
.
false
These operator functions allow the programmer using this class to construct relational
expressions such as those shown in the following program segments:
MyString name("John"), name("Jon");
if (name > name)


Creating a String Class
cout << "John is greater than Jon.\n";
else
cout << "John is not greater than Jon.\n";
MyString name("John");
if (name < "Jon")
cout << "John is less than Jon.\n";
else
cout << "John is not greater than Jon.\n";
The Overloaded >= and <= Operators
The
object has two overloaded versions of the >= operator for performing
MyString
greater-than or equal-to tests, and the <= operator for performing less-than or equal-to
tests. The first version of each is designed to work with another
object and the
MyString
second is designed to work with a traditional C-string. (The functions use the library func-
tion
to determine if a greater-than or less-than relationship exists.)
strcmp
The >= functions return a
if the
member of the calling object is greater than or
true
str
equal to the string contained in the right operand. Otherwise, the functions return
.
false
The <= functions return
if the
member of the calling object is less than or equal
true
str
to the string contained in the right operand. Otherwise, they return
.
false
These operator functions allow the programmer using this class to construct relational
expressions such as those shown in the following program segments:
MyString name("John"), name("Jon");
if (name >= name)
cout << "John is greater than or equal to Jon.\n";
else
cout << "John is not greater than or equal to Jon.\n";
MyString name("John");
if (name <= "Jon")
cout << "John is less than or equal to Jon.\n";
else
cout << "John is not less than or equal to Jon.\n";
Program - shows how
’s += operator performs string concatenation. Addi-
MyString
tionally, the program’s source code demonstrates how
allows the programmer
MyString
to treat strings much like any other built-in data type.
Program -

// This program demonstrates the MyString class.

#include

#include "MyString.h"


int main()

{

// Define and initialize several MyString objects.

MyString object("This"), object("is");

MyString object("a test.");

MyString object = object;

MyString object("is only a test.");
(program continues)


Creating a String Class
Program -
(continued)

// Define a C-string.

char string[] = "a test.";


// Display the MyString objects.

cout << "object: " << object << endl;

cout << "object: " << object << endl;

cout << "object: " << object << endl;

cout << "object: " << object << endl;

cout << "object: " << object << endl;


// Display the C-string.

cout << "string: " << string << endl;


// Test the overloaded += operator.

object += " ";

object += object;

object += " ";

object += object;

object += " ";

object += object;

object += " ";

object += object;

cout << "object: " << object << endl;


return ;

}
Program Output
object: This
object: is
object: a test.
object: This
object: is only a test.
string: a test.
object: This is a test. This is only a test.
Program - shows how
’s relational operators can be used to compare
MyString
strings with the same ease that numeric data types are compared.
Program -

// This program demonstrates the MyString class.

#include

#include "MyString.h"

using namespace std;


int main()

{

// Define several MyString objects.

MyString name("Billy"), name("Sue");

MyString name("joe");

MyString string("ABC"), string("DEF");

(program continues)

Creating a String Class
Program -
(continued)

// Display the MyString object values.

cout << "name: " << name.getValue() << endl;

cout << "name: " << name.getValue() << endl;

cout << "name: " << name.getValue() << endl;

cout << "string: " << string.getValue() << endl;

cout << "string: " << string.getValue() << endl;


// Test the overloaded relational operators.

if (name == name)

cout << "name is equal to name.\n";

else

cout << "name is not equal to name.\n";


if (name == "joe")

cout << "name is equal to joe.\n";

else

cout << "name is not equal to joe.\n";


if (string > string)

cout << "string is greater than string.\n";

else

cout << "string is not greater than string.\n";


if (string < string)

cout << "string is less than string.\n";

else

cout << "string is not less than string.\n";


if (string >= string)

cout << "string is greater than or equal to string.\n";

else

cout << "string is not greater than or equal to string.\n";


if (string >= "ABC")

cout << "string is greater than or equal to ABC.\n";

else

cout << "string is not greater than or equal to ABC.\n";


if (string <= string)

cout << "string is less than or equal to string.\n";

else

cout << "string is not less than or equal to string.\n";


if (string <= "DEF")

cout << "string is less than or equal to DEF.\n";

else

cout << "string is not less than or equal to DEF.\n";


return ;

}


Creating a String Class
Program -
(continued)
Program Output
name: Billy
name: Sue
name: joe
string: ABC
string: DEF
name is not equal to name.
name is equal to joe.
string is not greater than string.
string is less than string.
string is not greater than or equal to string.
string is greater than or equal to ABC.
string is less than or equal to string.
string is less than or equal to DEF.


No comments: