In: Computer Science
C++
For this assignment, you will implement the MyString class. Like the string class in C++’s standard library, this class uses C-strings as the underlying data structure. Recall that a C-string is a null-terminated array of type char. See section 8.1 in Savitch for more information about C-strings; in particular, you will find it helpful to take advantage of several of the C-string functions mentioned in that section. What To Do. In the hw8 directory that is created, you will find the following files: • mystring.h and mystring.cpp • a Makefile • and 4 test files (test1.cpp through test4.cpp). (Below are the files mentioned here, with one sample file). Implement the following: 1. a default constructor 2. a constructor that takes a const char * parameter (that is, a C-string) 3. a destructor 4. a copy constructor 5. the assignment operator. In addition, overload the following relational operators: >, <, >=, <=, ==, and !=. Lastly, overload the operator+ (concatenation). All of the relational operators return type int. To understand why, read the description of the C-string function strcmp. All of the comparisons should be lexicographical, i.e., similar to what strcmp() does. The == and != operators should evaluate to 1 if the condition is true, 0 if false. You are welcome to implement some of the operators by using others (for example, you can easily implement != using ==). Make sure that you can invoke the operators with string literals on either side of the operator. That is, both of the following expressions should be valid: str == "hello" "hello" == str where str is a MyString object. Place the member function implementations in mystring.cpp and compile using make. You can also edit mystring.h if you wish to implement some of the member functions directly in the class definition
Make File:
CC = g++
CXX = g++
INCLUDES =
CFLAGS = -Wall $(INCLUDES)
CXXFLAGS = -Wall $(INCLUDES)
LDFLAGS =
LDLIBS =
executables = test1 test2 test3 test4
objects = mystring.o test1.o test2.o test3.o test4.o
.PHONY: default
default: $(executables)
$(executables): mystring.o
$(objects): mystring.h
.PHONY: clean
clean:
rm -f *~ a.out core $(objects) $(executables)
.PHONY: all
all: clean default
mystring.cpp:
#include
#include
#include "mystring.h"
// Insertion (put-to) operator
std::ostream& operator<<(std::ostream& outs, const MyString& s)
{
outs << s.data;
return outs;
}
// Extraction (get-from) operator
std::istream& operator>>(std::istream& is, MyString& s)
{
// Though this cheats a bit, it's meant to illustrate how this
// function can work.
std::string temp;
is >> temp;
delete[] s.data;
s.len = strlen(temp.c_str());
s.data = new char[s.len+1];
strcpy(s.data, temp.c_str());
return is;
}
mystring.h:
#ifndef _MYSTRING_H_
#define _MYSTRING_H_
#include
class MyString {
public:
// default constructor
MyString();
// constructor
MyString(const char* p);
// destructor
~MyString();
// copy constructor
MyString(const MyString& s);
// assignment operator
MyString& operator=(const MyString& s);
// returns the length of the string
int length() const { return len; }
// insertion (or put-to) operator
friend std::ostream& operator<<(std::ostream& outs, const MyString& s);
// extraction (or get-from) operator
friend std::istream& operator>>(std::istream& is, MyString& s);
// concatenates two strings
friend MyString operator+(const MyString& s1, const MyString& s2);
// relational operators
friend int operator<(const MyString& s1, const MyString& s2);
friend int operator>(const MyString& s1, const MyString& s2);
friend int operator==(const MyString& s1, const MyString& s2);
friend int operator!=(const MyString& s1, const MyString& s2);
friend int operator<=(const MyString& s1, const MyString& s2);
friend int operator>=(const MyString& s1, const MyString& s2);
private:
char* data;
int len;
};
#endif
Here is a sample test file:
#include "mystring.h"
static MyString add(MyString s1, MyString s2)
{
MyString temp(" and ");
return s1 + temp + s2;
}
int main()
{
using namespace std;
MyString s1("one");
MyString s2("two");
MyString s3 = add(s1, s2);
cout << s3 << endl;
return 0;
}
// mystring.h
#ifndef _MYSTRING_H_
#define _MYSTRING_H_
#include <iostream>
class MyString {
public:
// default constructor
MyString();
// constructor
MyString(const char* p);
// destructor
~MyString();
// copy constructor
MyString(const MyString& s);
// assignment operator
MyString& operator=(const MyString& s);
// returns the length of the string
int length() const { return len; }
// insertion (or put-to) operator
friend std::ostream& operator<<(std::ostream& outs, const MyString& s);
// extraction (or get-from) operator
friend std::istream& operator>>(std::istream& is, MyString& s);
// concatenates two strings
friend MyString operator+(const MyString& s1, const MyString& s2);
// relational operators
friend int operator<(const MyString& s1, const MyString& s2);
friend int operator>(const MyString& s1, const MyString& s2);
friend int operator==(const MyString& s1, const MyString& s2);
friend int operator!=(const MyString& s1, const MyString& s2);
friend int operator<=(const MyString& s1, const MyString& s2);
friend int operator>=(const MyString& s1, const MyString& s2);
private:
char* data;
int len;
};
#endif
//end of mystring.h
// mystring.cpp
#include <string>
#include <cstring>
#include "mystring.h"
MyString::MyString()
{
data = '\0'; // initialize an empty string
len = 0;
}
MyString::MyString(const char* p)
{
len = strlen(p);
data = new char[strlen(p)+1];
strcpy(data,p);
}
MyString::~MyString()
{
delete data;
}
MyString::MyString(const MyString& s)
{
len = s.len;
data = new char[len];
strcpy(data,s.data);
}
MyString& MyString::operator=(const MyString& s)
{
if(this != &s)
{
delete data;
len = s.len;
data = new char[len];
strcpy(data,s.data);
}
return *this;
}
MyString operator+(const MyString& s1, const MyString&
s2)
{
char *p = new char[s1.length() + s2.length()+1];
int len = s1.length() + s2.length();
int i=0, j=0;
for(;i<s1.length();i++)
p[i] = s1.data[i];
for(;i<len;i++,j++)
p[i] = s2.data[j];
p[i] = '\0';
MyString sAdd(p);
return sAdd;
}
int operator<(const MyString& s1, const MyString&
s2)
{
return (strcmp(s1.data,s2.data) < 0);
}
int operator>(const MyString& s1, const MyString&
s2)
{
return (strcmp(s1.data,s2.data) > 0);
}
int operator==(const MyString& s1, const MyString&
s2)
{
return (strcmp(s1.data,s2.data) == 0);
}
int operator!=(const MyString& s1, const MyString&
s2)
{
return(!(s1 == s2));
}
int operator<=(const MyString& s1, const MyString&
s2)
{
return (strcmp(s1.data,s2.data) <= 0);
}
int operator>=(const MyString& s1, const MyString&
s2)
{
return (strcmp(s1.data,s2.data) >= 0);
}
// Insertion (put-to) operator
std::ostream& operator<<(std::ostream& outs, const
MyString& s)
{
outs << s.data;
return outs;
}
// Extraction (get-from) operator
std::istream& operator>>(std::istream& is,
MyString& s)
{
// Though this cheats a bit, it's meant to illustrate how this
// function can work.
std::string temp;
is >> temp;
delete[] s.data;
s.len = strlen(temp.c_str());
s.data = new char[s.len+1];
strcpy(s.data, temp.c_str());
return is;
}
//end of mystring.cpp
// main.cpp : C++ program to test the MyString class
#include "mystring.h"
static MyString add(MyString s1, MyString s2)
{
MyString temp(" and ");
return s1 + temp + s2;
}
int main()
{
using namespace std;
MyString s1("one");
MyString s2("two");
MyString s3 = add(s1, s2);
cout << s3 << endl;
return 0;
}
//end of main.cpp
Output: