In: Computer Science
Using either your own C-string functions of Lab 7.1 or the ones from the standrd C++ cstring library, create a String class, which — while having minimal functionality — illustrates the use of and need for the canonical form.
Overview
Here is the .h file for the class (note the class name — String with a capital S; trying to force the use of the classname string was to much of an issue:
class String { friend std::ostream &operator <<(std::ostream &os, const String &s); friend String operator +(const String &s1, const String &s2); public: String(const char *cs=""); String(const String &s); ~String(); String &operator =(const String &rhs); char &operator [](int index); String &operator +=(const String &s); int length() const; private: char *cs; };
I've also supplied a String_Exception class and an app for testing your class (it will be the test driver once I get it all into Codelab).
Implementation Notes
String::String(const char *cs) : cs(new char[strlen(cs)+1) { // the +1 is for the null terminator
#ifndef MYSTRING_H #define MYSTRING_H #include <iostream> class String { friend std::ostream &operator <<(std::ostream &os, const String &s); // friend bool operator ==(const String &s1, const String &s2); friend String operator +(const String &s1, const String &s2); public: String(const char *cs=""); String(const String &s); ~String(); String &operator =(const String &rhs); char &operator [](int index); String &operator +=(const String &s); // int find(char c) const; int length() const; // void clear(); private: char *cs; }; #endif
mystring_app.cpp
#include <iostream> #include <sys/sysinfo.h> #include <cstdlib> #include "mystring.h" using namespace std; int main() { String s = "Hello"; cout << "s: " << s << " (" << s.length() << ")" << endl; cout << "s + \" world\": " << s + " world" << endl; cout << "s[1]: " << s[1] << endl; String s1 = s; // making sure copy constructor makes deep copy String s2; s2 = s; // making sure assignment operator makes deep copy s[0] = 'j'; cout << endl; cout << "s: " << s << " (" << s.length() << ")" << endl; cout << "s1: " << s1 << " (" << s1.length() << ")" << endl; cout << "s2: " << s2 << " (" << s2.length() << ")" << endl; cout << endl; for (int i = 0; i < 5; i++) { s += s; cout << "s: " << s << " (" << s.length() << ")" << endl; } cout << endl; for (int i = 0; i < 5; i++) s += s; cout << "s: " << s << " (" << s.length() << ")" << endl; return 0; } mystring_exception.cpp
#ifndef MYSTRING_EXCEPTION #define MYSTRING_EXCEPTION #include <string> // Note this is the C++ string class! class String_Exception { public: String_Exception(std::string what) : what(what) {} std::string getWhat() {return what;} private: std::string what; }; #endif
// mystring_exception.cpp
#ifndef MYSTRING_EXCEPTION
#define MYSTRING_EXCEPTION
#include <string> // Note this is the C++ string class!
class String_Exception {
public:
String_Exception(std::string what) : what(what) {}
std::string getWhat() {return what;}
private:
std::string what;
};
#endif
//end of mystring_exception.cpp
// mystring.h
#ifndef MYSTRING_H
#define MYSTRING_H
#include <iostream>
class String {
friend std::ostream &operator <<(std::ostream &os,
const String &s);
// friend bool operator ==(const String &s1, const String
&s2);
friend String operator +(const String &s1, const String
&s2);
public:
String(const char *cs="");
String(const String &s);
~String();
String &operator =(const String &rhs);
char &operator [](int index);
String &operator +=(const String &s);
// int find(char c) const;
int length() const;
// void clear();
private:
char *cs;
};
#endif
//end of mystring.h
// mystring.cpp
#include "mystring.h"
#include "mystring_exception.cpp"
#include <cstring>
using namespace std;
String::String(const char *cs)
{
this->cs = new char[strlen(cs)+1];
strcpy(this->cs,cs);
}
String::String(const String &s)
{
cs = new char[length()+1];
strcpy(cs,s.cs);
}
String::~String()
{
delete cs;
}
String& String::operator =(const String &rhs)
{
if(this != &rhs)
{
delete cs;
cs = new char[rhs.length()];
strcpy(cs,rhs.cs);
}
return *this;
}
char & String::operator [](int index)
{
try{
if(index >=0 && index
< length())
{
return
cs[index];
}else
throw
String_Exception("Index out of bounds");
}catch(String_Exception &e)
{
cout<<e.getWhat();
}
}
String & String::operator +=(const String &s)
{
char *temp = new char[length()+s.length()+1];
strcpy(temp,cs);
strcat(temp,s.cs);
delete cs;
this->cs = temp;
return *this;
}
int String::length() const
{
return strlen(cs);
}
std::ostream &operator <<(std::ostream &os, const
String &s)
{
os<<s.cs;
return os;
}
String operator +(const String &s1, const String
&s2)
{
char *temp = new char[s1.length()+s2.length()+1];
strcpy(temp,s1.cs);
strcat(temp,s2.cs);
return String(temp);
}
//end of mystring.cpp
// mystring_app.cpp
#include "mystring.h"
#include <sys/sysinfo.h>
#include <cstdlib>
#include "mystring.h"
using namespace std;
int main() {
String s = "Hello";
cout << "s: " << s << " (" << s.length() << ")" << endl;
cout << "s + \" world\": " << s + " world" << endl;
cout << "s[1]: " << s[1] << endl;
String s1 = s; // making sure copy constructor makes deep
copy
String s2;
s2 = s; // making sure assignment operator makes deep copy
s[0] = 'j';
cout << endl;
cout << "s: " << s << " (" << s.length()
<< ")" << endl;
cout << "s1: " << s1 << " (" << s1.length()
<< ")" << endl;
cout << "s2: " << s2 << " (" << s2.length()
<< ")" << endl;
cout << endl;
for (int i = 0; i < 5; i++) {
s += s;
cout << "s: " << s << " (" << s.length()
<< ")" << endl;
}
cout << endl;
for (int i = 0; i < 5; i++)
s += s;
cout << "s: " << s << " (" << s.length()
<< ")" << endl;
return 0;
}
//end of mystring_app.cpp
Output: