当前位置: 首页 > news >正文

免费外贸网站大全网站定制电话

免费外贸网站大全,网站定制电话,全国icp网站备案审核时间,万户网络技术了解过string常用接口后#xff0c;接下来的任务就是模拟实现string类。 目录 VS下的string结构 默认成员函数和简单接口 string结构 c_str()、size()、capacity()、clear()、swap() 构造函数 拷贝构造函数 赋值重载 析构函数 访问及遍历 容量操作 reserve resize … 了解过string常用接口后接下来的任务就是模拟实现string类。 目录 VS下的string结构 默认成员函数和简单接口 string结构 c_str()、size()、capacity()、clear()、swap() 构造函数 拷贝构造函数 赋值重载 析构函数 访问及遍历 容量操作 reserve resize 修改操作 push_back append operator insert earse 输入/输出运算符重载 VS下的string结构 ■首先测试下string结构的大小注下述测试是在32位平台上进行的指针占4个字节 int main() {string s;cout sizeof(s) endl;return 0; } 通过调试窗口理解string的结构 int main() {string s(Hello);return 0; } 通过测试知道string总共占28个字节调试发现结构中有一个联合体用来定义string中字符串的存储空间 1.当字符串长度小于16时使用内部固定的字符数组来存放 。2.当字符串长度大于等于16时从堆上开辟空间。 union _Bxty { char _Buf[16];char* _Ptr;char _Alias[16]; } _Bx; 除了联合体还有一个size_t字段保存字符串长度还有一个size_t字段记录容量此外还有一个做其它事情的指针。总大小16444 28 默认成员函数和简单接口 下述接口的模拟实现仅仅是一种写法可能不是最优的也可能存在一些BUG仅供参考 string结构 c_str()、size()、capacity()、clear()、swap() 为了测试方便先将上述几个常用且简单的接口进行实现 //返回指向_str的指针const char* c_str(){return _str;}//返回_sizesize_t size() const{return _size;}//返回_capacitysize_t capacity() const{return _capacity;}//清空有效字符void clear(){_size 0;_str[0] \0;} 复习时间const修饰返回值的作用是避免返回值被修改const写在成员函数后面修饰的是隐藏的this指针不能对类的成员进行修改 swapstring类中提供一个swap接口用来交换两个string对象。 void swap(string s){std::swap(_str, s._str);std::swap(_size,s._size);std::swap(_capacity, s._capacity);} 构造函数 分析对于string s1“Hello”/ string s2 都能处理; 逻辑思路通过strlen计算str的字符个数确定size和capacity的值空间一般多开一个因为要算上\0。在将str 拷贝到开辟好的空间中。 //构造 string(const char* str ) {_size strlen(str);_capacity _size;_str new char[_capacity1];strcpy(_str,str);cout 调用构造函数 endl; } 测试代码 //构造函数测试void TestString1(){string s1(zhang);string s2;cout s1.c_str() endl;}  拷贝构造函数 分析string s1(s2); 按照拷贝对象的容量申请空间对拷贝对象进行拷贝。 传统写法 //拷贝构造string(const string s){_str new char[s._capacity];_size s._size;_capacity s._capacity;strcpy(_str,s._str);cout 调用拷贝构造 endl;} 测试代码 //拷贝构造测试void TestString2(){string s2(Hi zxy!);cout s2.c_str() endl;string s3(s2);cout s3.c_str() endl;} 现代写法这里注意在初始化列表对s进行初始化否则当tmp对象析构的时候会出现析构野指针的问题。 //现代写法string(const string s):_str(nullptr),_size(0),_capacity(0){string tmp(s._str);//this-swap(tmp);swap(tmp);cout 拷贝构造 endl;} 赋值重载 传统写法 注意不要见到就是引用在下述判断代码中s取出的s的地址和this指针进行比较如果地址不相同则进行赋值工作 赋值的过程需要将右操作数赋值给做左操作数这时从新根据右操作数的容量申请一块空间将左操作数空间释放。_str指向刚刚开好的空间将右操作数中的字符串拷贝到_str中。 //赋值重载string operator(const string s){//两操作数地址不相等if (this ! s){//申请一块能容纳右操作数的空间char* tmp new char[s._capacity];delete[] _str;_str tmp;strcpy(_str,s._str);_size s._size;_capacity s._capacity;}return *this;}  测试代码 //赋值重载测试void TestString3(){string str1(Hello World!);string str2(Hi!);cout 赋值前str1: str1.c_str() str2: str2.c_str() endl;str1 str2;cout 赋值后str1: str1.c_str() str2.c_str() endl;} 测试结果 现代写法 第二种相比较第一种写法省去了一次拷贝构造传值调用形参是实参的临时拷贝所以第二种写法更加的简洁第一种写法更容易理解。 //赋值重载现代写法1string operator(string s){if (this ! s){//string tmp(s._str);string tmp(s);swap(tmp);}return *this;}//赋值重载现代写法2string operator(string s){swap(s);return *this;} 析构函数 //析构~string(){_capacity _size 0;delete[] _str;_str nullptr;cout 调用析构函数 endl;} 测试代码 //析构函数测试void TestString4(){string str(zxy);cout str.c_str() endl;} 访问及遍历 operator[ ] char operator[](size_t pos){assert(pos _size);return _str[pos];}char operator[](size_t pos) const{assert(pos _size);return _str[pos];} begin/end typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str _size;} 迭代器访问string对象、vector等对象元素的一种通用机制。迭代器类似于指针类型不一定是指针使用迭代器可以访问某个元素。范围for的支持就和迭代器有关 void TestString2(){string s2(My name is zxy!);string::iterator it1 s2.begin();while (it1 ! s2.end()){cout *it1;it1;}cout endl;string::iterator it2 s2.begin();while (it2 ! s2.end()){(*it2);cout *it2;it2;}} 证明范围for是依赖于迭代器实现的 1.屏蔽掉string中的begin或者end.  2.放开屏蔽更改begin的命名为Begin。一样的报错  3.提供小写的begin和end  综上所述便捷神秘的范围for运用迭代器这种通用的机制来实现元素的遍历和访问。 容量操作 reserve 扩容申请一块n大小的空间将_str指向的字符串拷贝到tmp指向的空间中清理_str指向的字符串并将_str指向新空间更新容量的大小。 //扩容void reserve(size_t n){//新开一块空间char* tmp new char[n 1];strcpy(tmp, _str);delete[] _str;_str tmp;_capacity n;} void TestString6(){string ss(Hello World!);cout size: ss.size() endl;cout capacity: ss.capacity() endl;cout str: ss.c_str() endl;cout --------------reserve-------------- endl;ss.reserve(100);cout size: ss.size() endl;cout capacity: ss.capacity() endl;cout str: ss.c_str() endl;}   resize 改变字符串中有效字符的个数当n_size时其余位置用ch占位。当n_size时只有前n个字符是有效字符。 //resize更改有效元素个数的大小void resize(size_t n,char ch !){if (n _size){reserve(n);for (size_t i _size;i n; i){_str[i] ch;}_size n;_str[n] \0;}else{_size n;_str[n] \0;}}  上述代码中当n小于_size时在n位置填入\0,有效字符的个数正好是n,因为字符数组的下标是从0开始的。 void TestString7(){string ss(Hello);cout str: ss.c_str() endl;cout size: ss.size() endl;//字符串有效字符个数增多ss.resize(10,x);cout str: ss.c_str() endl; cout size: ss.size() endl;//字符串有效字符个数变少ss.resize(3);cout str: ss.c_str() endl;cout size: ss.size() endl;} 修改操作 push_back 尾插操作也就是在字符串末尾追加一个字符   //追加字符void push_back(char ch){if (_size _capacity){size_t newcapacity _capacity 0 ? 4 : 2 * _capacity;//扩容reserve(newcapacity);}_str[_size] ch;_str[_size] \0;} append 在_str末尾追加一个字符串   //追加字符串void append(const char* str){size_t len strlen(str);if (_size len _capacity){reserve(_sizelen1);}strcpy(_str_size,str);_size len;} operator 重载运算符使既可以追加字符右可以追加字符串实现思路和上述基本一样这里直接调用上面的接口。 //运算符重载string operator(char ch){push_back(ch);return *this;}string operator(const char* str){append(str);return *this;} 测试push_back/append/性能 void TestString3(){string ss(Hi);cout str: ss.c_str() endl;ss.append(zxy); cout append(zxy): ss.c_str() endl;ss.push_back(!);cout push_back(!): ss.c_str() endl;ss !;cout 字符(!): ss.c_str() endl;ss bd;cout 字符串(bd): ss.c_str() endl;} insert insert这里重载了两个接口分别是用来插入字符和插入字符串 ●在pos位置插入字符   //插入字符string insert(size_t pos,char ch){//检查pos是否越界assert(pos _size);if (_capacity _size){//扩容size_t newcapacity _capacity 0 ? 4 : 2 * _capacity;reserve(newcapacity);}//挪动数据size_t end _size 1;while (end pos){_str[end] _str[end-1];end--;}_str[pos] ch;_size;return *this;} void TestString9(){string ss(Helloworld!);ss.insert(6, );cout ss.c_str() endl;}  ●在pos位置插入字符串   //插入字符串 string insert(size_t pos, const char* str){assert(pos _size);size_t len strlen(str);if (_size len _size){//扩容size_t newcapacity _capacity 0 ? 4 : _sizelen;reserve(newcapacity);}//挪动数据size_t end _size len;while (end poslen-1){_str[end] _str[end - len];end--;}strncpy(_strpos,str,len);_size len;return *this;} void TestString10(){string ss(Hi Lisi!);ss.insert(3, zxy I am );cout ss.c_str() endl;} earse 删除pos后的len个字符如果len npos将pos后的数据全部删除 //删除字符string earse(size_t pos,size_t len npos){assert(pos _size);//如果pos后面的数据不够删或者npospos后数据全部删除if (len npos || len pos _size-pos){_str[pos] \0;_size pos;}else{strcpy(_str pos, _str pos len);_size - len;}return *this;} 输入/输出运算符重载 小提问输入和输出的重载为了和我们的使用习惯保持一致一般会定义在全局那么一定要在对应自定义类型中声明友元吗 答不一定声明友元的原因是要访问类中的私有成员如果在重载的过程中不涉及私有成员的访问就不用写友元声明 //流插入ostream operator(ostream out,string s){for (size_t i 0; i s.size(); i){out s[i];}return out;}流提取的实现使用了一个字符数组in.get()用于读取字符当数组满时追加到_str中,没满时将数据存放到buff数组中最后输入结束时如果buff中还有数据的话将剩余数据追加到_str中不过要注意在buff的数据末尾添加一个\0。 //流提取istream operator(istream in, string s){s.clear();char ch in.get();size_t i 0;char buff[128] {\0};while (ch ! ch ! \n){if (i 127){s buff;i 0;}buff[i] ch;ch in.get();}if (i 0){buff[i] \0;s buff;}return in;}
http://www.w-s-a.com/news/745371/

相关文章:

  • 湖南网站建设公司排名傲派电子商务网站建设总结
  • 网站建设求职要求互联网挣钱项目平台
  • 网站权重怎么做做黑彩网站能赚钱吗
  • 三台建设局网站网页设计购物网站建设
  • thinkphp大型网站开发市场调研公司招聘
  • 天宁区建设局网站七冶建设集团网站 江苏
  • 越南网站 后缀湘潭新思维网站
  • 环球旅行社网站建设规划书网钛cms做的网站
  • 软件资源网站wordpress不能识别语言
  • 东坑仿做网站西安私人网站
  • 公司想做个网站怎么办如何搭建视频网站
  • .net网站架设凯里网站建设哪家好
  • seo网站建站建站国外百元服务器
  • 家具网站开发设计论文企业网站里面的qq咨询怎么做
  • 网站视频提取软件app淘宝店购买网站
  • 站长之家域名解析做百度推广网站咱们做
  • 行业 网站 方案莱州网站建设公司电话
  • 丹东谁做微网站威海网络科技有限公司
  • 寻找网站建设_网站外包自助打印微信小程序免费制作平台
  • 台式机网站建设vk社交网站做婚介
  • 创建网站得花多少钱网站建设的技术路线
  • 图书馆网站建设汇报免费编程软件哪个好用
  • 手机搭建网站工具网站搜索引擎优化的基本内容
  • 网站快速排名二手交易网站开发技术路线
  • 官方网站开发公司施工企业会计王玉红课后答案
  • 网站建设能用手机制作吗网站建设所需物资
  • 阜阳做网站的公司阳江招聘网最新消息
  • 织梦可以做哪些类型型网站wordpress 融资
  • 建设银行手机银行官方网站下载安装腾讯企点账户中心
  • 品牌设计网站有哪些商务网站建设平台