主要写增删查改和几种常见的构造方式:
文章目录
定义先确定string类中成员变量:
private:char* _str;
size_t _size;//实际空间
size_t _capacity;//有效空间,真实容量没算\0;staticconst size_t npos;//位置};
1.1第一种构造方式 string(const char *s) :
//s1("HAOHAO")string(constchar* str):_size(strlen(str))//开空间初始化,_capacity(_size){
_str=newchar[_capacity +1];strcpy(_str, str);}
1.2.第二种构造方式拷贝构造://3.string(const string & str,string size_type n = npos):
这里需要用深拷贝,浅拷贝会报错,浅拷贝并没有直接开辟空间而是指针指向了被拷贝的空间,看起来没什么问题,但是程序结束时会报错,因为结束时会调用析构函数,按照下图所示s2会先调用析构函数,之后s1也会调用析构函数,此时s1的空间已经被s2释放了所以程序报错;
string s1("HAOHAO");
string s2=(s1);
深拷贝又有好几种写法,分为古代和现代两种写法
//深拷贝古代写法:啥都亲力亲为string(const string& s):_size(s._size),_capacity(s._capacity){
_str =newchar[_capacity +1];strcpy(_str, s._str);}// 深拷贝现代写法:找别人干活string(const string& s):_str(nullptr){
string tmp(s._str);//这里s._str的类型是char*所以调用的是我们自己写的第一种构造方式//这个swap是我们自己写的函数,后面重载操作符 =的时候会说为啥要自己写this->swap(tmp);}
1.3.重载操作符 =:
这也分了古代和现代两种写法,现代中用了我们自定义的swap函数,如果用swap(_str,s.str)这么写只是把指针_str和s.str这两个指针互换了,this的容量并没有交换无法全部拷贝到
//s1=s3;古代写法
string&operator=(const string& s){//释放掉原空间,避免浪费,可能s1很大s3很小if(this!=&s){//s3=s3这种情况char* tmp =newchar(s._size);//先开辟空间再释放strcpy(tmp, s._str);delete[] _str;
_str = tmp;//传的地址
_size = s._size;
_capacity = s._capacity;}return*this;}//现代写法
string &operator=(const string &s){if(this!=&s){
string tmp(s);//普通的swap(_str,tmp_str)只是交换了_str指针的方向但是string类里size和capacity还跟以前一样,会出问题this->swap(tmp);
cout <<"交换后"<< endl;
cout <<this->_str << endl;
\
}return*this;}voidswap(string& s){
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);}
1.4.重载运算符[ ]、s._str()、size()函数:
char&operator[](size_t pos){assert(pos < _size);//防止越界直接断死return _str[pos];}constchar*c_str(){return _str;}
size_t size()const{return _size;}
1.5.查找单个字符和字符串:
//查找单个字符
size_t find(constchar ch){for(size_t i =0; i < _size; i++){if(ch == _str[i]){return i;}}return npos;//没有找到返回npos}//查找字符串
size_t find(constchar*s,size_t pos=0){for(size_t i =0; i < _size; i++){//:strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。constchar* ptr =strstr(_str + pos, s);if(ptr ==nullptr){return npos;}else{return ptr - _str;}}return npos;//没有找到返回npos}
1.6.reserve()和resize()函数:
扩容reserve和resize: reserve的逻辑是先把内容拷贝下来,存在tmp中再把原来的空间给删掉;resize的容量可能会被变小,变小的话直接在n的位置加上’\0’,然后改变_size,如果变大又分了两种情况(1)n比_size大比_capacity小,(2)n直接比capacity大。
第一种情况直接在比 下标size 大的填上‘\0’占位;
第二种情况先扩容再占位;
voidreserve(size_t n){//改变capacity n比原来的那么就变成n 比原来小就不变if(n > _capacity){char* tmp =newchar[n +1];//\0strcpy(tmp, _str);delete[] _str;
_str = tmp;
_capacity = n;}}voidresize(size_t n,char ch='\0'){if(n <= _size){//resize跟reserve不一样它如果resize一个比它之前size小的数会缩容量的,最后一个位置填‘\0’
_str[n]='\0';
_size = n;}else{if(n > _capacity){reserve(n);}memset(_str + _size, ch, n - _size);//扩容后把空间填充从size开始
_str[n]='\0';
_size = n;}}
1.7.push_back()函数:
voidpush_back(char ch){//判断是否为空和是否已经满了,如果本身没有空间扩容四个字节,如果本身有空间但是满了直接扩容两倍if(_size == _capacity){reserve(_capacity==0?4: _capacity *2);}
_str[_size]= ch;++_size;
_str[_size]='\0';}
1.8.inset()函数:
指定位置插入字符或字符串:先判断容量是否够不够就扩,然后把从最后一个字符往后移,直到pos位置为空,end一定要在最后一个字符的后面一个位置也就是‘\0’的位置,如果end=_size,判断条件while (end>=(pos) ,如果此时在第0个位置插入end最后会变成-1程序歇火;
插入字符串也是一样的也是从最后面开始移动但是end要在size+len(插入字符串长度)的位置,直到找到pos
//插入字符
string&insert(size_t pos,char ch){assert(pos <= _size);//判断容量是否满了if(_size == _capacity){reserve(_capacity ==0?4: _capacity *2);}//这么写 在第0个位置插入时会报错,end变为-1直接歇火size_t类型不能为负数,转为int的时候while (end>=pos)这个判断还会出问题要// while (end>=(int)pos)//size_t end = _size;往后移直到第pos个位置为空//while (end>=pos) {// _str[end + 1] = _str[end];// --end;//}//直接 HAO\0,把end放在斜杠0后面
size_t end = _size+1;while(end > pos){
_str[end]= _str[end -1];
end--;}
_str[pos]= ch;++ _size;return*this;}//插入字符串
string&insert(size_t pos,constchar*ch){assert(pos <= _size);//先看容量够不够
size_t len =strlen(ch);if(_size + len > _capacity){reserve(_size+len);}
size_t end = _size + len;while(end >=pos+len){
_str[end]= _str[end - len];
end--;}strncpy(_str, ch, len);
_size+=len;return*this;}
1.9 append()函数:
在末尾插入字符串扩容时要结合实际情况扩容,还有一种简便写法直接调用上面写的insert函数
voidappend(constchar* ch){//扩容不能单纯的扩两倍可能不够万一要结合实际
size_t len =strlen(ch);if(_size + len > _capacity){this->reserve(_size+len);}strcpy(_str + _size, ch);//从上一个单词的末尾插}voidappend(constchar* ch){insert(_size, ch);}
版权归原作者 滘 所有, 如有侵权,请联系我们删除。