深圳英文建站公司,建设盗号网站的模块,项目管理过程五个阶段,网站制作工具1. 序言 STL#xff08;标准模板库#xff09;是一个C标准库#xff0c;其中包括一些通用的算法、容器和函数对象。STL的容器是C STL库的重要组成部分#xff0c;它们提供了一种方便的方式来管理同类型的对象。其中#xff0c;STLstring是一种常用的字符串类型。 STLstrin…1. 序言 STL标准模板库是一个C标准库其中包括一些通用的算法、容器和函数对象。STL的容器是C STL库的重要组成部分它们提供了一种方便的方式来管理同类型的对象。其中STLstring是一种常用的字符串类型。 STLstring是一个类它封装了字符串的操作并提供了一组成员函数。STLstring的实现使用了动态的内存分配技术这意味着字符串的大小可以随时改变。STLstring还提供了一些高效的成员函数例如substr、find、replace等这些函数可以对字符串进行快速的操作。 STLstring的实现主要基于字符数组。字符数组是一种固定大小的数组其中每个元素包含一个字符。STLstring使用一个字符数组来存储字符串并通过动态的内存分配技术来管理数组的大小。当向一个空的STLstring对象中添加字符时STLstring会自动调整数组的大小。 STLstring还实现了一些常见的字符串操作例如连接字符串、查找字符串、替换字符串和分割字符串等。这些操作使用了C STL库中的algorithm算法可以高效地处理字符串。同时STLstring也提供了迭代器的支持允许用户使用STL算法来处理字符串。 
2. string类的接口实现 在实现接口之前先要给出我们的初始类包括三个私有成员_size,_capacity,_str接下来我们会对这个初始类一步一步的完善为了文章易读后续接口函数不会展示类的全貌只会展示实现的接口函数内容在文章的末尾会给出完整的string类代码如下 
namespace zybjs
{class string{public:private:size_t _size;size_t _capacity;char* _str;};
} 
2.1 构造函数 
1默认构造和C串构造 在STL库中将C串构造和默认构造分开实现但是我们在模拟实现string类的时候可以将这俩个构造函数合并这样的代码会更简洁也方便我们自己的使用。在此之前我们先按库里面的思路走一趟在我们给初始容量的时候即便字符串长度是0我们也不能给0避免后续无法倍数扩容这里我们给的是4。并且给字符串开空间的时候要比容量多一个最后一个留给\0。VS下实现思路不同VS下给了一个16字节的字符数组_buf如果要存储的字符串小于16字节就存放在字符数组_buf中否则就重新开一个空间 default (1)            string(); from c - string(2)  string(const char* s); string():_size(0),_capacity(4)  //不能给0如果给0后续无法倍数扩容 下同
{_str  new char[_capacity  1]; //开空间的时候要比容量多一个字节留给\0,因为容量的大小不算\0,下同_str[0]  \0;
}
string(const char* str)  //const类型接收右值:_size(strlen(str))
{_capacity  _size  0 ? 4 : _size;_str  new char[_capacity  1];strcpy(_str, str);
} 但是我们在自己实现的时候大可不必这样去写我们之前学习了缺省参数并且全缺省的构造函数也可以作为默认构造所以我们可以对上述代码进行优化给str一个空串作为缺省参数这样当我们调用的时候不给实参就会默认使用空串进行构造来完成库中”string();“的功能。如下 
string(const char* str  )   //const类型接收右值:_size(strlen(str))
{_capacity  _size  0 ? 4 : _size;_str  new char[_capacity  1];strcpy(_str,str);  
} 
2拷贝构造 string类的拷贝构造很简单要注意的点有俩个其一string类涉及到空间管理所以在拷贝的时候要深拷贝否则会导致同一空间多次析构导致报错其二传参不能传值传参要使用传引用传参否则会导致无穷递归 
string(const string s):_size(s._size),_capacity(s._capacity)
{      //深拷贝_str  new char[_capacity  1];  //重新开空间strcpy(_str,s._str);     //字符序列拷贝
} 
2.2 析构函数 string类因为涉及到内存的管理所以析构函数不能使用默认生成的析构需要我们自己去实现析构。在实现析构的时候将_size和_capacity全部置零然后通过delete[]释放_str就可以了。如下 
~string()
{delete[] _str;   //释放_str_str  nullptr;_size  _capacity  0;
} 
2.3 size()、capacity() size()和capacity()很多人在实现的时候都觉得很简单反而会忽略一个点就是const对象访问的时候是否会权限放大。因为这个俩个函数仅涉及到读取没有修改的操作所以我们只需要实现const版本来兼容const对象和非const对象。如下 
size_t size() const  //兼容const对象和非const对象
{return _size;
}
size_t capacity() const//兼容const对象和非const对象
{return _capacity;
} 
2.4 c_str() 返回指向一个数组的指针该数组包含以 null 结尾的字符序列即 C 字符串该序列表示字符串对象的当前值。只需完成const版本来兼容const对象和非const对象。指针的返回值也需要是const char *类型防止通过指针对对象进行修改。 
const char* c_str() const 
{return _str;
} 
2.5 operator[] 因为要实现类似于数组的访问方式所以我们要实现[]的重载形式。[]的特性能够随机访问元素对于非const对象能够修改元素。所以operator[]要实现const版本和非const版本const版本的返回值必须是const引用。 
const char operator[](size_t pos) const
{assert(pos  _size pos  0);return _str[pos];
}
char operator[](size_t pos)
{assert(pos  _size  pos  0);return _str[pos];
} 
2.6 operator 赋值运算符的重载是对字符串对象的深拷贝和拷贝构造的过程相同但是‘’的特性支持连续的赋值所以我们在实现赋值重载的时候需要返回一个string对象来支持赋值重载的连续赋值。因为我们不涉及对传入参数的修改所以我们需要传入一个const string 类型。注意在赋值之前需要释放原来的空间。如下 
string operator(const string s)
{if (s._str ! _str){_size  s._size;_capacity  s._capacity;//深拷贝char* _tmp  new char[_capacity  1]; strcpy(_tmp,s._str);//先释放原来的空间delete[] _str;_str  _tmp;}return *this;
} 
测试 
zybjs::string s1(cacaca);
zybjs::string s2(dadada);
zybjs::string s3(bababa);
s3  s2  s1;
std::cout  s1.c_str()  std::endl;
std::cout  s2.c_str()  std::endl;
std::cout  s3.c_str()  std::endl; 2.7 字符串比较  字符串比较我们通过strcmp来进行比较strcmp(srt1,str2)返回的值为0字符串相同返回的值大于0str1str2返回的值小于0str1str2。基于此便可以实现字符串的比较函数。 
bool operator(const string s) const
{return strcmp(_str, s._str)  0;
}bool operator(const string s) const
{return strcmp(_str, s._str)  0;
}bool operator(const string s) const
{//return *this  s || *this  s;return *this  s || s  *this;
}bool operator(const string s) const
{return !(*this  s);
}bool operator(const string s) const
{return !(*this  s);
}bool operator!(const string s) const
{return !(*this  s);
} 
2.8 迭代器实现 string的迭代器底层是一个指针string类的迭代器是一种用于访问字符串中字符的对象可以通过迭代器的运算符访问字符串中的字符。迭代器为C容器提供了一种通用的访问手段。 
typedef char* iterator;
typedef const char* const_iterator;
iterator begin()
{//指向第一个字符的位置return _str;
}
iterator end()
{//指向最后一个字符的后一个位置return _str  _size;
}const_iterator begin() const
{return _str;
}
const_iterator end() const
{return _str  _size;
} 
2.9 reserve reserve()是为了给对象预留空间如果我们提前得知字符串需要的空间我们就可以提前开好避免频繁扩容带来的性能消耗。当reserve的参数小于string底层空间大小的时候reserve就不会对容量进行处理。 
void reserve(size_t n)
{if (n  _capacity){char* _tmp  new char[n1];strcpy(_tmp, _str);delete[] _str;_str  _tmp;_capacity  n;}
} 
2.10 resize 修改字符有效个数为n多出的空间用字符ch填充。如果n小于有效字符数本质就是删字符操作。如果容量不够会扩容。 
void resize(size_t n, char ch  \0)
{//当n有效字符数的时候本质上就是删字符//但是我们一般不会进行缩容在原来的空间上将n位置的字符设置为\0if (n  _size){_size  n;_str[_size]  \0;}else if (n  _size){if (n  _capacity)  //n_capacity就进行扩容{reserve(n);        }size_t i  _size;while (i  n)       //将非有效字符初始化为ch{_str[i]  ch;i;}_size  n;_str[_size]  \0; //设置终止位}
} 
2.11 push_back、append、operator push_back尾插append是在字符串后面追加一个字符串实现比较简单但要注意检查容量。 
void push_back(char ch)
{if (_size  1  _capacity){reserve(2 * _capacity);}_str[_size]  ch;_size;_str[_size]  \0;
}
void append(const char* str)
{size_t len  strlen(str);if (_size  len  _capacity){reserve(_size  len);}strcpy(_str_size,str);_size  len;
} operator的功能可以由push_back和append的复用来实现 
string operator(char ch)
{push_back(ch);return *this;
}string operator(const char* str)
{append(str);return *this;
} 
2.12 insert insert是string类中支持pos位插入字符或者字符串的函数。其中pos表示插入的位置返回string的引用表示插入后的新字符串。 
string insert(size_t pos, char ch)
{if (_size  1  _capacity){reserve(2 * _capacity);}size_t n  pos;size_t end  _size  1;while (end  pos){_str[end]  _str[end - 1];end--;}_str[pos]  ch;_size  1;_str[_size]  \0;return *this;
}string insert(size_t pos, const char* str)
{size_t len  strlen(str);if (_size  len  _capacity){reserve(_capacity  len);}size_t n  pos;size_t end  _size  1;while (end  pos){_str[end - 1  len]  _str[end - 1];end--;}strncpy(_str  pos, str, len);_size  len;_str[_size]  \0;return *this;
} 
2.13 erase C中的string类提供了一个名为erase()的成员函数用于删除字符串中的一部分字符并修改该字符串。该函数可以接受1个或2个参数具体取决于要删除的字符数。如果没有显式的指定删除字符数会使用默认的npos也就是无符号整型-1来作为缺省参数65535就会默认删除pos位后面所有的字符。然后返回删除字符后生成的新字符。 首先我们要定义一个和库里相同的npos string erase(size_t pos,size_t len  npos)
{assert(pos  _size);if (len  _size - pos - 1){_size  pos;_str[_size]  \0;}else{strcpy(_str  pos, _str  pos  len);_size - len;}return *this;
} 
2.14 流插入和流提取 std::ostream operator(std::ostream out, const string s){for (auto ch : s){out  ch;}return out;}std::istream operator(std::istream in, string s){s.clear();        //输入之前要清空字符串char ch  in.get();//获取字符包括\nchar buff[32];  //设置缓冲区来防止频繁扩容size_t i  0;while (ch !    ch ! \n){buff[i]  ch;if (i  30){buff[31]  \0;s  buff;i  0;}i;ch  in.get();}buff[i]  \0;s  buff;} 
3. 完整代码均调试通过 
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1#includeiostream
#includecassert
namespace zybjs
{class string{public:typedef char* iterator;typedef const char* const_iterator;iterator begin(){//指向第一个字符的位置return _str;}iterator end(){//指向最后一个字符的后一个位置return _str  _size;}const_iterator begin() const{return _str;}const_iterator end() const{return _str  _size;}//string()//	:_size(0)//	,_capacity(4)  //不能给0如果给0后续无法倍数扩容 下同//{//	_str  new char[_capacity  1]; //开空间的时候要比容量多一个字节留给\0,因为容量的大小不算\0,下同//	_str[0]  \0;//}//string(const char* str)//	:_size(strlen(str))//{//	_capacity  _size  0 ? 4 : _size;//	_str  new char[_capacity  1];//	strcpy(_str, str);//}string(const char* str  )   //const类型接收右值:_size(strlen(str)){_capacity  _size  0 ? 4 : _size;_str  new char[_capacity  1];strcpy(_str,str);  }string(const string s):_size(s._size),_capacity(s._capacity){      //深拷贝_str  new char[_capacity  1];  //重新开空间strcpy(_str,s._str);     //字符序列拷贝}~string(){delete[] _str;   //释放_str_str  nullptr;_size  _capacity  0;}size_t size() const  //兼容const对象和非const对象{return _size;}size_t capacity() const//兼容const对象和非const对象{return _capacity;}const char* c_str() const {return _str;}const char operator[](size_t pos) const{assert(pos  _size pos  0);return _str[pos];}char operator[](size_t pos){assert(pos  _size  pos  0);return _str[pos];}string operator(const string s){if (s._str ! _str){_size  s._size;_capacity  s._capacity;//深拷贝char* _tmp  new char[_capacity  1]; strcpy(_tmp,s._str);//先释放原来的空间delete[] _str;_str  _tmp;}return *this;}//字符串比较bool operator(const string s) const{return strcmp(_str, s._str)  0;}bool operator(const string s) const{return strcmp(_str, s._str)  0;}bool operator(const string s) const{//return *this  s || *this  s;return *this  s || s  *this;}bool operator(const string s) const{return !(*this  s);}bool operator(const string s) const{return !(*this  s);}bool operator!(const string s) const{return !(*this  s);}void reserve(size_t n){if (n  _capacity){char* _tmp  new char[n1];strcpy(_tmp, _str);delete[] _str;_str  _tmp;_capacity  n;}}void resize(size_t n, char ch  \0){//当n有效字符数的时候本质上就是删字符//但是我们一般不会进行缩容在原来的空间上将n位置的字符设置为\0if (n  _size){_size  n;_str[_size]  \0;}else if (n  _size){if (n  _capacity)  //n_capacity就进行扩容{reserve(n);        }size_t i  _size;while (i  n)       //将非有效字符初始化为ch{_str[i]  ch;i;}_size  n;_str[_size]  \0; //设置终止位}}void push_back(char ch){if (_size  1  _capacity){reserve(2 * _capacity);}_str[_size]  ch;_size;_str[_size]  \0;}void append(const char* str){size_t len  strlen(str);if (_size  len  _capacity){reserve(_size  len);}strcpy(_str_size,str);_size  len;}string operator(char ch){push_back(ch);return *this;}string operator(const char* str){append(str);return *this;}string insert(size_t pos, char ch){if (_size  1  _capacity){reserve(2 * _capacity);}size_t n  pos;size_t end  _size  1;while (end  pos){_str[end]  _str[end - 1];end--;}_str[pos]  ch;_size  1;_str[_size]  \0;return *this;}string insert(size_t pos, const char* str){size_t len  strlen(str);if (_size  len  _capacity){reserve(_capacity  len);}size_t n  pos;size_t end  _size  1;while (end  pos){_str[end - 1  len]  _str[end - 1];end--;}strncpy(_str  pos, str, len);_size  len;_str[_size]  \0;return *this;}string erase(size_t pos,size_t len  npos){assert(pos  _size);if (len  _size - pos - 1){_size  pos;_str[_size]  \0;}else{strcpy(_str  pos, _str  pos  len);_size - len;}return *this;}void clear(){_size  0;_str[_size]  \0;}private:size_t _size;size_t _capacity;char* _str;static const size_t npos;};const size_t string::npos  -1;std::ostream operator(std::ostream out, const string s){for (auto ch : s){out  ch;}return out;}std::istream operator(std::istream in, string s){s.clear();        //输入之前要清空字符串char ch  in.get();//获取字符包括\nchar buff[32];  //设置缓冲区来防止频繁扩容size_t i  0;while (ch !    ch ! \n){buff[i]  ch;if (i  30){buff[31]  \0;s  buff;i  0;}i;ch  in.get();}buff[i]  \0;s  buff;}
}  文章转载自: http://www.morning.mhpkz.cn.gov.cn.mhpkz.cn http://www.morning.cfccp.cn.gov.cn.cfccp.cn http://www.morning.rqfzp.cn.gov.cn.rqfzp.cn http://www.morning.nkjkh.cn.gov.cn.nkjkh.cn http://www.morning.qbfkz.cn.gov.cn.qbfkz.cn http://www.morning.4q9h.cn.gov.cn.4q9h.cn http://www.morning.wlddq.cn.gov.cn.wlddq.cn http://www.morning.jhgxh.cn.gov.cn.jhgxh.cn http://www.morning.jzsgn.cn.gov.cn.jzsgn.cn http://www.morning.qfwzm.cn.gov.cn.qfwzm.cn http://www.morning.pmghz.cn.gov.cn.pmghz.cn http://www.morning.cbqqz.cn.gov.cn.cbqqz.cn http://www.morning.cnxpm.cn.gov.cn.cnxpm.cn http://www.morning.gftnx.cn.gov.cn.gftnx.cn http://www.morning.ryywf.cn.gov.cn.ryywf.cn http://www.morning.hrypl.cn.gov.cn.hrypl.cn http://www.morning.pjrql.cn.gov.cn.pjrql.cn http://www.morning.wfjyn.cn.gov.cn.wfjyn.cn http://www.morning.cczzyy.com.gov.cn.cczzyy.com http://www.morning.ntyanze.com.gov.cn.ntyanze.com http://www.morning.shprz.cn.gov.cn.shprz.cn http://www.morning.ndngj.cn.gov.cn.ndngj.cn http://www.morning.fkyqm.cn.gov.cn.fkyqm.cn http://www.morning.lbbgf.cn.gov.cn.lbbgf.cn http://www.morning.tkgxg.cn.gov.cn.tkgxg.cn http://www.morning.hmbtb.cn.gov.cn.hmbtb.cn http://www.morning.ydhck.cn.gov.cn.ydhck.cn http://www.morning.zlbjx.cn.gov.cn.zlbjx.cn http://www.morning.pkmcr.cn.gov.cn.pkmcr.cn http://www.morning.dxqwm.cn.gov.cn.dxqwm.cn http://www.morning.mrfbp.cn.gov.cn.mrfbp.cn http://www.morning.rqkzh.cn.gov.cn.rqkzh.cn http://www.morning.qpfmh.cn.gov.cn.qpfmh.cn http://www.morning.xbnkm.cn.gov.cn.xbnkm.cn http://www.morning.gtqws.cn.gov.cn.gtqws.cn http://www.morning.mhlsx.cn.gov.cn.mhlsx.cn http://www.morning.mjbjq.cn.gov.cn.mjbjq.cn http://www.morning.cwgt.cn.gov.cn.cwgt.cn http://www.morning.ntffl.cn.gov.cn.ntffl.cn http://www.morning.rytps.cn.gov.cn.rytps.cn http://www.morning.cnbdn.cn.gov.cn.cnbdn.cn http://www.morning.tbwsl.cn.gov.cn.tbwsl.cn http://www.morning.fjtnh.cn.gov.cn.fjtnh.cn http://www.morning.lqlc.cn.gov.cn.lqlc.cn http://www.morning.xpmhs.cn.gov.cn.xpmhs.cn http://www.morning.hwbf.cn.gov.cn.hwbf.cn http://www.morning.ggjlm.cn.gov.cn.ggjlm.cn http://www.morning.xflwq.cn.gov.cn.xflwq.cn http://www.morning.msbmp.cn.gov.cn.msbmp.cn http://www.morning.mtsck.cn.gov.cn.mtsck.cn http://www.morning.rhkmn.cn.gov.cn.rhkmn.cn http://www.morning.ndmbd.cn.gov.cn.ndmbd.cn http://www.morning.znsyn.cn.gov.cn.znsyn.cn http://www.morning.rbmm.cn.gov.cn.rbmm.cn http://www.morning.qtqjx.cn.gov.cn.qtqjx.cn http://www.morning.wnjwb.cn.gov.cn.wnjwb.cn http://www.morning.pphgl.cn.gov.cn.pphgl.cn http://www.morning.pwxkn.cn.gov.cn.pwxkn.cn http://www.morning.mnwsy.cn.gov.cn.mnwsy.cn http://www.morning.rqfzp.cn.gov.cn.rqfzp.cn http://www.morning.bypfj.cn.gov.cn.bypfj.cn http://www.morning.jggr.cn.gov.cn.jggr.cn http://www.morning.rzdzb.cn.gov.cn.rzdzb.cn http://www.morning.pwksz.cn.gov.cn.pwksz.cn http://www.morning.kvzvoew.cn.gov.cn.kvzvoew.cn http://www.morning.rkqzx.cn.gov.cn.rkqzx.cn http://www.morning.msmtf.cn.gov.cn.msmtf.cn http://www.morning.wqpsf.cn.gov.cn.wqpsf.cn http://www.morning.pypqf.cn.gov.cn.pypqf.cn http://www.morning.fmkbk.cn.gov.cn.fmkbk.cn http://www.morning.llthz.cn.gov.cn.llthz.cn http://www.morning.pnntx.cn.gov.cn.pnntx.cn http://www.morning.gjlxn.cn.gov.cn.gjlxn.cn http://www.morning.tstwx.cn.gov.cn.tstwx.cn http://www.morning.wcgcm.cn.gov.cn.wcgcm.cn http://www.morning.wbxr.cn.gov.cn.wbxr.cn http://www.morning.rttkl.cn.gov.cn.rttkl.cn http://www.morning.ffdyy.cn.gov.cn.ffdyy.cn http://www.morning.btblm.cn.gov.cn.btblm.cn http://www.morning.yqwrj.cn.gov.cn.yqwrj.cn