四、字符串访问函数
1.operator[ ]()
[ ]运算符重载是为了让string类能够实现下标的访问
//可读可写 char& operator[](size_t pos) { assert(pos < _size); return _str[pos]; } //可读不可写 const char& operator[](size_t pos) const { assert(pos < _size); return _str[pos]; }
2.迭代器
相比其他容器的迭代器,string类的迭代器相对简单,实际上是char*的typedef;函数后面的const表示的是this不能被修改;
typedef char* iterator; typedef const char* const_iterator; iterator begin() { return _str;//返回字符串第一个位置 } iterator end() { return _str + _size;//返回'\0'的地址 } const_iterator begin() const { return _str; } const_iterator end() const { return _str + _size; }
五、关系运算符重载函数
bool operator<(const string& s1, const string& s2) { return strcmp(s1.c_str(), s2.c_str()) < 0; } bool operator==(const string& s1, const string& s2) { return strcmp(s1.c_str(), s2.c_str()) == 0; } //实现两种比较其他的可以复用 bool operator<=(const string& s1, const string& s2) { return s1 < s2 || s1 == s2; } bool operator>=(const string& s1, const string& s2) { return !(s1 < s2); } bool operator>(const string& s1, const string& s2) { return !(s1 <= s2); } bool operator!=(const string& s1, const string& s2) { return !(s1 == s2); }
六、流提取、流插入运算符重载
//流插入 << ostream& operator<<(ostream& out, const string& s) { //方式一 for (auto ch : s) { out << ch; } //方式二 for (size_t i = 0; i < s.size(); ++i) { out << s[i]; } //方式三 //out << s.c_str();//不能这样写 return out; } //流提取 >> istream& operator>>(istream& in, string& s) { s.clear(); char ch = in.get(); while (ch != ' ' && ch != '\n')//利用循环可以连续输入 { s += ch; ch = in.get(); } return in; }
完整代码
namespace mlxg3 { class string { public: /******************迭代器********************/ typedef char* iterator; typedef const char* const_iterator; iterator begin() { return _str; } iterator end() { return _str + _size; } const_iterator begin() const { return _str; } const_iterator end() const { return _str + _size; } /******************构造函数********************/ string(const char* str = "") :_size(strlen(str)) , _capacity(_size) { _str = new char[_capacity + 1]; strcpy(_str, str); } /******************拷贝构造********************/ //s2(s1) //传统写法 /* string(const string& s) :_size(s._size) , _capacity(s._capacity) { _str = new char[_capacity + 1]; strcpy(_str, s._str); } */ /******************赋值重载********************/ /* string& operator=(const string& s) { if (this != &s) { char* tmp = new char[s._capacity + 1]; strcpy(tmp, s._str); delete[] _str; _str = tmp; _size = s._size; _capacity = s._capacity; } return *this; } */ /******************拷贝构造与赋值重载现代写法********************/ //现代写法 void swap(string& s) { std::swap(_str, s._str); std::swap(_size, s._size); std::swap(_capacity, s._capacity); } //s2(s1) string(const string& s) :_str(nullptr) , _size(0) , _capacity(0) { string tmp(s._str); //this->swap(tmp); swap(tmp); } string& operator=(string s) { swap(s); return *this; } /******************析构函数********************/ ~string() { delete[] _str; _str = nullptr; _size = _capacity = 0; } /******************增删查改、增容********************/ //返回c形式的字符串 const char* c_str() const { return _str; } //返回有效字符的个数 size_t size() const { return _size; } //返回有效容量的大小 size_t size() const { return _size; } //[]重载 char& operator[](size_t pos) { assert(pos < _size); return _str[pos]; } //[]重载 --- const const char& operator[](size_t pos) const { assert(pos < _size); return _str[pos]; } //reserve增容 void reserve(size_t n) { if (n > _capacity) { char* tmp = new char[n + 1];//这里加1是为了给'\0'一个空间 strcpy(tmp, _str); delete[]_str; _str = tmp; _capacity = n; } } //resize增容 void resize(size_t n, char ch = '\0') { if (n <= _size) { _size = n; _str[_size] = '\0'; } else { if (n > _capacity) { reserve(n); } memset(_str + _size, ch, n - _size); _size = n; _str[_size] = '\0'; } } //尾插字符 void push_back(char ch) { /* if (_size == _capacity) { //增容 reserve(_capacity == 0 ? 4 : _capacity * 2); } _str[_size] = ch; ++_size; _str[_size] = '\0'; */ insert(_size, ch);//复用 } //尾插字符串 void append(const char* str) { /* size_t len = strlen(str); if (_size + len > _capacity)//不需要考虑给\0空间 { reserve(_size + len); } strcpy(_str + _size, str); _size += len; */ insert(_size, str);//复用 } //尾插字符 --- +=重载 string& operator+=(char ch) { push_back(ch); return *this; } //尾插字符串 --- +=重载 string& operator+=(const char* str) { append(str); return *this; } //查找第一个匹配的字符 size_t find(char ch) { for (size_t i = 0; i < _size; ++i) { if (ch == _str[i]) { return i; } } return npos; } //查找第一个匹配的字符串 size_t find(const char* s, size_t pos = 0) { const char* ptr = strstr(_str + pos, s); if (ptr == nullptr) { return npos; } else { return ptr - _str; } } //在pos位置插入一个字符 string& insert(size_t pos, char ch) { assert(pos <= _size); if (_size == _capacity) { reserve(_capacity == 0 ? 4 : _capacity * 2); } size_t end = _size + 1; while (end > pos) { _str[end] = _str[end - 1]; --end; } _str[pos] = ch; ++_size; return *this; } //在pos位置插入一个字符串 string& insert(size_t pos, const char* s) { assert(pos <= _size); size_t len = strlen(s); if (_size + len > _capacity) { reserve(_size + len); } size_t end = _size + len; while (end >= pos + len) { _str[end] = _str[end - len]; --end; } strncpy(_str + pos, s, len); _size += len; return *this; } //从pos位置开始删除字符 string& erase(size_t pos = 0, size_t len = npos) { assert(pos < _size); if (len == npos || pos + len >= _size) { _str[pos] = '\0'; _size = pos; } else { strcpy(_str + pos, _str + pos + len); _size -= len; } return *this; } //将字符串置空 void clear() { _str[0] = '\0'; _size = 0; } private: char* _str; size_t _size; size_t _capacity;//有效字符的空间数 static const size_t npos; }; //定义npos(为了和库一致) const size_t string::npos = -1; /* 字符串s1 字符串s2 "abcd" 和 "abcd" ----false "abcd" 和 "abcde" ----true "abcde" 和 "abcd" ----false */ //字符串的比较 --- 关系运算符的重载 bool operator<(const string& s1, const string& s2) { return strcmp(s1.c_str(), s2.c_str()) < 0; } bool operator==(const string& s1, const string& s2) { return strcmp(s1.c_str(), s2.c_str()) == 0; } bool operator<=(const string& s1, const string& s2) { return s1 < s2 || s1 == s2; } bool operator>=(const string& s1, const string& s2) { return !(s1 < s2); } bool operator>(const string& s1, const string& s2) { return !(s1 <= s2); } bool operator!=(const string& s1, const string& s2) { return !(s1 == s2); } //流插入重载 ostream& operator<<(ostream& out, const string& s) { //方式一 for (auto ch : s) { out << ch; } //方式二 for (size_t i = 0; i < s.size(); ++i) { out << s[i]; } //方式三 //out << s.c_str();//不能这样写 return out; } //流提取重载 istream& operator>>(istream& in, string& s) { s.clear(); char ch = in.get(); while (ch != ' ' && ch != '\n') { s += ch; ch = in.get(); } return in; } }