邯郸装修网站建设,wordpress 路径插件,专业设计网站的公司,网店网络营销策划方案字符串 - C引用 (cplusplus.com)这里给出标准官方的string实现#xff0c;可以看到设计还是较为复杂的#xff0c;有成员函数#xff0c;迭代器#xff0c;修饰符#xff0c;容量#xff0c;元素访问#xff0c;字符串操作等#xff0c;将字符尽可能的需求都设计出来引用 (cplusplus.com)这里给出标准官方的string实现可以看到设计还是较为复杂的有成员函数迭代器修饰符容量元素访问字符串操作等将字符尽可能的需求都设计出来我们这里实现string中比较常用且重要的。
成员变量
private:char* _str;size_t _size;size_t _capacity;
public:const static size_t npos;//声明一个npos 表示返回找不到的下标 或从-1的下一个开始寻找
目录
1.迭代器实现
2.成员函数
空构造 有参构造 拷贝构造
析构 重载
3.字符串操作
c_str find substr
5.修饰符
push_back append operator
insert erase
6.容量
reserve
size
capacity
resize
7.元素访问
重载下标引用操作符
8.运算符重载
重载
重载
重载
重载
重载
重载
重载输入流
重载输出流 1.迭代器实现
这里我们实现了常量迭代器与正常的迭代器反向迭代器并未实现。对于string这里的迭代器我们可以看到本质上是一个char *类型的指针在某些地方可能不是指针且它的用法也是与指针如出一撤。这里对于反向迭代器后面再实现。 typedef char* iterator;//迭代器const typedef 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;};
在这里 我们将char*定义为一个新的类型并且给出它的成员函数也就是迭代器的各个位置从而实现。利用迭代器我们可以对他进行遍历
Mystring::iterator it str1.begin();while (it ! str1.end()){cout *it ;it;}//范围forfor (auto tmp : str1){cout tmp ;} 同时其实本质上范围for的底层就是利用迭代器实现的编译器在遇到范围for这样的写法时就会将这一段代码替换成下面迭代器实现的这样的遍历。
2.成员函数
空构造
实际上并不需要实现我们这里给出它的实现是了解对于空字符串的构造函数虽说是空字符串但不可直接赋值nullptr否则后面实例化对象调成员函数时就是解引用空指针空字符串故这里会报错实际上实现会给几个字节空间放\0
Mystring():_str(new char[1]),_capacity(0),_size(0){} 有参构造
//有参构造Mystring(const char* str) : _size(strlen(str)), _capacity(_size)//缺省值直接给不给\0原先就有\0{//注意这里的字符串利用深拷贝,且初始化顺序遵循声明顺序_str new char[_capacity 1];//多开一个给\0strcpy(_str, str);} 拷贝构造
还是老问题直接的赋值会造成两次析构故这里需要进行深拷贝。
//拷贝构造//之前讲过浅拷贝会析构两次深拷贝解决Mystring(const Mystring s){_str new char[s._capacity 1];memset(_str, 0, s._capacity);strcpy(_str, s._str);this-_size s._size;this-_capacity s._capacity;}
析构
释放及初始化
//析构~Mystring(){delete [] _str;_str nullptr;_capacity _size 0;} 重载
// 赋值重载Mystring operator(const Mystring s){if (*this ! s){char* temp new char[s._capacity1];strcpy(temp, s._str);delete []_str;_str temp;this-_size s._size;this-_capacity s._capacity;}return *this;} 这里的赋值重载区分拷贝构造
用现有对象初始化定义的对象---------拷贝构造
用现有对象赋值给现有对象------------赋值
3.字符串操作
这里实现几个比较重要的常用的。
c_str
const char* c_str()const{return _str;} find
这里给出了两种实现字符寻找与字符串寻找
//寻找某个字符返回其下标位置size_t find(char ch,size_t pos0){for (size_t i pos; i _size; i){if (ch _str[i]){return i;}}return npos;//找不到返回-1}//寻找某个字符串返回其相同的个数size_t find(const char* ch, size_t pos 0){//暴力匹配const char* tmp strstr(_strpos, ch);if (tmp! nullptr){return tmp - _str;//指针相减找到个数}else{return npos;}} substr
//从pos位置处取n个字符,或n到 nposMystring substr(size_t pos, size_t lennpos){assert(pos _size);Mystring s;size_t end pos len;if (len pos || len pos _size){len _size - len;end _size;}s.reserve(len);for (size_t i pos; i poslen; i){s _str[i];//这里利用重载后的本质上就是尾插}return s;}
5.修饰符
push_back
//尾插字符void push_back(char ch){//尾插的操作很简单但是要考虑到扩容的问题if (_size _capacity){reserve(_capacity0?4:_capacity * 2);//为了避免空间是0扩容失败}_str[_size] ch;_size;_str[_size] \0;} append
//尾插字符串void append(const char*ch){size_t num strlen(ch);if (num _size _capacity){reserve(num _size);}strcpy(_str _size, ch);_size num;//注意这里直接运用strcpy拷贝过来连同\0一起之后变为新大小} operator
这里重载的是利用了尾插的实现故也作为字符串修饰
也是两种实现字符或字符串
Mystring operator(const char ch){push_back(ch);return *this;}Mystring operator(const char* ch){append(ch);return *this;}
insert 也是有两种实现方式
注意注释的提示若这里想要进行头插此时end0。只有当end--到负数才停止而size_t 无法去判断正负数,程序崩溃解决方法将类型转换为int 或者修改后移顺序_str[end] _str[end-1];去掉条件。
其次就是对于扩容需要考虑空间为0的情况。
//某个位置插入字符void insert(size_t pos,char ch){assert(pos _size);if (_size _capacity){reserve(_capacity 0 ? 4 : _capacity * 2);//为了避免空间是0扩容失败}int end _size;//pos位置处后移while (end(int)pos){//后移_str[end 1] _str[end];--end;}//插入_str[pos] ch;}//某个位置插入字符串void insert(size_t pos,char *ch){size_t len strlen(ch);if (_size len_capacity){reserve(_capacity 0 ? 4 : _capacity * 2);//为了避免空间是0扩容失败}size_t end _size;//pos位置处后移while (end pos){//后移_str[end len] _str[end];--end;}//插入strncpy(_strpos, ch,len);_size len;} erase
删除pos位置后的npos个字符这里的npos给的是缺省值再没参数的情况下为-1也就是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;}}
6.容量
reserve
//扩容void reserve(size_t n){if (n _size){char* tmp new char[n 1];//这里还是留一个\0位置strcpy(tmp, _str);delete[]_str;_str tmp;_capacity n;}}size
//返回大小
size_t size()const{return _size;}
capacity
//返回容量
size_t capacity()const{return _capacity;}
resize
//初始化大小为n且可以赋值之后的void resize(size_t n,char c\0){if (n _size){//删除_str[n] \0;_size n;}else{//扩容reserve(n);//初始化值while (_size n){_str[_size] c;_size;}//末尾给\0_str[_size] \0;}}
7.元素访问
重载下标引用操作符
const char operator[](int pos)const{assert(pos _size);return _str[pos];}
8.运算符重载
对于这里的比较运算符通过实现与再取反实现 ,,!.
重载
bool operator(const Mystring s1){return strcmp(this-_str, s1._str) 0;}
重载
bool operator(const Mystring s){return strcmp(this-_str, s._str) 0;}
重载
bool operator(const Mystring s){return *this s || *this s;//由于与已实现直接用}
重载
bool operator(const Mystring s){return !( *this s) ;//取反}
重载
bool operator(const Mystring s){return !(*this s);//取反}
重载
bool operator!(const Mystring s){return!(*thiss);}
重载输入流
//流插入
istream operator(istream in, Mystring s)
{char ch;ch in.get();//一个个拿字符包括空格与\nwhile (ch ! ch ! \n){s ch;ch in.get();}return in;
}重载输出流
//流提取
ostream operator(ostream out, const Mystring s)
{for (size_t i 0; i s.size(); i){out s[i];}return out;
}