diff --git a/work20220401/neoString/CString.cpp b/work20220401/neoString/CString.cpp index af97eda..33a37c1 100644 --- a/work20220401/neoString/CString.cpp +++ b/work20220401/neoString/CString.cpp @@ -7,36 +7,41 @@ #include "CString.h" -/* - * 按照给定大小来初始化字符串数据 +/** + * 按照给定大小来初始化空的字符串数据 */ -CString::CString(int size) { +CString::CString(int size) : length(0), allocSize(size) { data = new char[size](); } -CString::~CString() { - delete[] data; - data = nullptr; -} +/** + * 不设定初始化大小就默认512个字符来初始化 + */ +CString::CString() : CString(512) {} -/* - * 直接分配5120个字符... +/** + * 从源中复制字符串来构建新的对象 */ -CString::CString() : CString(MAX_LENGTH) {} +CString::CString(char *source) : CString(source, (int) strlen(source)) {} -/* - * 从源中复制字符串来构建新的对象,超过MAX_LENGTH的部分不会被放入 +/** + * 从源中复制字符串来构建新的对象,并定义初始长度,小于源字符串则会被截取 */ -CString::CString(char *source) : CString(MAX_LENGTH) { - strncpy(data, source, MAX_LENGTH); +CString::CString(char *source, int length) : CString(length + 1) { + strncpy(data, source, length); + data[length] = '\0'; - int sourceLength = (int) strlen(source); - if (sourceLength < MAX_LENGTH) { - data[sourceLength] = 0; - } + this->length = length; } -/* +CString::~CString() { + delete[] data; + data = nullptr; +} + +CString::CString(const CString &source) : CString(source.data) {} + +/** * 重载等号。借鉴了Java中String类的equal()方法的实现思路。 * 首先判断data是否为nullptr,同为null则true,否则就是false * 再比较两字符串长度,如果长度不一样不用说,直接返回false; @@ -49,11 +54,8 @@ bool CString::operator==(const CString &source) const { return source.data == nullptr && this->data == nullptr; } - int length = (int) strlen(data); - int sourceLength = (int) strlen(source.data); - // 字符串长度不等,字符串肯定是不等 - if (length != sourceLength) { + if (length != source.length) { return false; } else { // 长度相等且data指向相同肯定等 @@ -63,8 +65,8 @@ bool CString::operator==(const CString &source) const { } // 以上情况都不符合时才进行逐字比较 - int compareLength = std::min(sourceLength, length); - for (int i = 0; i < compareLength; ++i) { + // 能执行到此处两者长度肯定相等,因此访问数组不会越界 + for (int i = 0; i < length; ++i) { if (data[i] != source.data[i]) { return false; } @@ -82,22 +84,25 @@ CString &CString::operator=(const CString &source) { if (source.data == nullptr) { delete[] data; this->data = nullptr; + length = 0; + allocSize = 0; return *this; } - // 如果本来是null的话就先分配好空间 - if (this->data == nullptr) { - this->data = new char[MAX_LENGTH](); - } + int sourceLength = (int) strlen(source.data); - strncpy(data, source.data, MAX_LENGTH); + // 如果源字符串长度超过了本对象已分配的字符数组大小则重新分配长度合适的字符数组 + if (allocSize < sourceLength) { + allocSize = sourceLength + 1; - int sourceLength = (int) strlen(source.data); - if (sourceLength < MAX_LENGTH) { - data[sourceLength] = 0; + delete[] data; + data = new char[allocSize]; } + strcpy(data, source.data); + length = sourceLength; + return *this; } @@ -107,47 +112,74 @@ CString &CString::operator+=(const CString &source) { return *this; } - int sourceLength = (int) strlen(source.data); - int length = 0; - - // 本对象nullptr的话就先新分配再拼接 + // 本对象nullptr的话就直接新分配 if (data == nullptr) { - this->data = new char[MAX_LENGTH](); - length = sourceLength; + allocSize = source.length + 2 + 1; + this->data = new char[allocSize](); + + length = source.length; } else { length = (int) strlen(data); } - // 先加两个横杠... - for (int i = length, j = 0; i < MAX_LENGTH && j < 2; ++i, ++j) { - this->data[i] = '-'; - } - // 去他的strcat,不判溢出什么的了,直接手动实现判断 - for (int i = length + 2, j = 0; i < MAX_LENGTH && j < sourceLength; ++i, ++j) { - this->data[i] = source.data[j]; + // 如果拼接后字符长度超过已分配的内存大小,则重新分配data内存大小 + if (allocSize < (length + source.length + 2)) { + // 保存拼接前的原数据,以便重新分配足够的内存 + char *old = new char[length + 1](); + strcpy(old, data); + + // 重新分配内存,防止拼接后溢出,2为两个横杠大小 + length += source.length + 2; + allocSize = length + 1; + + delete[] data; + this->data = new char[allocSize](); + + strcpy(data, old); } + strcat(data, "--"); + strcat(data, source.data); + return *this; } -CString::CString(const CString &source) : CString(source.data) {} - -/* +/** * 按照字典顺序逐字对比 */ -bool CString::operator>(const CString &source) const { - // 管他data空不空呢,不是这里该管的事,调用方在调用前就应该判断了 - return strcoll(this->data, source.data) > 0; +bool CString::operator>(const CString &compareString) const { + // 首先判断两CString对象data成员是否为空指针,空直接返回false + if (compareString.data == nullptr || this->data == nullptr) { + return false; + } + + // 两对象data成员首指向相同则对比谁长 + if (compareString.data == this->data) { + return length > compareString.length; + } + + // 以上情况都不符合时才进行逐字比较 + int compareLength = std::min(compareString.length, length); + for (int i = 0; i < compareLength; ++i) { + if (data[i] > compareString.data[i]) { + return true; + } + } + return false; } std::ostream &operator<<(std::ostream &outputStream, const CString &source) { return outputStream << source.data; } -std::istream &operator>>(std::istream &inputStream, const CString &source) { - return inputStream >> source.data; +std::istream &operator>>(std::istream &inputStream, CString &source) { + inputStream >> source.data; + source.length = (int) strlen(source.data); + + return inputStream; +} + +char CString::operator[](int i) { + return (i < length && i >= 0) ? data[i] : '\0'; } -char CString::operator[](const int i) const { - return (i < MAX_LENGTH) ? data[i] : '\0'; -} \ No newline at end of file diff --git a/work20220401/neoString/CString.h b/work20220401/neoString/CString.h index 3ee2bc5..9c40504 100644 --- a/work20220401/neoString/CString.h +++ b/work20220401/neoString/CString.h @@ -9,15 +9,20 @@ #include "utility" using namespace std::rel_ops; - class CString { private: + // 字符数组做字符串 char *data = nullptr; - explicit CString(int size); + // 字符串实际长度 + int length = 0; + // 已分配的字符数量 + int allocSize = 0; public: - const static int MAX_LENGTH = 5120; + explicit CString(int size); + + CString(char *data, int length); explicit CString(char *source); @@ -29,17 +34,16 @@ public: bool operator==(const CString &source) const; - bool operator>(const CString &source) const; - - char operator[](int i) const; + bool operator>(const CString &compareString) const; CString &operator+=(const CString &source); CString &operator=(const CString &source); friend std::ostream &operator<<(std::ostream &outputStream, const CString &source); + friend std::istream &operator>>(std::istream &outputStream, CString &source); - friend std::istream &operator>>(std::istream &outputStream, const CString &source); + char operator[](int i); }; -#endif //WORK20220401_CSTRING_H +#endif //WORK20220401_CSTRING_H \ No newline at end of file