php購物網(wǎng)站搜索欄怎么做怎么樣把廣告做在百度上
?感謝您閱讀本篇文章,文章內(nèi)容是個人學(xué)習(xí)筆記的整理,如果哪里有誤的話還請您指正噢?
? 個人主頁:余輝zmh–CSDN博客
?文章所屬專欄:c++篇–CSDN博客
文章目錄
- 前言
- 一.`string`類的默認(rèn)成員函數(shù)以及深拷貝
- 1.基本框架
- 2.默認(rèn)成員函數(shù)
- 1.構(gòu)造函數(shù)
- 2.析構(gòu)函數(shù)
- 3.拷貝構(gòu)造函數(shù)(深拷貝)
- 4.賦值運(yùn)算符重載(深拷貝)
- 3.什么是深拷貝
- 深拷貝的必要性
- 深拷貝的實(shí)現(xiàn)
- 4.測試
- 二.`string`類的訪問和迭代器相關(guān)函數(shù)
- 1.訪問相關(guān)函數(shù)
- 2.迭代器相關(guān)函數(shù)
- 1.普通`string`對象的迭代器
- 2.`const` `string`對象的迭代器
- 3.測試
- 三.`string`類的容量相關(guān)函數(shù)
- 1.容量大小相關(guān)函數(shù)
- 2.擴(kuò)容相關(guān)函數(shù)
- 3.測試
- 四.`string`類的修改相關(guān)函數(shù)
- 1.拼接操作相關(guān)函數(shù)
- 2.插入操作相關(guān)函數(shù)
- 3.刪除操作相關(guān)函數(shù)
- 4.測試
- 五.`string`類的流插入和流提取函數(shù)
- 六.`string`類完整代碼
- 1.`string.h`頭文件代碼
- 2.`string.cpp`函數(shù)定義文件代碼
- 3.`test.cpp`測試文件代碼
前言
在上一篇文章中,我們了解到了std::string
類的常用接口函數(shù)以及如何熟練使用。在這片文章中,我們將深入探討如何模擬實(shí)現(xiàn)一個基本的string
類。我們的目的不是創(chuàng)建一個功能完整的string
庫,而是通過這個過程來學(xué)習(xí)字符串處理的基本原理和常見的實(shí)現(xiàn)技巧。通過模擬實(shí)現(xiàn)string
類,我們不僅能夠深入理解字符串的內(nèi)部工作原理,還能鍛煉我們的編程能力,提高解決問題的能力,希望這篇文章能過為你的編程之旅提供有價值的參考和啟發(fā)。
注意:模擬實(shí)現(xiàn)string類需要用到三個文件
test.cpp
文件用來進(jìn)行測試string.cpp
文件用來定義接口函數(shù)(部分較為短小的函數(shù)將會直接在string.h
文件中定義)string.h
文件用來聲明頭文件和string類
一.string
類的默認(rèn)成員函數(shù)以及深拷貝
1.基本框架
為了和庫里面的std::string
類進(jìn)行區(qū)分,我們首先定義一個命名空間Mystring
用來封裝我們自己模擬實(shí)現(xiàn)的string
類。
基本框架如下:
namespace Mystring{class string{Public:static const size_t npos=-1;//成員函數(shù)private://成員變量char* _str;size_t _size;size_t capacity;};
}
_st
r在堆上開辟動態(tài)內(nèi)存用來存儲string對象的數(shù)據(jù)。_size
用來記錄string對象的實(shí)際大小。_capacity
用來記錄當(dāng)前string對象可存儲的最大容量。npos
是一個無符號整形的最大值,在查找等相關(guān)函數(shù)會用到。
2.默認(rèn)成員函數(shù)
前面我們知道,一個類中有六個默認(rèn)成員函數(shù)(在我之前的文章類和對象(二)中有關(guān)于默認(rèn)成員函數(shù)的詳細(xì)講解,不清楚的可以看我之前的文章),在模擬實(shí)現(xiàn)string類時,我們只需要實(shí)現(xiàn)常用的四個(構(gòu)造函數(shù),析構(gòu)函數(shù),拷貝構(gòu)造函數(shù),賦值運(yùn)算符重載)即可。
1.構(gòu)造函數(shù)
-
代碼實(shí)現(xiàn):
//string.h中聲明 string(const char* str = ""); //string.cpp中定義 Mystring::string::string(const char* str) :_size(strlen(str)) ,_capacity(_size) ,_str(new char[_size+1]) {memcpy(_str,str,_size+1); }
-
實(shí)現(xiàn)原理:
- str字符串作為常量參數(shù)用來創(chuàng)建string對象,缺省值為空字符串(當(dāng)沒有參數(shù)時就是創(chuàng)建一個空對象),缺省值要在聲明中給,不能再定義中給。
- _size字符串大小和_capacity容量初始化值為參數(shù)str字符串的大小(strlen(str))。
- _str指針用來指向存儲string對象的動態(tài)內(nèi)存,開辟空間的大小為參數(shù)str字符串的大小加一,加一是為了存放結(jié)尾的’\0’,開辟空間后要將str字符串內(nèi)容拷貝到開辟的動態(tài)內(nèi)存。
2.析構(gòu)函數(shù)
-
代碼實(shí)現(xiàn):
//string.h文件中聲明 ~string(); //string.cpp文件中定義 Mystring::string::~string(){delete[] _str;_str=nullptr;_size=0;_capacity=0; }
-
實(shí)現(xiàn)原理:
- 釋放動態(tài)內(nèi)存空間,再將_str指針置為空指針。
- _size字符串大小和_capacity容量置為0。
3.拷貝構(gòu)造函數(shù)(深拷貝)
-
代碼實(shí)現(xiàn):
//string.h文件中聲明 string(const string&s); //string.cpp文件中定義 Mystring::string::string(const string&s) {_str=new char[s._capacity+1];strcpy(_str,s._str);_size=s._size;_capacity=s._capacity; }
-
實(shí)現(xiàn)原理:
- 用一個string對象拷貝構(gòu)造一個新的string對象,拷貝構(gòu)造函數(shù)需要完成深拷貝。
- 先用字符串s的容量作為新空間的大小申請一個新的動態(tài)內(nèi)存空間,再將s字符串的數(shù)據(jù)拷貝到新的內(nèi)存空間中。
- 新的string對象的_size和_capacity分別是原string對象的_size和_capacity.
4.賦值運(yùn)算符重載(深拷貝)
-
代碼實(shí)現(xiàn):
//string.h文件中聲明 string& operator=(const string&s); //string.cpp文件中定義 Mystring::string& Mystring::string::operator=(const string&s) {char* tmp=new char[s._capacity+1];memcpy(tmp,s._str,s._size+1);delete[] _str;_str=tmp;_capacity=s._capacity;_size=s._size;return *this; }
-
實(shí)現(xiàn)原理:
- 賦值和拷貝構(gòu)造的不同點(diǎn)在于,拷貝構(gòu)造是用已有的對象拷貝構(gòu)造一個新的對象;而賦值是用一個已存在的對象賦值給另一個已存在的對象,賦值也是需要完成深拷貝。
- 先用賦值對象s的容量大小申請一個新的動態(tài)內(nèi)存空間,設(shè)置一個新的tmp指針先指向這塊空間,再將賦值對象s的數(shù)據(jù)拷貝到新的內(nèi)存空間中。
- 釋放被賦值對象的原有空間,再將被賦值對象的_str指針指向新的內(nèi)存空間。
- 被賦值對象的_size和_capacity分別是賦值對象s的_size和_capacity.
3.什么是深拷貝
深拷貝(Deep Copy)是對象復(fù)制操作中的一種,它不僅僅復(fù)制對象的表層數(shù)據(jù)(如指針或引用),還會遞歸地復(fù)制對象內(nèi)部所有動態(tài)分配的內(nèi)存、引用的其他對象或其他資源。這樣,復(fù)制出來的新對象與原始對象在內(nèi)存中是完全獨(dú)立的,對它們的修改不會影響到彼此。
深拷貝的必要性
當(dāng)對象包含指向動態(tài)分配內(nèi)存的指針或其他需要管理的資源時,淺拷貝(僅復(fù)制指針值)會導(dǎo)致兩個對象共享同一塊內(nèi)存。這可能會引發(fā)以下問題:
- 數(shù)據(jù)損壞:一個對象修改了它共享的內(nèi)存中的數(shù)據(jù),導(dǎo)致另一個對象看到的數(shù)據(jù)也發(fā)生了變化。
- 內(nèi)存泄漏:如果兩個對象都認(rèn)為自己擁有這塊內(nèi)存,并在析構(gòu)時嘗試釋放它,就會導(dǎo)致重復(fù)釋放內(nèi)存的錯誤(double free),進(jìn)而可能導(dǎo)致程序崩潰。
- 資源管理混亂:如果對象還管理其他資源(如文件句柄、網(wǎng)絡(luò)連接等),共享這些資源可能會導(dǎo)致資源被意外關(guān)閉或重復(fù)訪問。
深拷貝的實(shí)現(xiàn)
實(shí)現(xiàn)深拷貝通常涉及以下幾個步驟:
- 為新對象分配內(nèi)存:如果原始對象包含動態(tài)分配的內(nèi)存,深拷貝的第一步是為新對象分配相應(yīng)的內(nèi)存空間。
- 復(fù)制數(shù)據(jù):將原始對象中的數(shù)據(jù)復(fù)制到新分配的內(nèi)存中。如果數(shù)據(jù)本身也是對象(即對象包含指向其他對象的指針),則需要遞歸地應(yīng)用深拷貝。
- 更新指針:將新對象的指針成員指向新分配的內(nèi)存,而不是原始對象的內(nèi)存。
- 處理其他資源:如果對象管理其他資源(如文件、網(wǎng)絡(luò)連接等),則需要確保新對象也能正確地獲取或創(chuàng)建這些資源的副本。
4.測試
測試代碼如下:
void test1(){//創(chuàng)建s1對象Mystring::string s1("hello world");//用s1對象拷貝構(gòu)造s2對象Mystring::string s2(s1);//將s1對象賦值給s3對象Mystring::string s3("hello");s3=s1;
}
測試結(jié)果如下:
二.string
類的訪問和迭代器相關(guān)函數(shù)
1.訪問相關(guān)函數(shù)
-
at()
函數(shù)代碼實(shí)現(xiàn)://string文件中聲明和定義 char& at(size_t pos) {//斷言檢查pos是否符合字符串的范圍assert(pos<_size);//直接返回字符數(shù)組對應(yīng)下標(biāo)上的字符即可return _str[pos]; }
-
operator[]
函數(shù)代碼實(shí)現(xiàn)://string文件中聲明和定義 //和at()函數(shù)同理 char& operator[](size_t pos) {assert(pos<_size);return _str[pos]; }
2.迭代器相關(guān)函數(shù)
1.普通string
對象的迭代器
-
類型定義:
//普通string對象的迭代器類型 typedef char* iterator;
-
begin()
函數(shù)代碼實(shí)現(xiàn)://string文件中聲明和定義 iterator begin()const {//返回_str首元素的地址return _str; }
-
end()
函數(shù)代碼實(shí)現(xiàn)://string文件中聲明和定義 iterator end()const {//返回_str最后一個元素的下一個位置的地址return _str+_size; }
2.const
string
對象的迭代器
-
類型定義:
//const string對象的迭代器類型 typedef const char* const_iterator;
-
cbegin()
函數(shù)代碼實(shí)現(xiàn)://string文件中聲明和定義 const_iterator begin()const {//返回_str首元素的地址return _str; }
-
cend()
函數(shù)代碼實(shí)現(xiàn)://string文件中聲明和定義 const_iterator end()const {//返回_str最后一個元素的下一個位置的地址return _str+_size; }
3.測試
測試代碼如下:
void test2(){Mystring::string s1("hello world");//使用opreator[]打印s1for(size_t i=0;i<s1.size();i++){cout<<s1[i]<<" ";}cout<<endl;//使用普通對象的迭代器打印s1Mystring::string::iterator it=s1.begin();while(it!=s1.end()){cout<<*it<<" ";it++;}cout<<endl;//使用const對象的迭代器打印s2const Mystring::string s2("hello");Mystring::string::const_iterator rit=s2.begin();while(rit!=s2.end()){cout<<*rit<<" ";rit++;}cout<<endl;
}
測試結(jié)果如下:
三.string
類的容量相關(guān)函數(shù)
1.容量大小相關(guān)函數(shù)
獲取string對象的大小需要使用size()函數(shù),獲取容量則需要使用capacity()函數(shù)
-
size()
函數(shù)代碼實(shí)現(xiàn)://string.h文件中聲明和定義 //直接返回_size即可 size_t size() {return _size; }
-
capacity()
函數(shù)代碼實(shí)現(xiàn)://string.h文件中聲明和定義 //直接返回_capacity即可 size_t capacity() {return _capacity; }
2.擴(kuò)容相關(guān)函數(shù)
string
類擴(kuò)容相關(guān)的函數(shù)主要是reserve()
和resize()
。
-
reserve()
函數(shù)代碼實(shí)現(xiàn)://string.h文件中聲明 void reserve(size_t); //string.cpp文件中定義 void Mystring::string::reserve(size_t n) {if(n>_capacity){char*tmp=new char[n+1];memcpy(tmp,_str,_size+1);delete[] _str;_str=tmp;_capacity=n;} }
-
實(shí)現(xiàn)原理:
- 首先判斷需要擴(kuò)容的大小n是否大于原容量大小_capacity,如果小于則不進(jìn)行擴(kuò)容,大于時就需要擴(kuò)容。
- 擴(kuò)容時先開辟內(nèi)存大小為(n+1)的動態(tài)內(nèi)存空間,在設(shè)置一個新的字符指針tmp指向新的內(nèi)存空間,然后將原string對象的數(shù)據(jù)拷貝到新的內(nèi)存空間中。
- 釋放原string對象的_str指針,再從新指向開辟的新內(nèi)存空間,最后更改內(nèi)存大小為n。
-
resize()
函數(shù)代碼實(shí)現(xiàn)://string.h文件中聲明 void resize(size_t n,char ch='\0'); //string.cpp文件中定義 void Mystring::string::resize(size_t n,char ch) {if(n>_capacity){reserve(n);}if(n>_size){for(size_t i=_size;i<n;i++){_str[i]=ch;}}_size=n;_str[_size]='\0';}
-
實(shí)現(xiàn)原理:
-
首先依然是需要判斷擴(kuò)容的大小n是否大于原容量大小_capacity,和reserve()函數(shù)不同的是,resize對于擴(kuò)容大小n小于原容量大小時會發(fā)生截斷,大于時就會進(jìn)行擴(kuò)容操作,這里擴(kuò)容操作直接調(diào)用reserve()函數(shù)即可。
-
如果擴(kuò)容大小n大于原string對象的_size,需要將多余的空間初始化為參數(shù)ch,參數(shù)ch的缺省值設(shè)置為’\0’(要在聲明中給),沒有傳參時,默認(rèn)初始化為0。
-
3.測試
測試代碼如下:
void test3(){Mystring::string s1("hello world");cout<<s1.size()<<" "<<s1.capacity()<<endl;//s1容量擴(kuò)為15s1.reserve(15);cout<<s1.size()<<" "<<s1.capacity()<<endl;//s1容量擴(kuò)為20,多余空間用字符a填充s1.resize(20,'a');cout<<s1.size()<<" "<<s1.capacity()<<endl;cout<<s1<<endl;//s1縮容為8,發(fā)生截斷s1.resize(8);cout<<s1.size()<<" "<<s1.capacity()<<endl;cout<<s1<<endl;
}
測設(shè)結(jié)果如下:
四.string
類的修改相關(guān)函數(shù)
1.拼接操作相關(guān)函數(shù)
-
1.push_back()函數(shù)實(shí)現(xiàn):
//string.h文件中聲明 void push_back(char ch); //string.cpp文件中定義 void Mystring::string::push_back(char ch) {if(_size==_capacity){reserve(_capacity==0?4:2*_capacity);}_str[_size]=ch;_size++;_str[_size]='\0'; }
2.實(shí)現(xiàn)原理:
- push_back()函數(shù)的功能是尾插單個字符,在尾插之前要先判斷是否需要擴(kuò)容,在擴(kuò)容時,如果需要尾插的string對象是空對象擴(kuò)容 大小先設(shè)置為4,如果不是空對象則擴(kuò)容大小是原容量的二倍,擴(kuò)容直接調(diào)用reserve()函數(shù)即可。
- 插入時,將原來字符串的’\0’位置存放插入的字符ch,再將大小_size增加一,最后重新在字符串的結(jié)尾加上’\0’。
-
1.
append()
函數(shù)實(shí)現(xiàn):append()函數(shù)有兩種不同的實(shí)現(xiàn),一個是在原
string
對象后增加單個字符,一個是增加字符串。//string.h文件中聲明 void append(char ch); void append(const char* str); //string.cpp文件中定義 //增加單個字符 void Mystring::string::append(char ch) {push_back(ch); } //增加字符串 void Mystring::string::append(const char* str) {size_t len=strlen(str);if(_size+len>_capacity){reserve(_size+len);}//_str加上_size就是原字符串結(jié)尾的位置,插入的字符串拷貝到原字符串后面memcpy(_str+_size,str,len+1);_size+=len; }
2.實(shí)現(xiàn)原理:
- 增加單個字符直接調(diào)用push_back函數(shù)。
- 增加字符串時,先獲取插入字符串的大小len,然后判斷原字符串的大小加上插入字符串的大小是否大于容量_capacity,如果大于需要先進(jìn)行擴(kuò)容,擴(kuò)容大小為原字符串的大小加上插入字符串的大小。
- 將插入的字符串拷貝到原字符串后面,拷貝大小為len+1,然后修改_size值。
-
1.
operator+=
函數(shù)實(shí)現(xiàn):operator+=
函數(shù)和append()
函數(shù)一樣有兩種不同的實(shí)現(xiàn),在原string
對象后增加單個字符和字符串。//string.h文件中聲明 string& operator+=(char ch); string& operator+=(const char* str); //string.cpp文件中定義 //增加單個字符 Mystring::string& Mystring::string::operator+=(char ch) {push_back(ch);return *this; } //增加字符串 Mystring::string& Mystring::string::operator+=(const char* str) {append(str);return *this; }
2.實(shí)現(xiàn)原理:
- 增加單個字符直接調(diào)用push_back()函數(shù),最后要返回this指針。
- 增加字符串直接調(diào)用append(const char* str)函數(shù),最后返回this指針。
2.插入操作相關(guān)函數(shù)
-
insert()
函數(shù)實(shí)現(xiàn):1.插入n個字符:
//string.h文件中聲明 void insert(size_t pos,size_t n,char ch); //string.cpp文件中定義 void Mystring::string::insert(size_t pos,size_t n,char ch) {assert(pos<_size);if((_size+n)>_capacity){reserve(_size+n);}size_t end=_size;while(end>=pos&&end!=npos){_str[end+n]=_str[end];end--;}for(size_t i=0;i<n;i++){_str[pos+i]=ch;}_size+=n;}
實(shí)現(xiàn)原理:
- 如果原字符串大小加上插入的個數(shù)大于容量大小時,需要先進(jìn)行擴(kuò)容,擴(kuò)容大小為原字符串大小加上插入的個數(shù)。
- 將插入位置后面的數(shù)據(jù)依次往后移動n個位置。
- 再將移動后空出來的位置插入n個字符ch。最后修改_size大小。
2.插入字符串:
//string.h文件中聲明 void insert(size_t pos,const char*str); //string.cpp文件中定義 void Mystring::string::insert(size_t pos,const char*str) {assert(pos<_size);size_t len=strlen(str);if(_size+len>_capacity){reserve(_size+len);}size_t end=_size;while(end>=pos&&end!=npos){_str[end+len]=_str[end];end--;}for(size_t i=0;i<len;i++){_str[pos+i]=str[i];}_size+=len; }
實(shí)現(xiàn)原理:
- 插入字符串和插入n個字符原理相同,不同點(diǎn)是,最后插入時,需要依次插入字符串的字符。
3.刪除操作相關(guān)函數(shù)
-
erase()
函數(shù)實(shí)現(xiàn)://string.h中聲明 void erase(size_t pos,size_t len=npos); //string.cpp文件中定義 void Mystring::string::erase(size_t pos,size_t len) {assert(pos<_size);if(len==npos||pos+len>=_size){_size=pos;_str[_size]='\0';}else{size_t end=len+pos;while(end<=_size){_str[pos++]=_str[end++];}_size-=len;} }
-
實(shí)現(xiàn)原理:
- 刪除要分為兩種情況,第一種,如果刪除的個數(shù)大于_size或者len等于npos值,直接從pos位置將后面全部刪除。
- 第二種,依次將后面的字符往前移動,從而達(dá)到刪除的目的。
4.測試
測試代碼如下:
void test4(){//創(chuàng)建一個空對象s1Mystring::string s1;//s1追加字符串hellos1.append("hello");cout<<s1<<endl;//s1追加字符串worlds1+="world";cout<<s1<<endl;//s1尾插字符!s1.push_back('!');cout<<s1<<endl;//在s1下標(biāo)為6的位置插入***s1.insert(6,"***");cout<<s1<<endl;//刪除s1下標(biāo)為10后面的所有字符s1.erase(10);cout<<s1<<endl;//刪除s1下標(biāo)為5后面的三個字符s1.erase(5,3);cout<<s1<<endl;
}
測試結(jié)果如下:
五.string
類的流插入和流提取函數(shù)
-
1.
operator<<
流插入函數(shù)實(shí)現(xiàn)://string.h文件中聲明 ostream& operator<<(ostream& out,const string&s); //string.cpp文件中定義 ostream& Mystring::operator<<(ostream& out,const string&s) {cout<<"operator<<"<<endl;for(auto e:s){out<<e;}return out; }
-
1.
operator>>
流提取函數(shù)實(shí)現(xiàn)://string.h文件中聲明 istream& operator>>(istream &in,string &s); //string.cpp文件中定義 istream& Mystring::operator>>(istream &in, string &s) {cout<<"operator>>"<<endl;s.clear();char ch = in.get();// 處理前緩沖區(qū)前面的空格或者換行while (ch == ' ' || ch == '\n'){ch = in.get();}char buff[128];int i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}if (i != 0){buff[i] = '\0';s += buff;}return in; }
測試代碼如下:
void test5(){Mystring::string s1;//輸入cin>>s1;//輸出cout<<s1<<endl;
}
六.string
類完整代碼
1.string.h
頭文件代碼
#include<iostream>
#include<string>
#include<string.h>
#include<assert.h>
using namespace std;namespace Mystring{class string{public:static const size_t npos=-1;//構(gòu)造函數(shù)string(const char* str = "");//析構(gòu)函數(shù)~string();//拷貝構(gòu)造函數(shù)string(const string&s);//賦值運(yùn)算符重載string& operator=(const string&s);//c格式打印const char* c_str(){return _str;}//容量大小size_t size(){return _size;}size_t capacity(){return _capacity;}//擴(kuò)容void reserve(size_t n);void resize(size_t n,char ch='\0');void clear(){_size=0;_str[_size]='\0';}//訪問方式char& operator[](size_t pos){assert(pos<_size);return _str[pos];}char& at(size_t pos){assert(pos<_size);return _str[pos];}//迭代器typedef char* iterator;iterator begin() {return _str;}iterator end() {return _str+_size;}typedef const char* const_iterator;const_iterator begin()const {return _str;}const_iterator end()const {return _str+_size;}//修改void push_back(char ch); void append(char ch); void append(const char* str); string& operator+=(char ch); string& operator+=(const char* str); void insert(size_t pos,size_t n,char ch);void insert(size_t pos,const char*str);void erase(size_t pos,size_t len=npos);//查找size_t find(char ch,size_t pos=0);size_t find(const char*str,size_t pos=0);//友元函數(shù)friend ostream& operator<<(ostream& out,const string&s);friend istream& operator>>(istream& in,string&s);private:int _size;int _capacity;char* _str;};//非string成員函數(shù)ostream& operator<<(ostream& out,const string&s);istream& operator>>(istream& in,string&s);
}
2.string.cpp
函數(shù)定義文件代碼
#include"string.h"Mystring::string::string(const char* str)
:_size(strlen(str))
,_capacity(_size)
,_str(new char[_size+1])
{cout<<"string()"<<endl;memcpy(_str,str,_size+1);
}Mystring::string& Mystring::string::operator=(const string&s)
{cout<<"operator="<<endl;char* tmp=new char[s._capacity+1];memcpy(tmp,s._str,s._size+1);delete[] _str;_str=tmp;_capacity=s._capacity;_size=s._size;return *this;
}Mystring::string::~string(){cout<<"~string()"<<endl;delete[] _str;_str=nullptr;_size=0;_capacity=0;
}Mystring::string::string(const string&s)
{cout<<"string()"<<endl;_str=new char[s._capacity+1];strcpy(_str,s._str);_size=s._size;_capacity=s._capacity;
}void Mystring::string::reserve(size_t n)
{if(n>_capacity){char*tmp=new char[n+1];memcpy(tmp,_str,_size+1);delete[] _str;_str=tmp;_capacity=n;}
}void Mystring::string::resize(size_t n,char ch)
{if(n>_capacity){reserve(n);}if(n>_size){for(size_t i=_size;i<n;i++){_str[i]=ch;}}_size=n;_str[_size]='\0';}void Mystring::string::push_back(char ch)
{if(_size==_capacity){reserve(_capacity==0?4:2*_capacity);}_str[_size]=ch;_size++;_str[_size]='\0';
}void Mystring::string::append(char ch)
{push_back(ch);
}void Mystring::string::append(const char* str)
{size_t len=strlen(str);if(_size+len>_capacity){reserve(_size+len);}memcpy(_str+_size,str,len+1);_size+=len;
}Mystring::string& Mystring::string::operator+=(char ch)
{push_back(ch);return *this;
}Mystring::string& Mystring::string::operator+=(const char* str)
{append(str);return *this;
}size_t Mystring::string::find(char ch,size_t pos)
{assert(pos<_size);for(size_t i=pos;i<_size;i++){if(_str[i]==ch){return i;}}return npos;
}size_t Mystring::string::find(const char*str,size_t pos)
{assert(pos<_size);const char* ptr=strstr(_str+pos,str);if(ptr){return ptr-_str;}else{return npos;}
}void Mystring::string::insert(size_t pos,size_t n,char ch)
{assert(pos<_size);if((_size+n)>_capacity){reserve(_size+n);}size_t end=_size;while(end>=pos&&end!=npos){_str[end+n]=_str[end];end--;}for(size_t i=0;i<n;i++){_str[pos+i]=ch;}_size+=n;}void Mystring::string::insert(size_t pos,const char*str)
{assert(pos<_size);size_t len=strlen(str);if(_size+len>_capacity){reserve(_size+len);}size_t end=_size;while(end>=pos&&end!=npos){_str[end+len]=_str[end];end--;}for(size_t i=0;i<len;i++){_str[pos+i]=str[i];}_size+=len;
}void Mystring::string::erase(size_t pos,size_t len)
{assert(pos<_size);if(len==npos||pos+len>=_size){_size=pos;_str[_size]='\0';}else{size_t end=len+pos;while(end<=_size){_str[pos++]=_str[end++];}_size-=len;}
}ostream& Mystring::operator<<(ostream& out,const string&s)
{//cout<<"operator<<"<<endl;for(auto e:s){out<<e;}return out;
}istream& Mystring::operator>>(istream &in, string &s)
{cout<<"operator>>"<<endl;s.clear();char ch = in.get();// 處理前緩沖區(qū)前面的空格或者換行while (ch == ' ' || ch == '\n'){ch = in.get();}char buff[128];int i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}if (i != 0){buff[i] = '\0';s += buff;}return in;
}
3.test.cpp
測試文件代碼
#include"string.h"void test1(){//創(chuàng)建s1對象Mystring::string s1("hello world");//用s1對象拷貝構(gòu)造s2對象Mystring::string s2(s1);//將s1對象賦值給s3對象Mystring::string s3("hello");s3=s1;
}void test2(){Mystring::string s1("hello world");//使用opreator[]打印s1for(size_t i=0;i<s1.size();i++){cout<<s1[i]<<" ";}cout<<endl;//使用普通對象的迭代器打印s1Mystring::string::iterator it=s1.begin();while(it!=s1.end()){cout<<*it<<" ";it++;}cout<<endl;//使用const對象的迭代器打印s2const Mystring::string s2("hello");Mystring::string::const_iterator rit=s2.begin();while(rit!=s2.end()){cout<<*rit<<" ";rit++;}cout<<endl;
}void test3(){Mystring::string s1("hello world");cout<<s1.size()<<" "<<s1.capacity()<<endl;//s1容量擴(kuò)為15s1.reserve(15);cout<<s1.size()<<" "<<s1.capacity()<<endl;//s1容量擴(kuò)為20,多余空間用字符a填充s1.resize(20,'a');cout<<s1.size()<<" "<<s1.capacity()<<endl;cout<<s1<<endl;//s1縮容為8,發(fā)生截斷s1.resize(8);cout<<s1.size()<<" "<<s1.capacity()<<endl;cout<<s1<<endl;
}void test4(){//創(chuàng)建一個空對象s1Mystring::string s1;//s1追加字符串hellos1.append("hello");cout<<s1<<endl;//s1追加字符串worlds1+="world";cout<<s1<<endl;//s1尾插字符!s1.push_back('!');cout<<s1<<endl;//在s1下標(biāo)為6的位置插入***s1.insert(6,"***");cout<<s1<<endl;//刪除s1下標(biāo)為10后面的所有字符s1.erase(10);cout<<s1<<endl;//刪除s1下標(biāo)為5后面的三個字符s1.erase(5,3);cout<<s1<<endl;
}void test5(){Mystring::string s1;//輸入cin>>s1;//輸出cout<<s1<<endl;}int main()
{//test1();//test2();//test3();//test4();test5();return 0;
}
以上就是關(guān)于如何模擬實(shí)現(xiàn)string類的講解,如果哪里有錯的話,可以在評論區(qū)指正,也歡迎大家一起討論學(xué)習(xí),如果對你的學(xué)習(xí)有幫助的話,點(diǎn)點(diǎn)贊關(guān)注支持一下吧!!!