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

网站建设方案策划营销推广平台

网站建设方案策划,营销推广平台,网络域名大全,wordpress 为什么不加www的不能访问嘿嘿,家人们,今天咱们来模拟实现string,好啦,废话不多讲,开干! 1:string.h 1.1:构造函数与拷贝构造函数 1.1.1:写法一 1.1.2:写法二(给缺省值) 1.2:赋值运算符重载与operatror[]获取元素 1.3:容量与迭代器 1.4:reserve与resize 1.5:清空与判断是否为空 1.6:push_back与…

嘿嘿,家人们,今天咱们来模拟实现string,好啦,废话不多讲,开干!


1:string.h

1.1:构造函数与拷贝构造函数

1.1.1:写法一

1.1.2:写法二(给缺省值)

1.2:赋值运算符重载与operatror[]获取元素

1.3:容量与迭代器

1.4:reserve与resize

1.5:清空与判断是否为空

1.6:push_back与append

1.7:insert

1.7.1:插入字符

1.7.2:插入字符串

1.8:erase

1.9:operator+=

1.9.1:添加字符

1.9.2:添加字符串

1.91:find

1.91.1:查找字符

1.91.2:查找字符串 

1.92:substr与swap

1.93:非成员函数的重载

1.93.1:流插入与流提取的重载

1.93.2:其他非成员函数的重载

2:Test.cpp

2.1:构造函数与拷贝构造

2.1.1:测试写法一

2.1.2:测试写法二

2.2:测试赋值运算符重载与[]获取元素

2.3:测试迭代器与容量

2.4:测试reserve与resize 

2.4.1:测试resize

2.4.2:测试reserve

2.5:测试push_back与append

2.6:测试insert

2.6.1:测试插入字符

2.6.2:测试插入字符串

2.7:测试erase

2.8:测试operator+=

2.9:测试find

2.91:测试substr与swap

2.92:测试流插入与流提取

2.92.1:第一版流提取

2.92.2:第二版流提取

2.93:测试其他非成员函数

3:知识补充

3.1:深拷贝与浅拷贝

3.1.1:浅拷贝

​3.1.2:深拷贝

4:总代码

4.1:string.h

4.2:Test.cpp


1:string.h

1.1:构造函数与拷贝构造函数

1.1.1:写法一

#include <iostream>
#include <string.h>
#include <assert.h>
using namespace std;//避免与库中的string冲突,因此使用命名空间
namespace MyString
{class string{public:string():_str(new char[1]), _size(0),_capacity(0){//空字符串只有\0,_str[0] = '\0';}//构造非空字符串string(const char * str)//开辟空间,多开辟个空间存放\0:_str(new char[strlen(str) + 1]){//开辟空间_capacity = _size = strlen(str);//拷贝数据strcpy(_str, str);}//拷贝构造函数//s2(s1),使用s1拷贝构造s2string(string & s){//开辟空间char* temp = new char[s._capacity + 1];_str = temp;_capacity = s._capacity;_size = s._size;//拷贝数据strcpy(_str, s._str);}//析构函数~string(){delete[] _str;_size = _capacity = 0;}private://定义成员变量并且给缺省值char* _str;int   _size;int   _capacity;};}

1.1.2:写法二(给缺省值)

#include <iostream>
#include <string.h>
#include <assert.h>
using namespace std;//避免与库中的string冲突,因此使用命名空间
namespace MyString
{class string{public://string()//	:_str(new char[1])//	, _size(0)//	,_capacity(0)//{//	//空字符串只有\0,//	_str[0] = '\0';//}构造非空字符串//string(const char * str)//	//开辟空间,多开辟个空间存放\0//	:_str(new char[strlen(str) + 1])//{//	//开辟空间//	_capacity = _size = strlen(str);//	//拷贝数据//	strcpy(_str, str);//}//给缺省值,构造空字符串时使用缺省值string(const char* str = "")//开辟空间,多开辟个空间存放\0:_str(new char[strlen(str) + 1]){//开辟空间_capacity = _size = strlen(str);//拷贝数据strcpy(_str, str);}/*拷贝构造函数s2(s1),使用s1拷贝构造s2*/string(string & s){//开辟空间char* temp = new char[s._capacity + 1];_str = temp;_capacity = s._capacity;_size = s._size;//拷贝数据strcpy(_str, s._str);}//析构函数~string(){delete[] _str;_size = _capacity = 0;}private://定义成员变量并且给缺省值char* _str = nullptr;int   _size = 0;int   _capacity = 0;};}

1.2:赋值运算符重载与operatror[]获取元素

		//s1 = s2 this---->s1   s2----->s//赋值运算符重载string & operator =(string & s){//开辟新空间char * temp = new char[s._capacity + 1];//释放旧空间delete _str;//拷贝数据strcpy(temp, s._str);//指向新空间_str = temp;_size = s._size;_capacity = s._capacity;return *this;}//T &,返回引用同样可以提高效率,有返回值的目的是为了支持连续赋值.char & operator[](size_t position){assert(position < _size);return _str[position];}//const成员函数,给const对象调用,与上面构成函数重载const char& operator[](size_t position) const{assert(position < _size);return _str[position];}

1.3:容量与迭代器

迭代器呢其实是一个类指针,因此我们在模拟实现的时候,直接通过指针来进行模拟即可~

#include <iostream>
#include <string.h>
#include <assert.h>
using namespace std;//避免与库中的string冲突,因此使用命名空间
namespace MyString
{class string{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;}//capacitysize_t size(){return _size;}size_t capacity(){return _capacity;}private://定义成员变量并且给缺省值char* _str = nullptr;int   _size = 0;int   _capacity = 0;};}

1.4:reserve与resize

我们来回顾下reserve与resize的相关知识 

1:reserve

  • 比size小不变化
  • 比size大但小于capacity也不发生变化
  • 比capacity大才会进行扩容

因此我们只要判断是否比capacity大

2:resize

  • 比size小则进行删除.

  • 比size大但小于capacity会改变size,并用\0插入.
  • 比capacity大,会先改变size的大小同时进行扩容.

		//仅需判断是否比capacity大void reserve(size_t n){if(n > _capacity){//开辟新空间char* temp = new char[n + 1];//拷贝数据strcpy(temp, _str);//释放旧空间delete[] _str;//指向新空间_str = temp;_capacity = n;}}void resize(size_t n,char ch = '\0'){//比size小则会进行删除if (n <= _size){_str[n] = ch;}//比size大比capacity小会改变size,并且用\0插入else if( n > _size && n <= _capacity){_size = n;}//比capacity大, 会先改变size的大小同时进行扩容.else{//扩容reserve(n);for(size_t i = _size; i < _capacity ; i++){_str[i] = ch;}_size = n;}}

1.5:清空与判断是否为空

		//只清除有效字符,不改变底层空间void clear(){_str[0] = '\0';_size = 0;}bool empty()const{return _size == 0;}

这里博主就不带着uu们测试啦,感兴趣的uu可以自己下去测试下~ 

1.6:push_back与append

//Modifiersvoid push_back(char ch){//检查容量if (_size == _capacity)//二倍扩容reserve(_capacity == 0 ? 4 : 2 * _capacity);_str[_size] = ch;_size++;_str[_size] = '\0';}void append(const char * str){assert(str);//求出添加的字符串的长度int length = strlen(str);//判断添加后的有效字符数量是否越过容量if (_size + length > _capacity)reserve(_size + length);//_str + _size的位置为\0strcpy(_str + _size, str);_size += length;}

1.7:insert

1.7.1:插入字符

	string & insert(size_t position,char ch){assert(position <= _size);if (_size == _capacity)//二倍扩容reserve(_capacity == 0 ? 4 : 2 * _capacity);//从后向前挪动覆盖for(int i = _size - 1; i >= position ;i--){_str[i + 1] = _str[i];}_str[position] = ch;_size++;_str[_size] = '\0';return *this;}

1.7.2:插入字符串

string & insert(size_t position,const char * str){assert(position <= _size);int length = strlen(str);if (_size + length > _capacity)reserve(_size + length);//从后向前挪动覆盖//_size + length - 1表示挪动的字符串的重点,positon + length表示挪动的字符串的起点for(int i = _size + length - 1; i >= position + length; i--){_str[i] = _str[i - length];}//拷贝数据strncpy(_str + position, str, length);_size += length;_str[_size] = '\0';return *this;}

1.8:erase

		void erase(size_t position = 0,size_t len = -1){//防止越界assert(position < _size);//len == -1:如果 len 为 -1,表示删除到字符串末尾。//len >= _size - pos,如果 len 超过从 pos 开始的剩余字符长度,同样认为是删除到末尾。if(len == -1 || len >= _size - position){_str[position] = '\0';_size = position;}else{//将 pos + len 后的字符串内容复制到 pos 位置,从而覆盖中间 len 长度的字符,实现删除操作strcpy(_str + position, _str + position + len);}}

1.9:operator+=

1.9.1:添加字符

		string& operator+=(char ch){push_back(ch);return *this;}

1.9.2:添加字符串

		string& operator+=(const char * str){append(str);return *this;}

1.91:find

1.91.1:查找字符

//添加const修饰,令const成员与非const成员均可调用size_t find(char ch, size_t pos = 0) const{for(size_t i = pos; i < _size;i++){if (_str[i] == ch)return i;}return -1;}

1.91.2:查找字符串 

		const char * c_str()const{return _str;}//添加const修饰,令const成员与非const成员均可调用size_t find(const char * str,size_t pos = 0	)const{const char* p = strstr(_str + pos, str);if(p != NULL){//指针 - 指针得到对应的首字符下标return p - _str;}return -1;}

1.92:substr与swap

		string substr(size_t pos = 0, size_t len = -1){string substr;//len == -1:如果 len 为 -1,表示全部获取。//len > _size - pos,如果 len 超过从 pos 开始的剩余字符长度,同样认为是全部获取if(len > _size - pos || len == -1){for(size_t i = 0; i < _size; i++){substr += _str[i];}}else{for(size_t i = pos; i < pos + len;i++){substr += _str[i];}}return substr;}//s1.swap(s2)void swap(string & str){std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);}

1.93:非成员函数的重载

1.93.1:流插入与流提取的重载

	ostream& operator<<(ostream& _cout,MyString::string& str){for (auto ch : str){cout << ch;}return _cout;}istream& operator>>(istream& _cin, MyString::string& str){第一版:会导致空间的浪费//char ch;_cin是无法读到\n与' '的//ch = _cin.get();清空字符//str.clear();//while (ch != '\n' && ch != ' ')//{//	str += ch;//	ch = _cin.get();//}//return _cin;//第二版char ch;ch = _cin.get();//底层给个buffchar buff[128];size_t i = 0;//将原本的字符清空str.clear();//cin无法读取' '与'\n'while (ch != '\n' && ch != ' '){buff[i++] = ch;//最后一个字符设置为\0if(i == 127){buff[i] = '\0';str += buff;}//持续读取字符ch = _cin.get();}if(i > 0){buff[i] = '\0';str += buff;}return _cin;} 
}
按照常规方式,流提取按照上面的第一版方式进行重载即可,但是,底层其实是给了buff,目的是: 防止空间的浪费,因为按照常规方式重载的话,那么在 扩容的时候一般是1.5倍或者2倍扩容,而通过给一个buff,能够最大程度地防止空间的浪费.

1.93.2:其他非成员函数的重载

	//会先调用此swap,有现成的,吃现成的,不使用模版里面的swapvoid swap(string& x, string& y){x.swap(y);}//自定义类型传值传参会调用拷贝构造,因此需要传引用bool operator==(const MyString::string& str1, const  MyString::string& str2){int result = strcmp(str1.c_str(), str2.c_str());return result == 0;}bool operator<(const  MyString::string& str1, const MyString::string& str2){int result = strcmp(str1.c_str(), str2.c_str());return result < 0;}bool operator>(const  MyString::string& str1, const  MyString::string& str2){int result = strcmp(str1.c_str(), str2.c_str());return result > 0;}bool operator<=(const  MyString::string& str1, const  MyString::string& str2){return (str1 < str2) || (str1 == str2);}bool operator>=(const  MyString::string& str1, const  MyString::string& str2){return !(str1 < str2);}bool operator!=(const  MyString::string& str1, const  MyString::string& str2){return !(str1 == str2);}

2:Test.cpp

2.1:构造函数与拷贝构造

2.1.1:测试写法一

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestConstructionAndCopyConstruction()
{MyString::string s1;MyString::string s2("hello world");MyString::string s3(s2);
}
int main()
{TestConstructionAndCopyConstruction();return 0;
}

2.1.2:测试写法二

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestConstructionAndCopyConstruction()
{MyString::string s1;MyString::string s2("hello world");MyString::string s3(s2);
}
int main()
{TestConstructionAndCopyConstruction();return 0;
}

2.2:测试赋值运算符重载与[]获取元素

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestAssignmentOperatorOverloadingAndElementAccess()
{MyString::string s1;MyString::string s2("hello world");const MyString::string s3("hello Linux");s1 = s2;cout <<"s1[0]:>" << s1[0] << endl;cout <<"s3[6]:>" << s3[6] << endl;
}
int main()
{TestAssignmentOperatorOverloadingAndElementAccess();return 0;
}

2.3:测试迭代器与容量

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestIteratorAndCapacity()
{MyString::string s1;MyString::string s2("hello world");s1 = s2;for(auto & element : s2){cout << element << endl;}cout <<"s2.size()" << s2.size() << endl;cout <<"s2.capacity()" << s2.capacity() << endl;
}int main()
{TestIteratorAndCapacity();return 0;
}

2.4:测试reserve与resize 

2.4.1:测试resize

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestResize()
{MyString::string str("hello world");//比size小则进行删除str.resize(10);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << endl;//比size大但小于capacity会用改变size,并用\0插入str.resize(13);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << endl;//比capacity大,会先改变size的大小同时进行扩容str.resize(20);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;
}int main()
{TestResize();return 0;
}

2.4.2:测试reserve

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestRserve()
{MyString::string str("hello world");cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << "reserver后" << endl;cout << endl;//比size小不变化str.reserve(10);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << endl;//比size大但小于capacity也不发生变化str.reserve(13);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << endl;//比capacity大才会进行扩容str.reserve(20);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;
}int main()
{TestRserve();return 0;
}

2.5:测试push_back与append

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestPushBackAndAppend()
{MyString::string str;str.append("hello world");str.push_back('x');
}int main()
{TestPushBackAndAppend();return 0;
}

2.6:测试insert

2.6.1:测试插入字符

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestInsert() 
{MyString::string str("hello world");//在下标为5的位置插入字符hstr.insert(5, 'h');
}int main()
{TestInsert();return 0;
}

2.6.2:测试插入字符串

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestInsert() 
{MyString::string str("hello world");//在下标为5的位置插入字符hstr.insert(5, 'h');str.insert(2, "Linux");
}int main()
{TestInsert();return 0;
}

2.7:测试erase

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestErase()
{MyString::string str("hello world");str.erase(2, 4);
}int main()
{TestErase();return 0;
}

 

2.8:测试operator+=

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void Test()
{MyString::string str("hello");str += ' ';str += "Linux";
}int main()
{Test();return 0;
}

2.9:测试find

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestFind() 
{MyString::string str("hello Linux");cout << str.find('l', 2) << endl;cout << str.find("Linux", 2) << endl;
}int main()
{TestFind();return 0;
}

2.91:测试substr与swap

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestSwapAndSubstr()
{MyString::string s1("hello Linux");MyString::string s2("hello bit");MyString::string temp = s1.substr(6, 5);cout << "交换前" << endl;cout << "s1:>" << s1 << endl;cout << "s2:>" << s2 << endl;cout <<"temp:>" << temp << endl;s1.swap(s2);cout << "交换后" << endl;cout <<"s1:>" << s1 << endl;cout <<"s2:>" << s2 << endl;
}
int main()
{TestSwapAndSubstr();return 0;
}

2.92:测试流插入与流提取

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestStreamInsertionAndStreamExtraction()
{MyString::string s1;cin >> s1;cout << s1 << endl;cout << "s1.size:>" << s1.size() << endl;cout << "s1.capacity:>" << s1.capacity() << endl;
}
int main()
{TestStreamInsertionAndStreamExtraction();return 0;
}

2.92.1:第一版流提取

2.92.2:第二版流提取

2.93:测试其他非成员函数

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"
void TestOtherFunction()
{MyString::string s1("hello world");MyString::string s2("hello bit");swap(s1, s2);s1.swap(s2);cout << s1.c_str() << endl;cout << s2.c_str() << endl;cout << (s1 == s2) << endl;cout << (s1 >= s2) << endl;cout << (s1 > s2) << endl;cout << (s1 < s2) << endl;cout << (s1 <= s2) << endl;cout << (s1 != s2) << endl;
}int main()
{TestOtherFunction();return 0;
}

3:知识补充

3.1:深拷贝与浅拷贝

在讲深浅拷贝之前,我们来看一个现象

我们可以清晰地看到,s2与s3的地址一样,这是为什么呢,因为博主将显示定义的拷贝构造函数给屏蔽了,因此在拷贝构造s3时会调用编译器默认的拷贝构造函数,那么这就会导致一个问题:

s2与s3共用同一块内存空间,在释放时同一块内存空间被释放多次而会引起程序崩溃,这种方式被称作浅拷贝.

3.1.1:浅拷贝

浅拷贝:又被称作位拷贝,编译器直接是将另外一个对象的值拷贝复制过来.如果对象中管理资源,那么最后就会导致多个对象共享一份资源,当一个对象销毁时就会将资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还是有效的,那么因此当继续对资源进行操作时,就会发生访问违规~

举一个简单例子

就像一个家庭中有两个孩子,但父母只买了一份玩具,两个孩子愿意一块玩,则万事大吉,万一不想分享就你争我抢,玩具损坏.
那么该如何解决浅拷贝的问题呢,用深拷贝就可以即每个对象都有一份独立的资源,不要和其他对象共享。父母给每个孩子都买一份玩具,各自玩各自的就不会有存在任何矛盾.  

 3.1.2:深拷贝

如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出,一般情况都是按照深拷贝方式提供.

4:总代码

4.1:string.h

#include <iostream>
#include <string.h>
#include <assert.h>
using namespace std;//避免与库中的string冲突,因此使用命名空间
namespace MyString
{class string{typedef char* iterator;typedef const char* const_iterator;public://string()//	:_str(new char[1])//	, _size(0)//	,_capacity(0)//{//	//空字符串只有\0,//	_str[0] = '\0';//}构造非空字符串//string(const char * str)//	//开辟空间,多开辟个空间存放\0//	:_str(new char[strlen(str) + 1])//{//	//开辟空间//	_capacity = _size = strlen(str);//	//拷贝数据//	strcpy(_str, str);//}//给缺省值,构造空字符串时使用缺省值string(const char* str = "")//开辟空间,多开辟个空间存放\0:_str(new char[strlen(str) + 1]){//开辟空间_capacity = _size = strlen(str);//拷贝数据strcpy(_str, str);}/*拷贝构造函数s2(s1),使用s1拷贝构造s2*/string(string& s){//开辟空间char* temp = new char[s._capacity + 1];_str = temp;_capacity = s._capacity;_size = s._size;//拷贝数据strcpy(_str, s._str);}//s1 = s2 this---->s1   s2----->s//赋值运算符重载string& operator =(string& s){//开辟新空间char* temp = new char[s._capacity + 1];//释放旧空间delete _str;//拷贝数据strcpy(temp, s._str);//指向新空间_str = temp;_size = s._size;_capacity = s._capacity;return *this;}//T &,返回引用同样可以提高效率,有返回值的目的是为了支持连续赋值.char& operator[](size_t position){assert(position < _size);return _str[position];}//const成员函数,给const对象调用,与上面构成函数重载const char& operator[](size_t position) const{assert(position < _size);return _str[position];}/////iteraoriterator begin(){return _str;}iterator end(){return _str + _size;}//设置成员函数const_iterator begin() const{return _str;}const_iterator end() const{return _str + _size;}//capacitysize_t size(){return _size;}size_t capacity(){return _capacity;}//仅需判断是否比capacity大void reserve(size_t n){if (n > _capacity){//开辟新空间char* temp = new char[n + 1];//拷贝数据strcpy(temp, _str);//释放旧空间delete[] _str;//指向新空间_str = temp;_capacity = n;}}void resize(size_t n, char ch = '\0'){//比size小则会进行删除if (n <= _size){_str[n] = ch;}//比size大比capacity小会改变size,并且用\0插入else if (n > _size && n <= _capacity){_size = n;}//比capacity大, 会先改变size的大小同时进行扩容.else{//扩容reserve(n);for (size_t i = _size; i < _capacity; i++){_str[i] = ch;}_size = n;}}//Modifiersvoid push_back(char ch){//检查容量if (_size == _capacity)//二倍扩容reserve(_capacity == 0 ? 4 : 2 * _capacity);_str[_size] = ch;_size++;_str[_size] = '\0';}void append(const char* str){assert(str);//求出添加的字符串的长度int length = strlen(str);//判断添加后的有效字符数量是否越过容量if (_size + length > _capacity)reserve(_size + length);//_str + _size的位置为\0strcpy(_str + _size, str);_size += length;}string& insert(size_t position, char ch){assert(position <= _size);if (_size == _capacity)//二倍扩容reserve(_capacity == 0 ? 4 : 2 * _capacity);//从后向前挪动覆盖for (int i = _size - 1; i >= position; i--){_str[i + 1] = _str[i];}_str[position] = ch;_size++;_str[_size] = '\0';return *this;}void clear(){_str[0] = '\0';_size = 0;}bool empty()const{return _size == 0;}string& insert(size_t position, const char* str){assert(position <= _size);int length = strlen(str);if (_size + length > _capacity)reserve(_size + length);//从后向前挪动覆盖//_size + length - 1表示挪动的字符串的重点,positon + length表示挪动的字符串的起点for (int i = _size + length - 1; i >= position + length; i--){_str[i] = _str[i - length];}//拷贝数据strncpy(_str + position, str, length);_size += length;_str[_size] = '\0';return *this;}void erase(size_t position = 0, size_t len = -1){//防止越界assert(position < _size);//len == -1:如果 len 为 -1,表示删除到字符串末尾。//len >= _size - pos,如果 len 超过从 pos 开始的剩余字符长度,同样认为是删除到末尾。if (len == -1 || len >= _size - position){_str[position] = '\0';_size = position;}else{//将 pos + len 后的字符串内容复制到 pos 位置,从而覆盖中间 len 长度的字符,实现删除操作strcpy(_str + position, _str + position + len);}}string& operator+=(char ch){push_back(ch);return *this;}string& operator+=(const char * str){append(str);return *this;}const char * c_str()const{return _str;}//添加const修饰,令const成员与非const成员均可调用size_t find(char ch, size_t pos = 0) const{for(size_t i = pos; i < _size;i++){if (_str[i] == ch)return i;}return -1;}//添加const修饰,令const成员与非const成员均可调用size_t find(const char * str,size_t pos = 0	)const{const char* p = strstr(_str + pos, str);if(p != NULL){//指针 - 指针得到对应的首字符下标return p - _str;}return -1;}string substr(size_t pos = 0, size_t len = -1){string substr;//len == -1:如果 len 为 -1,表示全部获取。//len > _size - pos,如果 len 超过从 pos 开始的剩余字符长度,同样认为是全部获取if(len > _size - pos || len == -1){for(size_t i = 0; i < _size; i++){substr += _str[i];}}else{for(size_t i = pos; i < pos + len;i++){substr += _str[i];}}return substr;}//s1.swap(s2)void swap(string & str){std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);}//析构函数~string(){delete[] _str;_size = _capacity = 0;}private://定义成员变量并且给缺省值char* _str = nullptr;int   _size = 0;int   _capacity = 0;};//Non-member_function_overloadsostream& operator<<(ostream& _cout,MyString::string& str){for (auto ch : str){cout << ch;}return _cout;}istream& operator>>(istream& _cin, MyString::string& str){第一版:会导致空间的浪费//char ch;_cin是无法读到\n与' '的//ch = _cin.get();清空字符//str.clear();//while (ch != '\n' && ch != ' ')//{//	str += ch;//	ch = _cin.get();//}//return _cin;//第二版char ch;ch = _cin.get();//底层给个buffchar buff[128];size_t i = 0;//将原本的字符情况str.clear();//cin无法读取' '与'\n'while (ch != '\n' && ch != ' '){buff[i++] = ch;//最后一个字符设置为\0if(i == 127){buff[i] = '\0';str += buff;}//持续读取字符ch = _cin.get();}if(i > 0){buff[i] = '\0';str += buff;}return _cin;}//会先调用此swap,有现成的,吃现成的,不使用模版里面的swapvoid swap(string& x, string& y){x.swap(y);}//自定义类型传值传参会调用拷贝构造,因此需要传引用bool operator==(const MyString::string& str1, const  MyString::string& str2){int result = strcmp(str1.c_str(), str2.c_str());return result == 0;}bool operator<(const  MyString::string& str1, const MyString::string& str2){int result = strcmp(str1.c_str(), str2.c_str());return result < 0;}bool operator>(const  MyString::string& str1, const  MyString::string& str2){int result = strcmp(str1.c_str(), str2.c_str());return result > 0;}bool operator<=(const  MyString::string& str1, const  MyString::string& str2){return (str1 < str2) || (str1 == str2);}bool operator>=(const  MyString::string& str1, const  MyString::string& str2){return !(str1 < str2);}bool operator!=(const  MyString::string& str1, const  MyString::string& str2){return !(str1 == str2);}
}

4.2:Test.cpp

#define _CRT_SECURE_NO_WARNINGS
#include "String.h"void TestConstructionAndCopyConstruction()
{MyString::string s1;MyString::string s2("hello world");MyString::string s3(s2);
}void TestAssignmentOperatorOverloadingAndElementAccess()
{MyString::string s1;MyString::string s2("hello world");const MyString::string s3("hello Linux");s1 = s2;cout <<"s1[0]:>" << s1[0] << endl;cout <<"s3[6]:>" << s3[6] << endl;
}void TestIteratorAndCapacity()
{MyString::string s1;MyString::string s2("hello world");s1 = s2;for(auto & element : s2){cout << element;}cout << endl;cout <<"s2.size():>" << s2.size() << endl;cout <<"s2.capacity():>" << s2.capacity() << endl;
}void TestResize()
{MyString::string str("hello world");//比size小则进行删除str.resize(10);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << endl;//比size大但小于capacity会用改变size,并用\0插入str.resize(13);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << endl;//比capacity大,会先改变size的大小同时进行扩容str.resize(20);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;
}void TestRserve()
{MyString::string str("hello world");cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << "reserver后" << endl;cout << endl;//比size小不变化str.reserve(10);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << endl;//比size大但小于capacity也不发生变化str.reserve(13);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;cout << endl;//比capacity大才会进行扩容str.reserve(20);cout << "size:>" << str.size() << endl;cout << "capacity:>" << str.capacity() << endl;
}void TestPushBackAndAppend()
{MyString::string str;str.append("hello world");str.push_back('x');
}
void TestInsert() 
{MyString::string str("hello world");//在下标为5的位置插入字符hstr.insert(5, 'h');str.insert(2, "Linux");
}void TestErase()
{MyString::string str("hello world");str.erase(2, 4);
}void Test()
{MyString::string str("hello");str += ' ';str += "Linux";
}void TestFind() 
{MyString::string str("hello Linux");cout << str.find('l', 2) << endl;cout << str.find("Linux", 2) << endl;
}
void TestSwapAndSubstr()
{MyString::string s1("hello Linux");MyString::string s2("hello bit");MyString::string temp = s1.substr(6, 5);cout << "交换前" << endl;cout << "s1:>" << s1 << endl;cout << "s2:>" << s2 << endl;cout <<"temp:>" << temp << endl;s1.swap(s2);cout << "交换后" << endl;cout <<"s1:>" << s1 << endl;cout <<"s2:>" << s2 << endl;
}void TestStreamInsertionAndStreamExtraction()
{MyString::string s1;cin >> s1;cout << s1 << endl;cout << "s1.size:>" << s1.size() << endl;cout << "s1.capacity:>" << s1.capacity() << endl;
}void TestOtherFunction()
{MyString::string s1("hello world");MyString::string s2("hello bit");swap(s1, s2);s1.swap(s2);cout << s1.c_str() << endl;cout << s2.c_str() << endl;cout << (s1 == s2) << endl;cout << (s1 >= s2) << endl;cout << (s1 > s2) << endl;cout << (s1 < s2) << endl;cout << (s1 <= s2) << endl;cout << (s1 != s2) << endl;
}int main()
{TestConstructionAndCopyConstruction();TestAssignmentOperatorOverloadingAndElementAccess();TestIteratorAndCapacity();TestResize();TestRserve();TestPushBackAndAppend();TestInsert();TestErase();Test();TestFind();TestSwapAndSubstr();TestStreamInsertionAndStreamExtraction();TestOtherFunction();return 0;
}

好啦,uu们,string的模拟实现这部分滴详细内容博主就讲到这里啦,如果uu们觉得博主讲的不错的话,请动动你们滴小手给博主点点赞,你们滴鼓励将成为博主源源不断滴动力,同时也欢迎大家来指正博主滴错误~

http://www.mnyf.cn/news/51903.html

相关文章:

  • 青海网站建设策划站长之家是什么
  • 建设工程质量管理条例网站营销策略有哪些内容
  • 做VIP视频网站赚钱福州百度seo
  • 海口中小企业网站制作seo工具包
  • 建设好网站怎么进行网站关键词优化
  • wordpress 中英文seo网络搜索引擎优化
  • 海口今日头条新闻如何做好seo基础优化
  • 企业网站的用户需求百度推销广告一年多少钱
  • 连云港建设工程安全网站站长seo查询
  • 学生网站建设实训报告seo百度快速排名
  • 网站建设上qq图标去除网上seo研究
  • 做付费推广哪个网站好百度推广费用报价单
  • 游戏开发app苹果aso优化
  • 大港天津网站建设普通话手抄报简单又漂亮
  • 常熟高端网站建设饥饿营销案例
  • wordpress标签聚合美化佳木斯seo
  • 长沙做网站好的公司有哪些2023年8月疫情严重吗
  • 厦门营销网站制作如何实现网站的快速排名
  • 成都微信网站建设多线上营销的方式
  • 淄博网站有效的网络推广
  • 专门做车评的网站中小企业网络推广
  • 网站php环境搭建深圳外贸网站建设
  • 深圳很多90后做虚假彩票网站诈骗优化关键词排名外包
  • 怎么用本机ip做网站seo免费诊断
  • 海口做网站公司哪家好百度应用市场app下载安装
  • 网站专题页ps教程举一个病毒营销的例子
  • 南昌网站全新开发教育机构培训
  • 香河做网站网络推广网站有哪些
  • 企业网站内容如何备案网络营销整合推广
  • wordpress关键词替换上海推广seo