目录
1.string的四大默认函数
1.1构造函数
1.2析构函数
1.3拷贝构造
1.4赋值运算符重载
2.访问string的三种方式
2.1[]访问
2.2迭代器访问
2.3范围for(本质是迭代器)
3.string相关功能的实现
3.1modify
3.2capacity
3.3access
3.4relations
3.5补充
4.补充
1.string的四个默认函数
1.1构造函数
//构造函数 String(const char* str = "") :_size(strlen(str)) { if (str == nullptr) exit(-1); _capacity = _size == 0 ? 3 : _size; _str = new char[_capacity + 1]; strcpy(_str,str); }
1.2析构函数
//析构函数 ~String() { if (_str == nullptr) assert(false); delete[] _str; _str = nullptr; _size = _capacity = 0; }
1.3拷贝构造
//拷贝构造 String(const String& s) { _str = new char[strlen(s._str)+1]; strcpy(_str,s._str); }
1.4赋值运算符重载
//赋值运算符 String& operator=(const String& s) { if (this != &s) { char* tmp = new char[strlen(s._str)+1]; strcpy(tmp,s._str); delete[] _str; _str = tmp; _size = s._size; _capacity = s._capacity; } return *this; }
2.访问string的三种方式
2.1[]访问
char& operator[](size_t pos) { return *(_str + pos); }
2.2迭代器访问
//迭代器 typedef char* iterator; typedef const char* const_iterator; iterator begin() { return _str; } iterator begin()const { return _str; } iterator end() { return _str + _size; } iterator end()const { return _str + _size; }
2.3范围for(本质是迭代器)
//范围for cout << "范围for: "; for (auto ch : s1) { cout << ch; }
3.string相关功能的实现
3.1modify
-push_back
//尾插一个字符 void push_back(char ch) { //检查是否扩容 if (_size + 1 > _capacity) reserve(2*_capacity); //插入数据 _str[_size] = ch; ++_size; _str[_size] = '\0'; }
-+= 字符
//重载 String& operator+=(char ch) { push_back(ch); return *this; }
-append
//append void append(const char* str) { int len = strlen(str); if (_size + len > _capacity) //扩容 { reserve(_capacity + len); } //插入数据 strcat(_str,str); _size += len; }
-+=字符串
//重载+= String& operator+=(const char* str) { append(str); return *this; }
-clear
//clear void clear() { _size = 0; _str[_size] = '0'; }
-swap
//swap void swap(String& s) { std::swap(_str,s._str); std::swap(_size,s._size); std::swap(_capacity, s._capacity); }
-C格式字符串
//C格式的字符串 const char* c_str()const { return _str; }
3.2capacity
-size
//获取长度 size_t size()const { return _size; }
-capacity
//获取容量 size_t size()const { return _capacity; }
-bool empty
bool empty()const { return _size == 0; }
-reserve(扩容)
//reserve(扩容) void reserve(size_t n) { if (n < _size) //删除数据 { _str[n] = '\0'; } if (n > _capacity) { //拷贝原来的数据 char* tmp = new char[n + 1]; 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 //n>=_size { if (n > _capacity) { reserve(n); } //将剩余的字符初始化 size_t i = _size; while (i < n) { _str[i] = ch; i++; } _size = n;//改变size大小 _str[_size] = '\0'; } }
3.3access
// access char& operator[](size_t pos) { return *(_str + pos); } char& operator[](size_t pos)const { return *(_str + pos); }
3.4relations
//relational operators bool operator<(const String& s) { return strcmp(_str, s._str) < 0; } bool operator <=(const String& s) { return strcmp(_str, s._str) <= 0; } bool operator>(const String& s) { return strcmp(_str, s._str) > 0; } bool operator >=(const String& s) { return strcmp(_str, s._str) >= 0; } bool operator==(const String& s) { return strcmp(_str,s._str) == 0; } bool operator!=(const String& s) { return strcmp(_str, s._str) != 0; }
3.5补充
1.-find //返回c再string中第一次出现的位置
//返回c再string中第一次出现的位置 size_t find(char c,size_t pos = 0) { assert(pos < _size); while (pos< _size) { if (_str[pos] == c) { return pos; } pos++; } return npos; }
--find //字符串
//返回子字串在string中第一次出现的位置 size_t find(const char* str, size_t pos = 0)const { return strstr(_str,str+pos) - _str - pos; }
2.//在pos位置上插入字符c/字符串str,并返回该字符的位置
-字符
//在pos位置上插入字符c/字符串str,并返回该字符的位置 size_t insert(size_t pos ,char ch ) { assert(pos < _size); //判断是否需要扩容 if (_size + 1 > _capacity) { reserve(2*_capacity); } //从后往前挪动数据 size_t end = _size + 1; while (end > pos) { _str[end] = _str[end - 1]; end--; } //在pos位置插入数据 _str[pos] = ch; //更新_size _size++; return pos; }
-字符串
size_t insert(size_t pos, const char* str) { assert(pos < _size); size_t len = strlen(str); //扩容 if (_size + len > _capacity) { reserve(_capacity + len); } //挪动数据 size_t end = _size + len; while (end - len > pos) { _str[end] = _str[end - len]; end--; } //在pos位置插入字符串 strncpy(_str + pos ,str,len); //更新_size _size += len; return pos; }
//删除数据
// 删除pos位置上的元素,并返回该元素的下一个位置 String& erase(size_t pos,size_t len) { assert(pos < _size); //将pos后的数据删完 if (len == npos || pos + len > _size) { _str[pos] = '\0'; _size = pos ; } else //删除一部分 { //把删除len后面的数据拷贝到pos后 strcpy(_str + pos ,_str + pos + len); _size -= len; } return *this; }
3.>>与<<的重载
<<
ostream& operator<<(ostream& _cout, const my_func::String& s) { for (auto e : s) { _cout << e; } _cout << endl; return _cout; }
>>
istream& operator>>(istream& _cin,my_func::String& s) { s.clear();//清空之前的内容 //先往数组里面放,满了/读取到'\n'再往s里面放 //这样避免频繁的扩容 char buff[128]; char ch = cin.get(); size_t i = 0; while (ch != '\n') { buff[i++] = ch; if (i == 127) { s += buff;//满了往s里面加 i = 0; } ch = cin.get();//继续读取 } if (i != 0) { s += buff; } return _cin; }
4.补充
1.reserve与resize
reserve不会改变_size的大小(有效元素的个数)
(当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。)
resize会改变并且用字符初始化多出来的空间
(resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变)
2.str与c_str
c_str是string
类提供的成员函数,用于将string
对象转换为C风格的字符串(以空字符结尾的字符数组)。示例:
c_str在使用cout打印的时候,遇到\0就会停止打印
str 在使用重载后的<<打印,是按_size打印的