diff options
| author | Kamil Kaminski <kylek389@gmail.com> | 2014-02-28 03:55:14 -0600 | 
|---|---|---|
| committer | Kamil Kaminski <kylek389@gmail.com> | 2014-02-28 03:58:28 -0600 | 
| commit | dd0127d725d2aba3c81e502d4ae03a14e5f2eef9 (patch) | |
| tree | 0579d7941c1cd0c2f16300cc95dbeef46dd03d97 | |
| parent | 401ed2b66c9e80eecaf154f3a2ef932f919ae456 (diff) | |
| download | cstring++-master.tar.gz cstring++-master.tar.bz2 cstring++-master.zip  | |
counting, introduce outward conversion to 'const char *' without
a copy, implement != operator
| -rw-r--r-- | main.cpp | 18 | ||||
| -rw-r--r-- | string.cpp | 61 | ||||
| -rw-r--r-- | string.h | 27 | 
3 files changed, 73 insertions, 33 deletions
@@ -10,9 +10,13 @@ int main(int argc, char **argv)      else          std::cout << "false" << std::endl; +    /* uses copy ctor, compiler implicitly creates obj out of ", beta" and +     * then passess it to copy ctor +     */      MyString mystr1 = ", beta"; -    MyString mystr2 = ", charlie"; -    MyString mystr3 = ", delta"; +    /* next to call ctor that takes in char arr */ +    MyString mystr2("charlie"); /* if it was () then it would be a fwd decl! */ +    MyString mystr3 = MyString(", delta");      mystr.concat(mystr1).concat(mystr2).concat(mystr3);      std::cout << mystr << std::endl; @@ -21,9 +25,17 @@ int main(int argc, char **argv)      mystr4.concat(", world!").concat(" goodbye");      std::cout << mystr4 << std::endl; +    /* test outward conversion */ +    const char *mystr_charptr = mystr4; +    std::cout << mystr_charptr << " | len: " << std::strlen(mystr_charptr) << std::endl; +      MyString mystr5 = "bro";      std::cout << mystr5 << ", char at 1 is: " << mystr5[1] << std::endl; +    /* getCount() is a static method hence it doesn't need to be called on +     * an object +     */ +    std::cout << "mystring instances count: " << MyString::getCount(); +      return 0;  } - @@ -9,23 +9,41 @@  MyString::MyString(int len) : str_(new char[len + 1]), length_(len)  { +    this->count++;  } -MyString::MyString(const char *str) : length_(strlen(str)) +MyString::MyString(const char *str) : str_(new char[strlen(str)+1]), length_(strlen(str))  { -    str_ = new char[length_ + 1];      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 @@ -41,6 +59,9 @@ int MyString::indexOf(char ch, int pos) const      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_) @@ -65,6 +86,9 @@ bool MyString::isSubstring(const MyString& str) const      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; @@ -109,21 +133,6 @@ MyString& MyString::concat(const char *str)      return *this;  } -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; -} -  bool operator==(const MyString& lhs, const MyString& rhs)  {      if (lhs.length_ != rhs.length_) @@ -135,13 +144,17 @@ bool operator==(const MyString& lhs, const MyString& rhs)          return false;  } -/* seems like the ostream& in front has nothing to do with dereferencing a pointer, - * but it seems like the & is placed there so we can make consecutive overloaded - * calls to cout, effectively chaining all of the calls - */ +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 */ + * 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_); @@ -179,3 +192,7 @@ MyString::operator char*()          return NULL;  } +MyString::operator const char*() const +{ +    return this->str_; +} @@ -17,11 +17,14 @@ class MyString          char *str_;          int length_;          MyString(int); +        static size_t count;      public:          MyString(); -        MyString(char); +        explicit MyString(char); +        /* allow implicit conversions, it is useful */          MyString(const char *); +        /* copy constructor */          MyString(const MyString &);          MyString& operator=(const MyString &);          ~MyString(); @@ -33,29 +36,33 @@ class MyString          MyString& concat(const MyString &);          MyString& concat(const char *);          void printStr(void) const; +        static size_t getCount(void);          bool operator!(void) const;          char& operator[](int);          char operator[](int) const;          operator char*(); /* outward class conversion into char * */ +        operator const char*() const;  };  bool operator==(const MyString&, const MyString &); +bool operator!=(const MyString&, const MyString &);  std::ostream& operator<<(std::ostream&, const MyString &); -inline MyString::MyString() +/* it is always good idea to have default ctor to avoid manual init later + * for data types that include this class type + */ +inline MyString::MyString() : str_(new char[1]), length_(0)  { -    length_ = 0; -    str_ = new char[1];      str_[0] = '\0'; +    this->count++;  } -inline MyString::MyString(char ch) +inline MyString::MyString(char ch) : str_(new char[2]), length_(1)  { -    length_ = 1; -    str_ = new char[2];      str_[0] = ch;      str_[1] = '\0'; +    this->count++;  }  inline int MyString::length() const @@ -68,5 +75,9 @@ inline void MyString::printStr(void) const      std::cout << "length: " << length_ << ", value: \"" << str_ << "\"";  } -#endif +inline size_t MyString::getCount(void) +{ +    return count; +} +#endif  | 
