五、capacity
1.size
类外成员不能直接访问类的私有属性/数据,因此需要提供一个接口进行访问数据,但是要对数据进行保护,因此用了const传参和传值返回。
访问string中的元素个数。
size_t size()const { return _size; }
2.capacity
访问string的容量。
size_t capacity()const { return _capacity; }
3.empty
判断字符串是否为空。
bool empty()const { if (_size == 0) { return true; } return false; }
4.resize
修改字符串的元素个数,可以尾插指定的字符,未指定则默认插入’\0’。
void resize(size_t n, char c = '\0')//更改元素个数 { if (n <= _size) { _size = n; _str[_size] = '\0'; } else { reserve(n);//先扩容,再加元素 for (size_t i = _size; i < n; ++i) { _str[i] = c; } _str[n] = '\0'; _size = n; } }
5.reserve
修改字符串的容量。
void reserve(size_t n)//更改容量大小 { if (n > _capacity) { char* temp = new char[n + 1];//先开空间再拷贝值(避免因为空间开辟失败的异常使_str原地址也丢失了) strcpy(temp, _str); delete[] _str; _str = temp; _capacity = n; } }
六、access
访问字符串中的字符,运算符[]重载。
1.普通对象的接口(可读可写)
char& operator[](size_t index)//普通对象的接口(可读可写) { assert(index < _size); return _str[index]; }
2.const对象的接口(只读)
const char& operator[](size_t index)const//const对象的接口(只读) { assert(index < _size); return _str[index]; }
七、relational operators
1.运算符<重载
bool operator<(const string& s) { size_t len = _size < s._size ? _size : s._size; for (size_t i = 0; i < len; ++i) { if ((*this)[i] >= s[i]) { return false; } return true; } }
2.运算符>重载
bool operator>(const string& s) { size_t len = _size < s._size ? _size : s._size; for (size_t i = 0; i < len; ++i) { if ((*this)[i] <= s[i]) { return false; } return true; } }
3.运算符<=重载
复用>。
bool operator<=(const string& s) { return !(*this > s); }
4.运算符>=重载
复用<。
bool operator>=(const string& s) { return !(*this < s); }
5.运算符==重载
复用<和>。
bool operator==(const string& s) { return (!((*this) < s)) && (!((*this) > s)); }
6.运算符!=重载
复用==。
bool operator!=(const string& s) { return !((*this) == s); }
八、String operations
1.find
1.找字符
找一个字符第一次在字符串中出现的下标
// 返回c在string中第一次出现的位置(下标) size_t find(char c, size_t pos = 0) const { assert(pos < _size); for (size_t i = 0; i < _size; ++i) { if ((*this)[i] == c) { return i; } } return npos; }
2.找子串
找一个子串第一次出现在字符串中的下标
复用C语言对字符串的操作——strstr函数(在一个字符串中找子串)
// 返回子串s在string中第一次出现的位置(下标) size_t find(const char* s, size_t pos = 0) const { assert(pos < _size); const char* ptr = strstr(_str + pos, s); if (ptr == nullptr) { return npos; } else { return ptr - _str; } }
也可以一个字符一个字符的遍历寻找:
// 返回子串s在string中第一次出现的位置(下标) size_t find(const char* s, size_t pos = 0) const { assert(pos < _size); size_t i = 0; while (i < _size) { int flag = 0; if ((*this)[i] == s[0]) { size_t k = i; for (size_t j = 0; j < strlen(s); ++j, ++k) { if ((*this)[k] != s[j]) { flag = 1; } } if (flag == 0) return i; } i++; } return npos; }
2.c_str
返回字符串的地址
const char* c_str()const { return _str; }
九、Non-member function overloads
1.流插入
ostream& operator<<(ostream& _cout, const string& s) { for (size_t i = 0; i < s.size(); i++) { _cout << s[i]; } return _cout; }
2.流提取
istream& operator>>(istream& _cin, string& s) { s.clear();//将原来s中的值清除 char buff[128] = { '\0' }; size_t i = 0; char ch = _cin.get();//这里不能使用getc或者scanf函数的原因是他们都是按照空格' '或者换行'\n'进行分割内容的,所以无法取到空格和换行,因此只能用get() while (ch != ' ' || ch != '\n') { if (i == 127)//缓存部分满了 { s += buff;//将内容存入s,同时将缓存部分情况 i = 0; } buff[i++] = ch; ch = _cin.get(); } return _cin; }
十、私有属性
private: char* _str; size_t _capacity; size_t _size; const static size_t npos = -1;//只有这个特例可以这样定义,其他static数据成员都要在类内声明,在类外定义。
总结
以上就是今天要讲的内容,本文介绍了作者自己实现的string类的相关类成员函数,如果文章中的内容有错误或者不严谨的部分,欢迎大家在评论区指出,也欢迎大家在评论区提问、交流。
最后,如果本篇文章对你有所启发的话,希望可以多多支持作者,谢谢大家!