行业知识
【C++初阶】string模拟实现
✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
追风赶月莫停留
平芜尽处是春山
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
string模拟实现
- 构造函数
- 析构函数
- 重载
- 方括号引用
- +=操作
- =操作
- 迭代器
- 增删查改
- 增
- 找
- 流提取和流插入
构造函数
//有参构造string(char* str){size_t _size = strlen(str);_capacity = _size;str = new char[_capacity+1];strcpy(_str, str);}//无参构造string(){_str = new char[1];_size = 0;_capacity = 0;_str[0] = 'string (const char* str = "
';}析构函数
"){size_t _size = strlen(str);_capacity = _size;_str = new char[_capacity+1];strcpy(_str, str);}至于无参构造中,为了防止解引用发生错误,所以特有开了一个空间,并赋值为斜杠0。
上面代码就是普通的构造函数的写法,无参和有参构造,这里我们并不采用初始化列表的方式进行初始化。
但实际我们并不会这么写,会直接写一个全缺省:
~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}上面中初始化时并不能直接赋值给’\0’,str是字符串类型而’\0’是字符,两者类型不一样,所以应赋值"\0"。当然也可以不用赋值,直接空字符串也是,因为常量字符串中自带斜杠0。
重载
方括号引用
析构函数就没有什么特别需要注意的了,和常规写法差不多
char& operator[](size_t pos){assert(pos push_back(str);return *this;}string& operator+=(const char* str){append(str);return *this;}if(_str != &s){char* tem = new char[s._capacity+1];strcpy(tem, s._str);delete[] _str;_str = tem;_size = s._size;_capacity = s._capacity;}return *this;}return _str;}iterator end(){return _str + _size;}if (n _capacity){char* cur = new char[n+1];strcpy(cur, _str);delete[] _str;_str = cur;_capacity = n;}}增
void push_back(char ch){if (_size == _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;_size++;_str[_size] = 'void append(const char* str){size_t len = strlen(str);if (_size+len > _capacity){reserve(_size+len);}strcpy(_str+_size, str);_size += len;}';}这是一个扩容函数,在push_back或insert时,空间都有可能满,所以会先进行扩容。
void insert(size_t pos, char str){assert(pos size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}size_t end = _size ;while (end = pos){_str[end + 1] = str[end];end--;}_str[pos] = str;_size++;}void insert(size_t pos, char* str){size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}size_t end = _size;while (end >= pos){_str[end + len] = _str[end];end--;}strncpy(_str+pos, str, len);_size += len;}push_back()函数是在原本string中最后面的位置添加一个字符。
找
append()函数和push_back()函数还是有点大径相同,只不过append()是增加一个字符串在原string类后面,不过有一些细节还是需要注意。
size_t Find(const char* str, size_t pos = 0){const char* ptr = strstr(_str+pos, str);if (ptr == nullptr){return npos;}else{return ptr - _str;}}insert()函数是一个可以在容器内插入字符的函数,在进行插入的时候都要对容器内的空间进行检查,防止空间满。在这里还要注意一点,我们是利用了end来当做循环条件,而end的类型是size_t ,而size_t是无符号整型。
而当pos为0时,这个时候循环结束条件就是end=-1,但end是size_t 类型,所以当end=-1时,实际上并不会得到你所期望的负数结果。由于size_t是一个无符号整形,所以它会将-1解释为一个非常大的正数。
所以这种情况下,程序就会陷入***循环。
string(const string& s){_str = new char[s._capacity+1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity; }该insert()函数和上面的insert()函数功能差不多,但是这里insert()是插入一段字符,而上面的insert()函数是插入一个字符。
这里最后不能用strcpy(),因为strcpy()会把斜杠0一起复制过去,这样就会覆盖原有的一个值。
流提取和流插入
size_t Find(char ch, size_t pos = 0){for(size_t i = pos; iFind()函数是查找某个元素,并返回下标值,npos是全局静态变量,它值为-1, 在这里我们给了pos默认值,默认是从0开始找,也可以指定从那个数开始找。
ostream& operatorfor (auto ch : s){out _size = 0;_str[0] = '';}istream& operator(istream& in, string& s){s.clear();char ch = in.get();while(ch != ' ' && ch != '\n'){s += ch;ch = in.get();}return in}_size = 0;_str[0] = '';}istream& operator>(istream& in, string& s){s.clear();char open[128] = {0};char ch = in.get();while(ch != ' ' && ch != '\n'){open[i++] = ch;if (i == 127){open[i] = '';s += open;i = 0;}ch = in.get();}if (i > 0){open[i] = '';s += ch;}return in;}该函数是查找一段字符串的函数,并返回该字符串的起始位置,npos是全局静态变量,值为-1;
string substr(size_t pos, size_t len = npos){assert(pos _size){end = _size;}string str;for (size_t i = pos; isubstr()函数从主容器中取出指定范围的数据,其中npos是在上面已经提到过了,而在这len也是size_t类型,上面说过size_t是无符号整型,一旦len为负数,系统就会理解len是一个很大的值,也就相当于要取出的数大于pos后面的数据长度了,所以只是把后面的数全部取出来,和pos+len的情况是一样,所以在这里就吧它俩当成一种情况
使用substr()函数时要注意有没有深拷贝构造函数,程序会报错,需要提前写构造函数:
改进过的流提取就节省了很多空间,这里是利用了数组open,来临时存储数据,数组满了,再直接利用操作符"+="操作即可。
关于本章知识点如果有不足或者遗漏,欢迎大家指正,谢谢!!!
上一篇:linux服务器怎么拉黑ip?
下一篇:曙光服务器电源怎么启动?