目录
- size_t size() const获取size大小
- 代码
- size_t capacity()const获取capacity
- 代码
- char& operator[](size_t pos)获取pos位置字符
- 代码
- const char& operator[](size_t pos) const获取pos位置字符(只能读取不能更改)
- 代码
- const char* c_str() const获取_str的地址
- 代码
- iterator和const iterator迭代器
- iterator begin()和const iterator begin()
- 代码
- iterator end()和const iterator end()
- 代码
- void erase(size_t pos, size_t len = npos)从len位置开始往前删除数据到pos位置
- 错误写法
- 代码
- void resize(size_t n, char ch = '\0')插入数据
- 代码
- size_t find(char ch)查找字符所在位置
- 代码
- size_t find(char ch,size_t pos=0) const查找pos位置之后字符所在的位置
- 代码
- size_t find(const char* sub, size_t pos = 0) const查找pos位置开始字符串所在位置
- 代码
- string substr(size_t pos = 0, size_t len = npos)取pos位置之后指定长度的字符串
- 代码
感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接
🐒🐒🐒 个人主页
🥸🥸🥸 C语言
🐿️🐿️🐿️ C语言例题
🐣🐣🐣 python
🐓🐓🐓 数据结构C语言
🐔🐔🐔 C++
🐿️🐿️🐿️ 文章链接目录
size_t size() const获取size大小
因为返回的值是不允许被修改的,所以在后面加了个const
代码
size_t size() const
{return _size;
}
size_t capacity()const获取capacity
代码
size_t capacity()const
{return _capacity;
}
char& operator[](size_t pos)获取pos位置字符
这里有两个函数,因为有时候会遇到常量字符串,就是只能读取数据,但是不能修改,所以需要分两个函数来对待不同的情况
代码
char& operator[](size_t pos)
{assert(pos<_size);return _str[pos];
}
const char& operator[](size_t pos) const获取pos位置字符(只能读取不能更改)
代码
const char operator[](size_t pos) const{assert(pos < _size);return _str[pos];}
我们加上断言可以防止访问越界,并且因为pos位置的空间是通过new开辟出来的,而new开辟出来的空间是存在堆上的,所以这里出了作用域并不会被销毁,因此我们就直接引用返回,引用返回的好处是在函数外面我们不仅可以读取数据,还可以更改数据
const char* c_str() const获取_str的地址
代码
const char* c_str() const
{return _str;
}
iterator和const iterator迭代器
迭代器我们用指针来实现
iterator begin()和const iterator begin()
代码
typedef char* iterator;iterator begin(){return _str;}
typedef const char* iterator const;const iterator begin() const{return _str;}
我们将char*类型简化命名为iterator,由于是在类域里面,所以不会和string中的iterator冲突
iterator end()和const iterator end()
代码
iterator end(){return _str + _size;}
const iterator end() const{return _str + _size;}
void erase(size_t pos, size_t len = npos)从len位置开始往前删除数据到pos位置
错误写法
static const size_t npos = -1;void erase(size_t pos, size_t len = npos){assert(pos <= _size);if (len == npos || len+pos >= _size ){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}}
但是这里有溢出的风险,pos+len中如果pos=npos,因为npos已经是最大值了,npos+一个任意数就溢出了,所以需要对这里进行一点修改
static const size_t npos = -1;
void erase(size_t pos, size_t len = npos)
{assert(pos <= _size);if (len == npos || len >= _size - pos){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}
}
_size-pos的最大值也是npos,但是strcpy(_str + pos, _str + pos + len)也有_str + pos + len,这不还是有溢出的风险吗,所以我觉得可以直接加个断言这样要方便很多
代码
static const size_t npos = -1;
void erase(size_t pos, size_t len = npos)
{assert(pos <= _size);assert(_size + pos + len <= npos);if (len == npos || len >= _size - pos){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}
}
static const size_t npos = -1是因为我写的函数用了命名空间域包起来的,直接用npos会显示未定义,所以我就自己定义了一个npos
void resize(size_t n, char ch = ‘\0’)插入数据
代码
void resize(size_t n, char ch = '\0')
{if (n <= _size){_str[n] = '\0';_size = n;}else{reserve(n);for (size_t i = _size; i < n; i++){_str[i] = ch;}_str[n]='\0';_size = n;}
}
代码逻辑为当n小于等于size的时候就以n位置为结束位置,让_str[n]=’\0’,不管后面是否还有数据,总之就是n后面的数据不要了
当n大于_size的时候,就从_size位置开始尾差字符ch
size_t find(char ch)查找字符所在位置
代码
size_t find(char ch)
{for (size_t i = 0; i < _size; i++){if (_str[i] == ch){return i;}}return npos;
}
这个比较容易理解,就是遍历一遍字符串,找到字符ch就返回下标
没有找到就返回npos,因为npos是最大的值,一般的字符串都没有那么大,所以返回npos就表示没有找到
size_t find(char ch,size_t pos=0) const查找pos位置之后字符所在的位置
代码
size_t find(char ch,size_t pos=0) const
{for (size_t i = pos; i < _size; i++){if (_str[i] == ch){return i;}}return npos;
}
和上面的完全一样,区别就是是从pos位置开始遍历,而上面的是从最开始的位置遍历
size_t find(const char* sub, size_t pos = 0) const查找pos位置开始字符串所在位置
代码
size_t find(const char* sub, size_t pos = 0) const
{assert(pos < _size);const char* p = strstr(_str+pos, sub);if (p){return p - _str;}elsereturn npos;
}
这个是直接用 strstr去找的,strstr作用是返回字符串中首次出现子串的地址。
如果strstr返回的不是空,就说明找到了,所以返回下标就是两个指针相减,没找到就返回npos
string substr(size_t pos = 0, size_t len = npos)取pos位置之后指定长度的字符串
代码
string substr(size_t pos = 0, size_t len = npos){string sub;if (len == npos || len >= _size - pos){for (size_t i = pos; i < _size; i++){sub += _str[i];}}else{for (size_t i = pos; i < pos+len; i++){sub += _str[i];}}return sub;}
有两种情况如下图:
pos+len<size
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fmxCytoz-1721783392372)(https://i-blog.csdnimg.cn/direct/ea108802adc345ae8bcc4e37c50c1e9e.png)]
pos+len>=size
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UTZtPmmP-1721783392375)(https://i-blog.csdnimg.cn/direct/520fc2c971ad4b9da282e066f7eed7ab.png)]
我们要去len个长度的字符串,第一中情况就可以直接取,因为len+pos小于size,所以不用担心在取的时候越界
第二种情况就是len+pos>=size,这个时候就要注意不能取越界了,所以就从pos位置一直取到size位置