- #pragma once
- #include<assert.h>
-
- namespace hqj
- {
- class string
- {
- public:
- friend ostream& operator<<(ostream& _cout, const hqj::string& s);
-
- friend istream& operator>>(istream& _cin, hqj::string& s);
- string(const char* str = "")//构造函数
- :_size(strlen(str))
- , _capacity(_size)
- {
- _str = new char[_capacity + 1];
- strcpy(_str, str);
- }
-
- string(const string& s)//拷贝构造函数
- :_capacity(0)
- , _size(0)
- , _str(nullptr)
- {
- string tmp(s._str);//这里不能传s,原因是要调用构造函数而不是拷贝构造函数
- swap(tmp);
- }
-
- ~string()//析构函数
- {
- delete[] _str;
- _str = nullptr;
- _size = 0;
- _capacity = 0;
- }
-
- void reserve(size_t n)
- {
- if (n > _capacity)
- {
- char* tmp = new char[n + 1];
- strcpy(tmp, _str);
- delete[] _str;
- _str = tmp;
-
- _capacity = n;
- }
- }
-
- void push_back(char c)//尾插一个字符
- {
- if (_size >= _capacity)//不要去改变_capacity
- {
-
- reserve(_capacity == 0 ? 4 : _capacity * 2);
- }
-
- _str[_size] = c;
- _size++;
- _str[_size] = '\0';
- }
-
- void append(const char* str)
- {
- size_t len = strlen(str);
- if (_size + len > _capacity)
- {
- reserve(_size + len);
- }
-
- strcpy(_str + _size, str);
- _size += len;
- }
-
- //+=运算符重载
- string& operator+=(char c)
- {
- push_back(c);
- return *this;
- }
-
- string& operator+=(const char* str)
- {
- append(str);
- return *this;
- }
-
-
- size_t capacity()const
- {
- return _capacity;
- }
-
- bool empty()const
- {
- return _size == 0;
- }
-
-
- void clear()//清空string对象
- {
- _str[0] = '\0';
- _size = 0;
- }
-
- void swap(string& s)//string的交换函数,是现代写法的基础(包工头写法
- {
- std::swap(_str, s._str);
- std::swap(_size, s._size);
- std::swap(_capacity, s._capacity);
- }
-
- const size_t size()const//string有效数据个数
- {
- return _size;
- }
-
- //[]运算符重载
- char& operator[](size_t index)
- {
- assert(index < _size);
- return _str[index];
- }
-
- const char& operator[](size_t index)const
- {
- assert(index < _size);
- return _str[index];
- }
-
- //迭代器部分
- typedef char* iterator;
-
- iterator begin()
- {
- return _str;
- }
-
- iterator end()
- {
- return _str + _size;
- }
-
- const iterator begin() const
- {
- return _str;
- }
-
- const iterator end() const
- {
- return _str + _size;
- }
-
- string& operator=(const string& s)
- {
- string tmp(s);
- swap(tmp);
- return *this;
- }
-
- //提供私有成员_str
- const char* c_str()const
- {
- return _str;
- }
-
- // 返回c在String中第一次出现的位置
-
- size_t find(char c, size_t pos = 0) const
- {
- assert(pos < _size);
- for (int i = pos; i < _size; i++)
- {
- if (_str[i] == c)
- {
- return i;
- }
- }
- return npos;
- }
-
- // 返回子串s在String中第一次出现的位置
-
- size_t find(const char* s, size_t pos = 0) const
- {
- assert(pos < _size);
- char* tmp = strstr(_str + pos, s);
- if (tmp == nullptr)
- {
- return npos;
- }
- return find(*tmp);
- }
-
-
- // 在pos位置上插入字符c/字符串str,并返回该字符的位置
-
- string& insert(size_t pos, char c)
- {
- assert(pos <= _size);//pos=size相当于尾插
- if (_size >= _capacity)//不要去改变_capacity
- {
- reserve(_capacity == 0 ? 4 : _capacity * 2);
- }
- size_t end = _size + 1;
- while (end != pos)
- {
- _str[end] = _str[end-1];
- end--;
- }
- _str[pos] = c;
- _size++;
- return *this;
- }
-
- string& insert(size_t pos, const char* str)
- {
- assert(pos <= _size);
- size_t len = strlen(str);
- if (_size+len >= _capacity)//不要去改变_capacity
- {
- reserve(_size+len);
- }
- size_t end_new = _capacity;
- size_t end_old = _size;
- while (end_old > pos)
- {
- _str[end_new] = _str[end_old];
- end_old--;
- end_new--;
- }
- _str[end_new] = _str[pos];
- for (int i = 0; i < len; i++)
- {
- _str[pos++] = str[i];
- }
- _size+=len;
- return *this;
- }
-
- // 删除pos位置上的元素,并返回该元素的下一个位置
- void erase(size_t pos, size_t len = npos)
- {
- assert(pos < _size);
-
- if (len == npos || pos + len >= _size)
- {
- _str[pos] = '\0';
- _size = pos;
- }
- else
- {
- size_t begin = pos + len;
- while (begin <= _size)
- {
- _str[begin - len] = _str[begin];
- ++begin;
- }
- _size -= len;
- }
- }
-
-
- void resize(size_t n, char c = '\0')
- {
- size_t len = strlen(_str);
- if (n > _capacity)
- {
- reserve(n);
- for (int i = len + 1; i < _capacity; i++)
- {
- (*this) += c;
- }
- }
- else
- {
- _str[n] = '\0';
- }
- _size = n;
- }
-
- bool operator<(const string& s)
- {
- if (strcmp(_str, s._str) < 0)
- {
- return true;
- }
- return false;
- }
-
- bool operator<=(const string& s)
- {
- if ((*this) < s || (*this) == s)
- {
- return true;
- }
- return false;
- }
-
- bool operator>(const string& s)
- {
- return !(*this <= s);
- }
-
- bool operator>=(const string& s)
- {
- return !(*this < s);
- }
-
- bool operator==(const string& s)
- {
- if (strcmp(_str, s._str) == 0)
- {
- return true;
- }
- return false;
- }
-
- bool operator!=(const string& s)
- {
- return!((*this) == s);
- }
-
-
- private:
- char* _str;
- size_t _size;
- size_t _capacity;
- public:
- const static size_t npos;
- };
-
- const size_t string::npos = -1;
- //流插入流提取的运算符重载
- ostream& operator<<(ostream& out, const hqj::string& s)
- {
- for (int i = 0; i < s.size(); i++)
- {
- out << s._str[i];
- }
- return out;
- }
-
- /* istream& operator>>(istream& in, string& s)
- {
- s.clear();
-
- char buff[129];
- size_t i = 0;
-
- char ch;
- ch = in.get();
- while (ch != ' ' && ch != '\n')
- {
- buff[i++] = ch;
- if (i == 128)
- {
- buff[i] = '\0';
- s += buff;
- i = 0;
- }
- ch = in.get();
- }
-
- if (i != 0)
- {
- buff[i] = '\0';
- s += buff;
- }
-
- return in;
- }*/
- //自己的版本
- istream& operator>>(istream& in, string& s)
- {
- char ch;
- ch = in.get();
- while (ch != '\n' && ch != '\0')
- {
- s += ch;
- ch = in.get();
- }
- return in;
- }
_str 是一个指向字符数组(C-style string)的指针,用于存储字符串的字符序列。
_size 是一个用于记录字符串当前长度的变量,即字符串中实际包含的字符数量。
_capacity 是一个用于记录字符串当前内存容量的变量,即分配给字符串的字符数组的大小。
这样的设计是为了支持动态字符串的存储和操作。当字符串长度超过当前内存容量时,可以通过重新分配更大的内存空间来保证字符串的存储能力。而 _str 指针则可以指向新分配的内存空间,以容纳更多的字符序列。
- private:
- char* _str;
- size_t _size;
- size_t _capacity;
构造函数中的语法 const char* str = "" 定义了一个默认参数。如果在创建对象时不传入参数,那么默认会将一个空字符串赋值给 str。如果传入参数,则使用传入的字符串来初始化新对象。
在构造函数中,首先使用 C 标准库函数 strlen 来计算 str 字符串的长度,并将其保存到成员变量 _size 中。然后,根据字符串长度计算出需要分配的存储空间,并将其保存到成员变量 _capacity 中。
接下来使用 new 运算符在堆上动态分配内存,分配的空间大小为 _capacity + 1,因为字符串末尾要以字符 '\0' 结束。然后使用 C 标准库函数 strcpy 将 str 字符串的内容复制到新分配的内存空间中。
最后,将指针变量 _str 指向新分配的内存空间,完成 C++ 字符串的构造过程。
- string(const char* str = "")//构造函数
- :_size(strlen(str))
- , _capacity(_size)
- {
- _str = new char[_capacity + 1];
- strcpy(_str, str);
- }
在拷贝构造函数中,首先初始化成员变量 _capacity、_size 和 _str,它们分别表示字符串的容量、大小和存储内容的指针。
然后,在构造函数内部创建了一个名为 tmp 的临时字符串对象,并通过传入的参数 s 的 _str 成员变量来初始化它。这里不能直接传入 s,而是使用 s._str,是因为直接传入 s 会导致递归调用拷贝构造函数,而我们需要调用的是构造函数。
接下来,通过调用 swap 函数,将临时字符串对象 tmp 和当前对象的内容进行交换。这一步中,实际上是交换了 _str 指针指向的内存空间,从而实现了将原始字符串对象的内容复制给新对象的目的。
最终,根据交换后的内容,临时字符串对象 tmp 会自动被销毁,同时也会自动释放内存空间。
- string(const string& s)//拷贝构造函数
- :_capacity(0)
- , _size(0)
- , _str(nullptr)
- {
- string tmp(s._str);//这里不能传s,原因是要调用构造函数而不是拷贝构造函数
- swap(tmp);
- }
在赋值运算符重载函数中,首先创建了一个名为 tmp 的临时字符串对象,并通过传入的参数 s 调用拷贝构造函数初始化它。
接下来,调用 swap 函数,将临时字符串对象 tmp 和当前字符串对象的内容进行交换。这一步中,实际上是交换了 _str 指针指向的内存空间,从而实现了将原始字符串对象的内容复制给当前对象的目的。
最后,返回当前字符串对象的引用,以支持链式赋值操作。
- string& operator=(const string& s)
- {
- string tmp(s);
- swap(tmp);
- return *this;
- }
在析构函数中,首先使用 delete[] 关键字释放之前在堆上动态分配的 _str 成员变量指向的内存空间。这是为了避免发生内存泄漏,释放资源以确保不再使用该内存空间。
接下来,将指针 _str 赋值为 nullptr,以防止在使用已释放的内存时发生未定义的行为。
最后,将成员变量 _size 和 _capacity 的值都设为 0,以标记字符串的大小和容量为 0,表示该字符串对象已经被析构销毁。
- ~string()//析构函数
- {
- delete[] _str;
- _str = nullptr;
- _size = 0;
- _capacity = 0;
- }
resize 函数接受两个参数:新的字符串大小 n 和要填充的字符 c(可选,默认为结束符 '\0')。该函数首先使用 strlen 函数获取当前字符串的长度 len。然后根据不同情况进行处理:
如果新的字符串大小 n 大于字符串的容量 _capacity,表示需要增加字符串的容量以容纳更多的字符。这里通过调用 reserve 函数来增加字符串的容量,保证足够存放 n 个字符,并且在剩余空间中填充字符 c。循环从 len + 1 开始,一直到容量 _capacity,将字符 c 追加到字符串中。
如果新的字符串大小 n 不大于字符串的容量 _capacity,表示不需要增加字符串的容量。此时,如果 n 小于当前字符串的长度 len,需要将字符串截断到指定大小,即将第 n 个字符设置为结束符 '\0'。如果 n 大于等于当前字符串的长度 len,则不需要进行额外操作。
最后,更新字符串的大小 _size 为新的字符串大小 n。
- void resize(size_t n, char c = '\0')
- {
- size_t len = strlen(_str);
- if (n > _capacity)
- {
- reserve(n);
- for (int i = len + 1; i < _capacity; i++)
- {
- (*this) += c;
- }
- }
- else
- {
- _str[n] = '\0';
- }
- _size = n;
- }
-
这是一个 C++ 字符串类中的 reserve 函数,用于预留足够的容量来存储字符串。
在 reserve 函数中,首先判断传入的参数 n 是否大于当前字符串的容量 _capacity。如果大于,则需要进行扩容操作。
创建了一个名为 tmp 的字符数组指针,通过使用 new 运算符在堆上分配了 n+1 个字符的内存空间。这里 n+1 是为了包含字符串的结尾字符 \0。
然后,使用 strcpy 函数将原始字符串 _str 的内容复制到新分配的内存空间 tmp 中。
接下来,使用 delete[] 运算符释放原始字符串 _str 指向的内存空间,以防止出现内存泄漏。
将指针 _str 更新为指向新分配的内存空间 tmp,使其指向新的字符串内容。
最后,将字符串的容量 _capacity 更新为 n,表示字符串已经具备了预留的容量。
- void reserve(size_t n)
- {
- if (n > _capacity)
- {
- char* tmp = new char[n + 1];
- strcpy(tmp, _str);
- delete[] _str;
- _str = tmp;
-
- _capacity = n;
- }
- }
在 push_back 函数中,首先判断当前字符串的大小 _size 是否已经达到了容量 _capacity,如果已经达到,则通过调用字符串类内部的 reserve 函数进行扩容,以腾出更多的空间来存储新的字符。
当确保有足够的容量后,将字符 c 插入到字符串的末尾 _str[_size],并将 _size 的值加一。最后,在末尾添加一个空字符 \0,保证字符串的完整性。
- void push_back(char c)//尾插一个字符
- {
- if (_size >= _capacity)//不要去改变_capacity
- {
-
- reserve(_capacity == 0 ? 4 : _capacity * 2);
- }
-
- _str[_size] = c;
- _size++;
- _str[_size] = '\0';
- }
在 append 函数中,首先获取待追加字符数组 str 的长度 len,使用 strlen 函数计算得到。
接着,判断当前字符串的大小 _size 加上待追加字符数组的长度 len 是否超过了容量 _capacity。如果超过了容量,则通过调用字符串类内部的 reserve 函数进行扩容,以腾出足够的空间来存储新的字符。
当确保有足够的容量后,使用 strcpy 函数将字符数组 str 的内容复制到字符串的末尾 _str + _size,即从 _str 的第 _size 个位置开始复制。
最后,将 _size 的值增加 len,表示字符串的大小已经扩展到了追加后的长度。
需要注意的是,为了保证字符串的完整性,最后需要手动添加一个空字符 \0,以结束字符串。
与 push_back 函数相比,append 函数可以一次性追加多个字符,效率较高。适用于需要一次性追加多个字符或者字符数组的情况。而 push_back 则适用于单个字符的追加。
- void append(const char* str)
- {
- size_t len = strlen(str);
- if (_size + len > _capacity)
- {
- reserve(_size + len);
- }
-
- strcpy(_str + _size, str);
- _size += len;
- }
-
在函数体内,通过使用 assert 宏来判断指定的下标是否越界,如果越界则会触发一个断言错误并终止程序的执行,从而避免了对无效位置进行访问。
然后,根据运算符的重载类型(即 const 和非 const),返回私有成员变量 _str 中对应下标位置的字符的引用或常量引用,从而实现对字符串中字符的读写操作。
使用 [] 运算符可以方便地访问字符串对象中的任意字符,类似于数组的使用方式。
- //[]运算符重载
- char& operator[](size_t index)
- {
- assert(index < _size);
- return _str[index];
- }
-
- const char& operator[](size_t index)const
- {
- assert(index < _size);
- return _str[index];
- }
第一个重载函数 operator+=(char c) 接受一个字符 c 作为参数。在函数体内,调用了字符串类的 push_back 函数,将字符 c 追加到字符串的末尾。然后,返回当前字符串对象的引用 *this。
第二个重载函数 operator+=(const char* str) 接受一个字符数组 str 作为参数。在函数体内,调用了字符串类的 append 函数,将字符数组 str 追加到字符串的末尾。然后,返回当前字符串对象的引用 *this。
- string& operator+=(char c)
- {
- push_back(c);
- return *this;
- }
-
- string& operator+=(const char* str)
- {
- append(str);
- return *this;
- }
这是 C++ 字符串类中的 capacity 函数,用于获取字符串对象的容量大小。
在函数体内,直接返回私有成员变量 _capacity 的值。该变量表示字符串对象已经预分配的空间大小,即在不扩容的情况下,该字符串对象最多可以存储多少个字符。
使用 capacity 函数可以帮助我们了解当前字符串对象的容量大小,以便更好地管理内存分配和释放,避免浪费或者不足的情况发生。
- size_t capacity()const
- {
- return _capacity;
- }
这是 C++ 字符串类中的 empty 函数,用于判断字符串对象是否为空。
在函数体内,通过比较私有成员变量 _size 是否等于 0,来判断字符串是否为空。如果 _size 等于 0,表示字符串中没有任何字符,即为空;否则,表示字符串中至少包含一个字符,即不为空。
- bool empty()const
- {
- return _size == 0;
- }
-
在函数体内,首先将字符串对象 _str 的第一个字符 _str[0] 设置为 '\0',即空字符,表示字符串为空。
然后,将私有成员变量 _size 设置为 0,表示字符串中没有任何字符。
通过调用 clear 函数可以将字符串对象清空,使其不包含任何字符。
- void clear()//清空string对象
- {
- _str[0] = '\0';
- _size = 0;
- }
在函数体内,通过使用 std::swap 函数来交换私有成员变量 _str、_size 和 _capacity 与另一个字符串对象 s 的对应成员变量的值。
std::swap 是 C++ 标准库中的一个通用函数模板,用于交换两个对象的值。它会根据对象的类型自动选择最高效的交换方式,从而避免了手动实现交换逻辑的繁琐和潜在的错误。
通过调用 swap 函数,可以快速且安全地交换两个字符串对象的内容。
- void swap(string& s)//string的交换函数,是现代写法的基础(包工头写法
- {
- std::swap(_str, s._str);
- std::swap(_size, s._size);
- std::swap(_capacity, s._capacity);
- }
-
在函数体内,直接返回私有成员变量 _size 的值,表示字符串中包含 _size 个字符,即为有效数据的个数。
使用 size 函数可以方便地获取字符串中字符的数量,可以用于数组越界和其他处理中。
- const size_t size()const//string有效数据个数
- {
- return _size;
- }
-
在代码中,使用 typedef 关键字定义了一个名为 iterator 的别名,它表示指向字符的指针类型。
然后,重载了 begin() 和 end() 函数,分别用于返回字符串对象的起始位置和结束位置的迭代器。
对于非常量对象,begin() 函数直接返回私有成员变量 _str,即指向字符串开头的指针。而 end() 函数返回 _str + _size,即指向字符串结尾下一个位置的指针。
对于常量对象,也重载了 begin() 和 end() 函数,返回相同的迭代器,但是声明为常量迭代器,表示在常量对象上不允许修改字符值。
通过返回迭代器,可以方便地遍历字符串对象中的字符,并进行各种操作。
- //迭代器部分
- typedef char* iterator;
-
- iterator begin()
- {
- return _str;
- }
-
- iterator end()
- {
- return _str + _size;
- }
-
- const iterator begin() const
- {
- return _str;
- }
-
- const iterator end() const
- {
- return _str + _size;
- }
-
c_str() 函数通常用于将字符串对象转换为 C 风格的字符串,以便与需要接受 C 风格字符串作为参数的函数进行交互。
- //提供私有成员_str
- const char* c_str()const
- {
- return _str;
- }
-
函数的参数包括一个指向字符数组的指针 s 和一个可选的起始搜索位置 pos(默认为0)。
首先,使用 assert 断言确保 pos 的值小于字符串的长度 _size,以避免越界访问。
接下来,使用标准库函数 strstr 在字符串 _str 的 pos 位置之后搜索指定的子串 s。如果找到了匹配的子串,则 strstr 函数返回指向该子串的指针;如果没有找到,则返回空指针。
如果 tmp 是空指针(即找不到匹配的子串),则表示查找失败,函数返回特殊值 npos(通常定义为 size_t(-1),表示无效的位置)。
如果找到了匹配的子串,函数会继续调用 find 函数,传入子串的第一个字符 *tmp,以在整个字符串中找到该字符第一次出现的位置,并将其作为结果返回。
需要注意的是,find 函数返回的是子串第一次出现的位置,而不是子串本身。如果需要获取子串本身,可以使用字符串类的 substr 函数进行切片操作。
此外,该代码中的 find 函数是一个 const 成员函数,表示它不会修改字符串对象的内容。
- size_t find(const char* s, size_t pos = 0) const
- {
- assert(pos < _size);
- char* tmp = strstr(_str + pos, s);
- if (tmp == nullptr)
- {
- return npos;
- }
- return find(*tmp);
- }
-
第一个 insert 函数接受两个参数:一个是要插入的字符 c,另一个是插入位置 pos。该函数首先使用断言 assert 确保插入位置不超出字符串的范围。然后,如果字符串当前的长度 _size 已经达到了其容量 _capacity,则通过调用 reserve 函数增加字符串的空间以容纳新字符。接下来,将 pos 之后的所有字符依次向后挪一位,为新字符腾出空间。最后,将新字符插入到指定位置,更新字符串的长度并返回字符串对象本身的引用。
第二个 insert 函数与第一个函数类似,但它接受的参数是一个字符指针 str,表示要插入的字符串。该函数的实现类似于第一个函数,只不过需要多次插入字符,并且需要移动更多的字符位置。在插入前,该函数还会先计算待插入字符串的长度 len。最后,更新字符串的长度并返回字符串对象本身的引用。
- // 在pos位置上插入字符c/字符串str,并返回该字符的位置
-
- string& insert(size_t pos, char c)
- {
- assert(pos <= _size);//pos=size相当于尾插
- if (_size >= _capacity)//不要去改变_capacity
- {
- reserve(_capacity == 0 ? 4 : _capacity * 2);
- }
- size_t end = _size + 1;
- while (end != pos)
- {
- _str[end] = _str[end-1];
- end--;
- }
- _str[pos] = c;
- _size++;
- return *this;
- }
-
- string& insert(size_t pos, const char* str)
- {
- assert(pos <= _size);
- size_t len = strlen(str);
- if (_size+len >= _capacity)//不要去改变_capacity
- {
- reserve(_size+len);
- }
- size_t end_new = _capacity;
- size_t end_old = _size;
- while (end_old > pos)
- {
- _str[end_new] = _str[end_old];
- end_old--;
- end_new--;
- }
- _str[end_new] = _str[pos];
- for (int i = 0; i < len; i++)
- {
- _str[pos++] = str[i];
- }
- _size+=len;
- return *this;
- }
-
erase 函数接受两个参数:要删除的元素的起始位置 pos,和要删除的元素的长度 len(可选,默认为 npos)。该函数首先使用断言 assert 确保删除位置不超出字符串的范围。然后根据 len 的值进行不同的处理:
如果 len 的值为默认值 npos 或者 pos + len 大于等于字符串的长度 _size,表示要删除 pos 位置之后的所有元素,则将 pos 位置上的元素设置为结束符 '\0',并更新字符串的长度 _size 为 pos。
否则,需要删除指定位置 pos 后面的 len 个元素。首先定义一个变量 begin,表示要删除的元素之后的第一个元素的位置。然后通过循环将 begin 位置及其后面的所有元素向前挪动 len 个位置,以覆盖要删除的元素。最后,更新字符串的长度 _size 减去 len。
这样,删除成功后,字符串中就会被删除的元素占据的位置填补上相应的元素,并且字符串的长度也会相应调整。
- // 删除pos位置上的元素,并返回该元素的下一个位置
- void erase(size_t pos, size_t len = npos)
- {
- assert(pos < _size);
-
- if (len == npos || pos + len >= _size)
- {
- _str[pos] = '\0';
- _size = pos;
- }
- else
- {
- size_t begin = pos + len;
- while (begin <= _size)
- {
- _str[begin - len] = _str[begin];
- ++begin;
- }
- _size -= len;
- }
- }
-
首先,这些比较运算符都接受一个字符串对象 s 作为参数,并以引用形式传递。接下来,按照运算符的定义进行逐个实现:
小于运算符(<)通过调用 strcmp 函数比较当前字符串 _str 和参数字符串 s._str 的大小。如果 _str 小于 s._str,则返回 true;否则返回 false。
小于等于运算符(<=)通过在小于运算符之后添加一个等于运算符组成。如果当前字符串小于 s 或者当前字符串等于 s,则返回 true;否则返回 false。
大于运算符(>)通过在小于等于运算符之前添加逻辑非运算符(!)来实现。如果当前字符串不小于等于 s,即大于 s,则返回 true;否则返回 false。
大于等于运算符(>=)通过在大于运算符之前添加逻辑非运算符来实现。如果当前字符串不大于 s,即小于 s,则返回 true;否则返回 false。
等于运算符(==)通过调用 strcmp 函数比较当前字符串和参数字符串的大小。如果相等,则返回 true;否则返回 false。
不等于运算符(!=)通过在等于运算符之前添加逻辑非运算符来实现。如果当前字符串不等于 s,则返回 true;否则返回 false。
这样,就可以使用比较运算符对字符串对象进行大小比较操作。
- bool operator<(const string& s)
- {
- if (strcmp(_str, s._str) < 0)
- {
- return true;
- }
- return false;
- }
-
- bool operator<=(const string& s)
- {
- if ((*this) < s || (*this) == s)
- {
- return true;
- }
- return false;
- }
-
- bool operator>(const string& s)
- {
- return !(*this <= s);
- }
-
- bool operator>=(const string& s)
- {
- return !(*this < s);
- }
-
- bool operator==(const string& s)
- {
- if (strcmp(_str, s._str) == 0)
- {
- return true;
- }
- return false;
- }
-
- bool operator!=(const string& s)
- {
- return!((*this) == s);
- }
-
首先,流插入运算符重载函数接受一个输出流对象 out 和一个字符串对象 s 作为参数,并以引用形式传递。实现过程中遍历字符串 _str 的每个字符并输出到 out 流中,最后返回输出流对象 out。
比较而言,流提取运算符重载函数接受一个输入流对象 in 和一个自定义的字符串对象 s 作为参数。实现过程中逐个读取输入流中的字符,如果字符不是换行符或者字符串终止符,则将其添加到字符串对象 s 中,最后返回输入流对象 in。
- //流插入流提取的运算符重载
- ostream& operator<<(ostream& out, const hqj::string& s)
- {
- for (int i = 0; i < s.size(); i++)
- {
- out << s._str[i];
- }
- return out;
- }
- //自己的版本
- istream& operator>>(istream& in, string& s)
- {
- char ch;
- ch = in.get();
- while (ch != '\n' && ch != '\0')
- {
- s += ch;
- ch = in.get();
- }
- return in;
- }