这里对于String类的具体补充是让我们更加完善这个接口,在上一篇博客中 点击此处就是一个简单的手撕String,这里是补充,让我们对于String类的理解更加的深刻.
比较简单,就是要对于其后面的元素进行后移的操作,复杂度比较高
void insert(size_t pos, const char& ch){
//0.检查位置是否有效[0,size]
assert(pos <= _size);
//1.容量检查
if (_size == _capacity){
size_t newc = _capacity == 0 ? 15 : 2 * _capacity;
reserve(newc);
}
//2.从后向前移动元素(先将\0放在最后,以免最后的添加)
size_t end = _size + 1;
while (end > pos){
_data[end] = _data[end - 1];
--end;
}
//3.插入
_data[pos] = ch;
//4.更新
_size++;
}
这个函数的内部就是由很多简单的步骤组成的,我们多看看,多理解就行了.
步骤:
1.输入位置检查
2.容量检查
3.依次循环往后
4.插入
5.更新
这里就不做过多的解释了,其实完成一个字符串的插入就是相当于将每一个字符进行插入,多次形成一个循环就可以了.
void insert(size_t pos, const char* ptr){
//输入检查
assert(pos <= _size);
//要插入字符串的长度
int len = strlen(ptr);
if (_size+len > _capacity){
reserve(_size + len); //如果内部的容量不够,则对其进行扩容
}
size_t end = _size + len; //定义最后的位置
while (end>pos+len-1){//在内部进行循环,让字符串挨个加上
_data[end] = _data[end - len]; //按照对应的位置进行赋值
--end;//挨个循环
}
_size += len; //对其位置进行更新
}
void erase(size_t pos, size_t len = npos){
assert(pos < _size); //输入的是否有效检查
if (len == npos||pos+len>=_size){
//当存在输入的pos值大于或者等于其中的值时,直接对所有的进行删除
_size = pos;
_data[_size] = '\0';
}
else{ //如果输入的是有效字符
size_t start = pos + len; //先定义最后的位置
//[pos+len,size]
while (start <= _size){ //在要删除的循环内部
//依次向前移动
_data[start - len] = _data[start]; //将要删除后面的依次进行提前
start++; //循环
}
_size -= len; //在直接对_size减去len 即可
}
}
//===============上面的代码需要下面的进行实现--定义了一个静态变量赋予了缺省值
class String{
public:
...
private:
size_t _size;
size_t _capacity;
char* _data;
static const size_t npos;
};
//静态成员在外部进行定义
const size_t String::npos=-1;
删除基本上都牵扯到内存_size缩小
size_t find(const char& ch, size_t pos = 0){
for (size_t i = pos; i < _size; ++i){
if (_data[i] == ch)
return i;
}
//越界
return npos;
}
步骤:
1.看是否有效
2.利用C语言的strstr进行寻找
3.寻找到则输出对应的位置
4.没有寻找到则输出其所预先设好的缺省值
size_t find(const char* ptr, size_t pos = 0){
assert(pos < _size); //输入检查
char* ptrPos=strstr(_data+pos, ptr); //运用strstr函数找到对应的
if (ptrPos){
return ptrPos - _data; //如果找到,则直接对其进行输出
}
return npos; //如果没找到则输出缺省值,这里的npos是上面的函数私有类定义的静态变量
}
步骤:
1.我们给定了开始的位置和长度
2.创建新的String空间
3.从pos位置开始进行memcpy拷贝过去
4.因为它会把POS后面的全部拷贝,我们只需要len
5.我们将len 长度时的值变为\0,让这个字符串强制结束
6.返回新创建的空间,删除原来的空间
String substr(size_t pos, size_t len=npos){
assert(pos < _size); //输入检查
if (len==npos||pos + len >= _size){
//如果对应的字节是相等的话,责直接调用函数对其进行输出
return String(_data + pos);
}
else{ //如果满足条件
char* newC = new char[len+1]; //先开辟一个对应的空间
memcpy(newC, _data + pos, sizeof(char)*len); //将对应的字节拷贝过去
newC[len] = '\0'; //对新的空间的最后位置赋予\0,因为在字符串里面都是以\0结尾的
return String(newC); //将洗的呢字符串进行输出
delete[] newC; //删除掉以前的字符串空间
}
}
自定义输入操作
istream& operator>>(istream& in, String& str){
char ch; //定义一个字符串
while (ch=cin.get()){ //利用grt函数接口,遇到空格时结束
if (ch == ' ' || ch == '\n') //等于对应的值时,直接退出
break;
//尾插
str += ch; //满足条件则直接尾插
}
return in; //返回对应的值
}
自定义输出操作
ostream& operator<<(ostream& out, const String& str){
for (const auto& ch : str) //直接使用一个范围for函数将其进行输出
out << ch;
return out; //返回其值
}
这篇农科就是对上一篇博客的一个总结和补充,让String类的接口能更加的全面.不清楚的可以返回到上一篇博客看. 点击此处