/* string.cpp * * Note: http://msdn.microsoft.com/en-us/magazine/cc163742.aspx * */ #include "string.h" #include MyString::MyString(int len) : str_(new char[len + 1]), length_(len) { this->count++; } MyString::MyString(const char *str) : str_(new char[strlen(str)+1]), length_(strlen(str)) { strcpy(str_, str); this->count++; } MyString::MyString(const MyString& str) : str_(new char[str.length_ + 1]), length_(str.length_) { strcpy(str_, str.str_); this->count++; } MyString& MyString::operator=(const MyString& rhs) { /* don't do anything if object assigns itself */ if (this == &rhs) return *this; length_ = rhs.length_; delete[] str_; str_ = new char[ length_ + 1]; strcpy(str_, rhs.str_); /* assignment operator requires this */ return *this; } MyString::~MyString() { delete[] str_; this->count--; } int MyString::indexOf(char ch, int pos) const { while (pos < length_) { if (str_[pos] == ch) return pos; pos++; } return -1; } /* define this field only once, .h is not the best place */ size_t MyString::count = 0; bool MyString::isSubstring(const MyString& str) const { if (length_ < str.length_) return false; int i, j, temp; for (i = 0; i < length_; i++) { j = 0; temp = i; while ((j < str.length_) && (str_[temp] == str.str_[j])) { temp++; j++; } if (j == str.length_) return true; } return false; } /* might seem redundant since constructor can create an object from char array * and call other isSubstring method that takes in MyString type */ bool MyString::isSubstring(const char *str) const { int i, j, k; for (i = 0; i < length_; i++) { j = i; k = 0; while (str_[j++] == str[k++]) ; if (str[k-1] == '\0') return true; } return false; } /* there are few ways to implement this */ MyString& MyString::concat(const MyString& str) { /* right way to do this would be to use realloc and double the buffer each * we append something (if it's full) */ MyString ret(length_ + str.length_); strcpy(ret.str_, str_); strcat(ret.str_, str.str_); return (*this = ret); } MyString& MyString::concat(const char *str) { char *newstr = new char[length_ + strlen(str) + 1]; strcpy(newstr, str_); strcpy(newstr + length_, str); delete[] str_; length_ += strlen(str); str_ = newstr; return *this; } bool operator==(const MyString& lhs, const MyString& rhs) { if (lhs.length_ != rhs.length_) return false; if (strcmp(lhs.str_, rhs.str_) == 0) return true; else return false; } bool operator!=(const MyString& lhs, const MyString& rhs) { return !(lhs == rhs); } /* right now I think the reference is used to avoid returning copy of ostream * so when calls are chained up we work on one ostream object only * * this function is in global scope, it is friend'ed to allow us access to data * members of calss MyString */ std::ostream& operator<<(std::ostream& ostr, const MyString& rhs) { return (ostr << rhs.str_); } /* unary operator operate on one operand, itself! */ bool MyString::operator!(void) const { return (this->length_ == 0); } char& MyString::operator[](int i) { /* references need to point to valid objects, all hell could breaks loose */ return this->str_[i]; } char MyString::operator[](int i) const { if (i < 0 || i > this->length_ - 1) return 0; else return this->str_[i]; } MyString::operator char*() { char *ret = new char[this->length_ + 1]; if (ret) { strcpy(ret, this->str_); return ret; } else return NULL; } MyString::operator const char*() const { return this->str_; }