// CSE 374 Lecture 23 code // courtesy of Hal Perkins // Implementation of a simple string class. #include #include #include "Str.h" using namespace std; // Print trace messages with object addresses to show when functions get called. void trace(const void *obj, const char *what) { cout << "this = " << obj << ", Str::" << what << " called" << endl; } // constructors Str::Str() { trace(this, "default constructor"); // allocate empty string st_ = new char[1]; st_[0] = '\0'; } Str::Str(const char *s) { trace(this, "c-string constructor"); int len = strlen(s); st_ = new char[len+1]; strcpy(st_, s); } Str::Str(const Str &s) { trace(this, "copy constructor"); int len = strlen(s.st_); st_ = new char[len+1]; strcpy(st_, s.st_); } // destructor Str::~Str() { trace(this, "destructor"); delete [] st_; } // operations int Str::length() const { trace(this, "length"); return strlen(st_); } char * Str::c_str() const { trace(this, "c_str"); char * result = new char[strlen(st_)+1]; strcpy(result, st_); return result; } void Str::append(const Str &s) { trace(this, "append"); char *newst = new char[strlen(st_) + strlen(s.st_) + 1]; strcpy(newst, st_); strcat(newst, s.st_); delete [] st_; st_ = newst; } Str & Str::operator=(const Str &s) { trace(this, "assignment"); // do nothing if trying to assign a string to itself if (this == &s) { return *this; } // Replace string array with one of correct size // (Note: this is where the self-assignment test _really_ matters) // (Note: a better implementation would re-use the existing array // if it's long enough, but not too long) delete [] st_; st_ = new char[strlen(s.st_)+1]; // copy characters and return strcpy(st_, s.st_); return *this; } // stream output // (Note: not a member function of Str. This is an overloaded global // function that is a friend of Str so it can access private data) ostream &operator<<(ostream &out, const Str &s) { out << s.st_; return out; }