如何制作一个个人网站,婚纱摄影网站设计模板,国外博客写作网站,网站怎样做seo目录
模拟实现string类的默认成员函数
模拟实现构造函数
模拟实现拷贝构造函数
模拟实现赋值运算符重载
模拟实现析构函数
string类的增容
模拟实现reserve 模拟实现resize
string类的遍历和查询
模拟实现const迭代器
模拟实现普通迭代器
模拟实现c_str
模拟实现si…目录
模拟实现string类的默认成员函数
模拟实现构造函数
模拟实现拷贝构造函数
模拟实现赋值运算符重载
模拟实现析构函数
string类的增容
模拟实现reserve 模拟实现resize
string类的遍历和查询
模拟实现const迭代器
模拟实现普通迭代器
模拟实现c_str
模拟实现size
模拟实现[ ]重载
模拟实现find查找字符
模拟实现find查找字符串
string类的修改
模拟实现push_back
模拟实现append 重载
模拟实现insert插入字符
模拟实现insert插入字符串
string类的删除
模拟实现erase删除字符或者字符串
模拟实现string类整体代码 在前几期我们学习了库中string类相关函数接口的使用为了更深层次的理解string类本期我们需要学习string类的模拟实现。
模拟实现string类的默认成员函数
模拟实现构造函数
string(const char* str):_str(new char[strlen(str) 1]),_size(strlen(str)),_capacity(_size){strcpy(_str, str);} 构造函数,给缺省值的目的是为了让字符串有默认的\0,使得编译器能够识别字符串的结束。 模拟实现拷贝构造函数
string(string s):_str(nullptr),_size(0),_capacity(0){string tmp(s._str);std::swap(_str, tmp._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);} 创建了对象交换了中间对象和新创建的对象的成员变量。 模拟实现赋值运算符重载
string operator (string s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);return *this;} 形参就是一个中间对象通过实参对象的值传递进行了拷贝构造生成了中间对象。 模拟实现析构函数
~string(){delete[] _str;_str nullptr;_size _capacity 0;} 对象声明周期结束前先调用析构函数完成资源的清理。资源清理后编译器再进行对象的销毁与对象的创建和调用构造函数的顺序刚好相反。 string类的增容
模拟实现reserve
void reserve(size_t n){if (n _capacity){//多申请一个空间是为了给\0char* tmp new char[n 1];strcpy(tmp, _str);delete[] _str;_str tmp;_capacity n;}} 需要多申请一个空间是为了留给\0。 模拟实现resize
void resize(size_t n,char ch \0){if (n _size){_str[n] \0;}else{if (n _capacity){reserve(n);}memset(_str _size, ch, n - _size);_size n;_str[_size] \0;}} resize扩容时有三种情况扩容的空间小于原来字符串有效字符的个数扩容的空间大于原来字符的个数但是小于容量扩容的空间大于原来字符的容量后两种的实际操作可以分为同一种。 string类的遍历和查询
模拟实现const迭代器
const_iterator begin()const{return _str;}const_iterator end() const{return _str _size;} 迭代器本质上就是一个指针。 const成员函数const迭代器普通对象和const对象都可以进行访问。 模拟实现普通迭代器 iterator begin(){return _str;}iterator end(){return _str _size;} 普通迭代器只有普通对象可以访问。 模拟实现c_str
const char* c_str()const{return _str;} 重载流提取之外的输出字符串的方法。 模拟实现size size_t size()const{return _size;} 什么时候设置为const成员函数什么时候设置成普通成员函数这取决于我们对字符串的操作求大小打印这些不需要改变结构的可以设置成const方便const对象去进行访问。 模拟实现[ ]重载 char operator[] (size_t pos){return _str[pos];}
模拟实现find查找字符
size_t find(char ch){for (size_t i 0; i _size; i){if (ch _str[i]){return i;}}return npos;}npos一个静态的无符号const成员变量表示整型的最大值再找不到元素时返回npos。 模拟实现find查找字符串
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;}} 因为返回的是下标所以最终通过指针相减获得了对应字符串的首元素的下标字符串首元素的下标就是整个字符串的下标因为字符串是连续存储的。 string类的修改
模拟实现push_back
void push_back(char ch){if (_size _capacity){reserve(_capacity 0 ? 4 : _capacity * 2);}_str[_size] ch;_size;_str[_size] \0;} 与顺序表类似因为string类本身就是一个数组可以理解为它就是一个顺序表。因为刚开始会覆盖\0,最终一定要在最后一个有效字符的下一位置添加上\0 。 模拟实现append void append(const char* s){//先得求出要尾插的字符串的长度因为此时空间不足的话不能以2倍扩容因为一个字符串的长度可能远远大于容量size_t len strlen(s);if (_size len _capacity){reserve(_size len);}strcpy(_str _size, s);_size len;} 需要注意扩容时不能像以往一样二倍扩容因为字符串的长度是不能预期的。 重载 //重载,尾插字符
string operator(char ch){push_back(ch);return *this;}//重载,尾插字符串
string operator(const char* str){append(str);return *this;} 本质上就是复用了push_backappend两个函数。 模拟实现insert插入字符
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;} 插入字符时与顺序表类似但是需要注意end的位置因为pos时无符号整型所以一般情况下要将end的前一个的位置移动到end位置而不是把end位置移动到end1位置这点当无符号整型判断时要注意。 模拟实现insert插入字符串
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){_str[end] _str[end - len];--end;}strncpy(_str pos, s, len);return *this;} 我们要注意一定要使用strncpy函数控制字符的个数如果使用strcpy会将\0拷贝过去导致字符串异常结束。 string类的删除
模拟实现erase删除字符或者字符串
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;} 要注意pos的范围因为我们一般删除的都是有效字符所以pos的范围就是有效字符下标的范围。缺省值是npos所以如果不给定初始值默认全部删除完。 模拟实现string类整体代码
namespace yjd
{class string{public://迭代器typedef char* iterator;typedef const char* const_iterator;//构造函数,给缺省值的目的是为了让字符串有默认的\0,使得编译器能够识别字符串的结束string(const char* str):_str(new char[strlen(str) 1]),_size(0),_capacity(0){strcpy(_str, str);}//拷贝构造函数的深拷贝进阶版本string(string s):_str(nullptr),_size(s._size),_capacity(s._capacity){string tmp(s._str);std::swap(_str, tmp._str);}//赋值运算符重载的深拷贝进阶版本2string operator (string s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);return *this;}//析构函数~string(){delete[] _str;_str nullptr;_size _capacity 0;}//const迭代器const对象和普通对象都可以调用调用const_iterator begin()const{return _str;}const_iterator end() const{return _str _size;}//普通迭代器普通对象调用iterator begin(){return _str;}iterator end(){return _str _size;}//以cout对象.c_string的方式打印字符串,什么时候设置成const类型的成员变量取决于我们的用法如果只是打印对象自然不会更改所以我们就设置成const成员函数const char* c_string()const{return _str;}//求字符串有效字符的个数size_t size()const{return _size;}//重载[],从而以数组的形式访问字符串的每个元素char operator[] (size_t pos){return _str[pos];}//进行空间的扩容实现reserve的功能void reserve(size_t n){if (n _capacity){//多申请一个空间是为了给\0char* 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){_str[n] \0;}else{if (n _capacity){reserve(n);}memset(_str _size, ch, n - _size);_size n;_str[_size] \0;}}//尾插一个字符实现push_back的功能void push_back(char ch){if (_size _capacity){reserve(_capacity 0 ? 4 : _capacity * 2);}_str[_size] ch;_size;_str[_size] \0;}//尾插一个字符实现append的功能void append(const char* s){//先得求出要尾插的字符串的长度因为此时空间不足的话不能以2倍扩容因为一个字符串的长度可能远远大于容量size_t len strlen(s);if (_size len _capacity){reserve(_size len);}strcpy(_str _size, s);_size len;}//重载尾插字符string operator(char ch){push_back(ch);return *this;}//重载,尾插字符串string operator(const char* str){append(str);return *this;}//实现find进行字符的查找size_t find(char ch){for (size_t i 0; i _size; i){if (ch _str[i]){return i;}}return npos;}//实现find查找某个字符串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;}}//插入元素实现insertstring 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;}//实现insert插入字符串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){_str[end] _str[end - len];--end;}strncpy(_str pos, s, len);return *this;}//进行字符串的删除实现erasestring 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;}private:char* _str;size_t _size;size_t _capacity;//定义静态常变量npos找不到是就返回nposstatic const size_t npos;};const size_t string::npos -1; 以上便是string类常见接口的模拟实现可以帮助大家对string类更深一步的了解模拟实现不一定要全部掌握但是库中的string类中的相关常见接口一定要掌握。 本期内容到此结束^_^