目录
- void reserve(size_t n)扩容实现
- 代码
- void insert(size_t pos, char ch)字符前插
- 错误写法
- 代码
- void insert(size_t pos, const char* str)在指定位置插入字符串
- 错误写法
- 代码
- void push_back(char ch)字符尾差
- 写法一
- 写法二
- void append(const char* str)字符串尾差
- 写法一
- 写法二
- string& operator+=(char ch)字符+=
- 代码
- string& operator+=(const char* str)字符串+=
- 代码
感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接
🐒🐒🐒 个人主页
🥸🥸🥸 C语言
🐿️🐿️🐿️ C语言例题
🐣🐣🐣 python
🐓🐓🐓 数据结构C语言
🐔🐔🐔 C++
🐿️🐿️🐿️ 文章链接目录
void reserve(size_t n)扩容实现
void reserve(size_t n)我们需要先判断如果传入的n值是大于或等于_capacity时,就代表需要扩容,这里的扩容我们用new来扩容
new扩容的方式就先用一个char*的tmp类型指针,然后new开辟一块空间,空间大小为n个字节
因为new开辟的空间是没有数据的,所以我们需要将_str的数据拷贝过来,所以strcpy,然后拷贝之后释放掉原来的空间
让_str指向tmp所指向的空间,之后更改_capacity的值
代码
void reserve(size_t n)
{
if (n > _capacity)
{
char* tmp = new char[n];
strcpy(tmp, _str);
delete[]_str;
_str = tmp;
_capacity = n;
}
void insert(size_t pos, char ch)字符前插
错误写法
void insert(size_t pos, char ch)
{
assert(pos <= _size);
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : 2 * _capacity);
}
size_t end = _size;
while (end >= pos)
{
_str[end + 1] = _str[end];
--end;
}
_str[pos] = ch;
_size++;
}
这段代码的逻辑是这样的,让end指向\0位置,从后往前交换
当end==pos的时候,就是将pos位置的字符给pos+1位置,之后pos位置就可以插入我们想要插入的字符了





这个写法看上去没什么问题,事实上当pos=0的时候end是不可能小于0的,所以问题就出在这里,因为end是size_t的类型,那我们改成int类型是不是就可以解决了呢?
事实上还是不行,因为pos的类型是size_t,当运算符两边操作数类型不同的时候是会发生类型提升的,提升原则一般是向范围大的类型提升,所以这里的end还是会变成size_t
将pos改成int的话其实也是可以的,但是因为库里的类型就是size_t,所以我们不建议直接将传参类型改成int,而是在判断的时候强制类型转换
代码
void insert(size_t pos, char ch)
{
assert(pos <= _size);
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : 2 * _capacity);
}
int end = _size;
while (end >= (int)pos)
{
_str[end + 1] = _str[end];
--end;
}
_str[pos] = ch;
_size++;
}
其次我们还可以在不改变类型的情况下用另外种写法
我们只需要让end变成size+1,当end-pos的时候就直接跳出来,这样就可以避免end<0这样的情况
void insert(size_t pos, char ch)
{
assert(pos <= _size);
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : 2 * _capacity);
}
size_t end = _size+1;
while (end > pos)
{
_str[end ] = _str[end-1];
--end;
}
_str[pos] = ch;
_size++;
}
void insert(size_t pos, const char* str)在指定位置插入字符串
错误写法
void insert(size_t pos, const char* str)
{
assert(pos <= _size);
size_t len = sizeof(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
size_t end = _size + len;
while (end > pos)
{
_str[end ] = _str[end - len];
end--;
}
strncpy(_str + pos, str, len);
_size += len;
}
这个写法有两个问题
第一个是size_t len = sizeof(str)有问题,因为sizeof把\0给算进去了,如果算进去\0的话,strncpy(_str + pos, str, len)会把str的\0也给拷贝进去
第二个是end>pos条件有问题,原本是想将pos位置的数据往后挪到,但是有了这个条件后,pos位置之前的数据也会被挪到后面去


所以条件判断应该在end>pos+len和end>=pos+len里面去选,具体选谁我们用下面的图来说明





因为pos位置的数据可以往后挪,但是pos位置之前的数据不可以挪,所以end-len<=pos,将len往右移得end<=pos+len

代码
void insert(size_t pos, const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
size_t end = _size + len;
while (end > pos)
{
_str[end ] = _str[end - len];
end--;
}
strncpy(_str + pos, str, len);
_size += len;
}
void push_back(char ch)字符尾差
void push_back(char ch)是一次插入一个字符,因为字符的大小是固定的,所以我们每次需要扩容的时候只扩2被就足够了
并且我们需要判断_capacity=0的情况,所以用一个三目判断来实现
之后将要插入的字符插入的_str中_size位置,因为插入时会将原来的\0覆盖掉,所以在插入后需要++_size,然后将\0再插入到_size位置
写法一
void push_back(char ch)
{
if (_size == _capacity)
{
reserve(_capacity==0?4:2 * _capacity);
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
}
写法二
void push_back(char ch)
{
insert(_size, ch);
}
void append(const char* str)字符串尾差
append 的扩容不像push_back一样每次扩2倍,因为append插入的字符串,字符串我们不确定他一次插入多大,所以要算str的长度
然后用strcpy拷贝
这里也可以用strcat,但是strcat需要遍历一遍,找到\0才开始拷贝,这样就比较麻烦,而strcpy是直接在字符串后面拷贝,所以选择用strcpy
写法一
void append(const char* str)
{
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
strcpy(_str + _size, str);
_size += len;
}
写法二
void append(const char* str)
{
insert(_size, str);
}
string& operator+=(char ch)字符+=
operator+=其实就是尾差一个数据,然后返回string对象的指针
代码
string& operator+=(char ch)
{
push_back(ch);
return *this;
}
string& operator+=(const char* str)字符串+=
这两个函数内部差异就是push_back和append
代码
string& operator+=(const char* str)
{
append(str);
return *this;
}

被折叠的 条评论
为什么被折叠?



