簡單的string類的模擬實現
綜述:c++標準庫提供了一個字串型別string ,該型別可以直接定義一個字串物件,並且對字串進行各種操作;以下是本人根據c++標準庫中的string類,簡單的模擬實現該類;
先看cpulspuls中string類的成員函式:
其中我只實現圖中列出函式原型的幾個成員函式:
(1)實現之前先看看這寫函式及其過載函式是什麼意思:
測試程式碼:
#include<iostream>
using namespace std;
#include<string>
int main()
{
string str1("12345");
cout<<"str1:"<<str1<<endl;
str1.push_back('w');
cout<<"str1.push_back('w'):"<<str1<<endl;
cout<<"str1[0]:"<<str1[0]<<"\nstr[1]:"<<str1[1]<<endl;
string str2("abcde");
cout<<"str2:"<<str2<<endl;
str1+=str2;
cout<<"str1+=str2:"<<str1<<endl;
str1+="www";
cout<<"str1+=www:"<<str1<<endl;
str1+='M';
cout<<"str1+='M':"<<str1<<endl;
cout<<endl;
cout<<endl;
string str3("123456");
string str4("www");
cout<<"str3:"<<str3<<"\nstr4:"<<str4<<endl;
str3.insert(3,str4);
cout<<"str3.insert(3,str4):"<<str3<<endl;
string str5("abcdef");
cout<<"str5:"<<str5<<endl;
str3.insert(3,str5,2,3);
cout<<"str3.insert(3,str5,2,3):"<<str3<<endl;
cout<<endl;
cout<<endl;
cout<<"str5:"<<str5<<endl;
str5.insert(4,"789456",3);
cout<<"str5.insert(4,\"789456\",3):"<<str5<<endl;
cout<<endl;
cout<<endl;
string str6("hanxu");
cout<<"str6:"<<str6<<endl;
str6.insert(3,"LOVE");
cout<<"str6.insert(3,\"LOVE\"):"<<str6<<endl;
cout<<endl;
cout<<endl;
string str7("smth");
cout<<"str7:"<<str7<<endl;
str7.insert(2,2,'o');
cout<<"str7.insert(2,'o',2):"<<str7<<endl;
return 0;
}
圖解:
三、模擬實現
//模擬實現c++標準庫中的string類
#include<iostream>
using namespace std;
#include<string.h>
class String
{
friend ostream& operator<<(ostream& os,String& s);
//類的預設成員函式
public:
String(const char* str="")//構造
:_capacity(strlen(str)+1)
,_sz(strlen(str))
,_str(new char[strlen(str)+1])
{
cout<<"String(const char* str=\"\");"<<endl;
strcpy(_str,str);
}
String(const String& s)//拷貝構造
:_capacity(strlen(s._str)+1)
,_sz(s._sz)
,_str(new char[strlen(s._str)+1])
{
cout<<"String(const Strig& s);"<<endl;
strcpy(_str,s._str);
}
/*String& operator=(String s)//賦值操作符過載---現代寫法(不用引用傳參)
{
cout<<"String& operator=(String s)"<<endl;
std::swap(_str,s._str);
_capacity=strlen(s._str)+1;
_sz=s._sz;
return *this;
}*/
String& operator=(const String& s)//賦值操作符過載---常規寫法(引用傳參)
{
cout<<"String& operator=(const String& s);"<<endl;
if (this!=&s)
{
delete[] _str;
_str=new char[strlen(s._str)+1];
strcpy(_str,s._str);
}
return *this;
}
~String()//析構
{
cout<<"~String();"<<endl;
if (NULL!=_str)
{
delete[] _str;
_str=NULL;
}
_capacity=0;
_sz=0;
}
//類的操作成員函式
public:
void push_back(const char c);//給物件後面新增一個字元
char& operator[] ( size_t pos );//取物件的下標元素
const char& operator[](size_t pos)const;//取字串的下標元素
String& operator+= ( const String& str );//給一個物件本身追加另一個物件
String& operator+= ( const char* s );//給一個物件本身追加一個字串
String& operator+= ( char c );//給一個物件本身追加一個字元
//以下函式的位置pos1都是從0計數開始
String& insert ( size_t pos1, const String& str );//在一個字串的pos1位置插入字串str
String& insert ( size_t pos1, const String& str, size_t pos2, size_t n );//在一個字串的pos1位置插入字串str前n位組成的字串
String& insert ( size_t pos1, const char* s, size_t n);//在一個字串的pos1位置插入字串s前n位組成的字串
String& insert ( size_t pos1, const char* s );//在一個字串的pos1位置插入字串s
String& insert ( size_t pos1, size_t n, char c );//在一個字串的pos1位置插入n個字元c
private:
//由於檢查並調整容量,只是在成員函式內部呼叫,所有經該函式定義為私有成員函式,不對外提供介面;體現c++的封裝特性,使該類變得安全
void CheakCapacty(size_t n)//檢查容量,並調整容量
{
if (_sz+1+n>=_capacity)
{
_capacity=_capacity*2+10;
char* tmp=new char[_capacity];
strcpy(tmp,_str);
delete[] _str;
_str=tmp;
}
}
private:
size_t _capacity;//字串當前的容量
size_t _sz;//字串實際的字元個數(不包含'\0')
char* _str;//字串
};
void String::push_back(const char c)//給字串後面新增一個字元c
{
CheakCapacty(1);
_str[_sz++]=c;
_str[_sz]='\0';
}
const char& String::operator[](size_t pos)const//取字串的下標元素
{
return _str[pos];
}
char& String::operator[](size_t pos)//取字串的下標元素
{
return _str[pos];
}
String& String::operator+= (const String& str )//給一個字串本身後面加上一個字串
{
CheakCapacty(strlen(str._str));
strcat(_str,str._str);//字串追加
_sz+=str._sz;
return *this;
}
String& String::operator+= ( const char* s )//給一個字串本身後面加上一個字串
{
CheakCapacty(strlen(s));
strcat(_str,s);
_sz+=strlen(s);
return *this;
}
String& String::operator+=( char c )//給一個字串本身後面加上一個字元
{
CheakCapacty(1);
_str[_sz++]=c;
_str[_sz]='\0';
return *this;
}
String& String::insert ( size_t pos1, const String& str )//從一個字串的pos位置開始插入字串str
{
if (_str==NULL||str._str==NULL)
{
return *this;
}
if (pos1>=0&&pos1<=strlen(_str))//'\0'位置也可以插入
{
CheakCapacty(strlen(str._str));//調整容量
char* tmp=new char[strlen(_str)-pos1+2];//開闢一段新空間儲存pos1位及其以後的字元
strcpy(tmp,_str+pos1);//把字串pos1位置及其後的字串賦值到臨時空間
strcpy(_str+pos1,str._str);//將要插入的字串複製到對應的其實位置
strcpy(_str+(pos1+strlen(str._str)),tmp);//將之前臨時變數儲存的原字串pos1位置之後的字串新增到插入以後的部分!
delete[] tmp;
}
return *this;
}
String& String::insert ( size_t pos1, const String& str, size_t pos2, size_t n )//在一個字串的pos1位置插入str字串的pos2位置及其後面的n個字元
{
if (_str==NULL||(str._str+pos2)==NULL)
{
return *this;
}
if (pos1>=0&&pos1<=strlen(_str)&&pos2>=0&&pos2<=strlen(str._str))
{
CheakCapacty(strlen(str._str));//調整容量
char* tmp=new char[strlen(_str)-pos1+2];//開闢一段新空間儲存pos1位及其以後的字元
strcpy(tmp,_str+pos1);//把字串pos1位置及其後的字串賦值到臨時空間
strncpy(_str+pos1,str._str+pos2,n);//將要插入的n個字元複製到對應的其實位置
strcpy(_str+(pos1+n),tmp);//將之前臨時變數儲存的原字串pos1位置之後的字串新增到插入以後的部分!
delete[] tmp;
}
return *this;
}
String& String::insert ( size_t pos1, const char* s, size_t n)//在一個字串的pos1位置插入字串s前n位組成的字串
{
if (_str==NULL||s+n==NULL)
{
return *this;
}
if (pos1>=0&&pos1<=strlen(_str))//'\0'位置也可以插入
{
CheakCapacty(n);//調整容量
char* tmp=new char[strlen(_str)-pos1+2];//開闢一段新空間儲存pos1位及其以後的字元
strcpy(tmp,_str+pos1);//把字串pos1位置及其後的字串賦值到臨時空間
strncpy(_str+pos1,s,n);//將要插入的字串複製到對應的其實位置
strcpy(_str+(pos1+n),tmp);//將之前臨時變數儲存的原字串pos1位置之後的字串新增到插入以後的部分!
delete[] tmp;
}
return *this;
}
String& String::insert ( size_t pos1, const char* s )//在一個字串的pos1位置插入字串s
{
if (_str==NULL||s==NULL)
{
return *this;
}
if (pos1>=0&&pos1<=strlen(_str))//'\0'位置也可以插入
{
CheakCapacty(strlen(s));//調整容量
char* tmp=new char[strlen(_str)-pos1+2];//開闢一段新空間儲存pos1位及其以後的字元
strcpy(tmp,_str+pos1);//把字串pos1位置及其後的字串拷貝到臨時空間
strcpy(_str+pos1,s);//將要插入的字串複製到對應的其實位置
strcpy(_str+(pos1+strlen(s)),tmp);//將之前臨時變數儲存的原字串pos1位置之後的字串新增到插入以後的部分!
delete[] tmp;
}
return *this;
}
String& String::insert ( size_t pos1, size_t n, char c )//在一個字串的pos1位置插入n個字元c
{
if (_str==NULL||n<=0)
{
return *this;
}
if (pos1>=0&&pos1<=strlen(_str))//'\0'位置也可以插入
{
CheakCapacty(n);//調整容量
char* tmp=new char[strlen(_str)-pos1+2];//開闢一段新空間儲存pos1位及其以後的字元
strcpy(tmp,_str+pos1);//把字串pos1位置及其後的字串拷貝到臨時空間
while(n--)
{
_str[pos1++]=c;
}
strcpy(_str+(pos1+n+1),tmp);
delete[] tmp;
}
return *this;
}
ostream& operator<<(ostream& os,String& s)
{
os<<s._str;
return os;
}
int main()
{
////1.四個預設建構函式測試
//String s1("1234");
//cout<<"s1:"<<s1<<endl;
//String s2("56789abcd");
//cout<<"s2:"<<s2<<endl;
////String s3;
////cout<<s3<<endl;
////s3=s2;
////cout<<s3<<endl;
// //2.push_back和operator[]測試
////cout<<s1[0]<<"->"<<s1[1]<<"->"<<s1[2]<<endl;
////s1.push_back('W');
////cout<<s1<<endl;
////3.operator+=()函式測試
////s1+=s2;//String& String::operator+= (const String& str )
// //s1+="abcd";//String& String::operator+= ( const char* s )
// //s1+='w';//String& String::operator+=( char c )
////cout<<s1<<endl;
////4.insert()函式測試
////s1=s1.insert(2,s2);
////cout<<"s1.insert(2,s2):"<<s1<<endl;
////s1=s1.insert(2,s2,3,4);
////cout<<"s1.insert(2,s2,3,4):"<<s1<<endl;
// //s2=s2.insert(4,"HKLM",2);
// //cout<<"s2=s2.insert(4,\"HKLM\",2):"<<s2<<endl;
//s2=s2.insert(5,"HMWKT");
//cout<<"s2=s2.insert(5,\"HMWKT\"):"<<s2<<endl;
////s2=s2.insert(5,3,'M');
////cout<<"s2=s2.insert(5,3,'M'):"<<s2<<endl;
String str1("12345");
cout<<"str1:"<<str1<<endl;
str1.push_back('w');
cout<<"str1.push_back('w'):"<<str1<<endl;
cout<<"str1[0]:"<<str1[0]<<"\nstr[1]:"<<str1[1]<<endl;
String str2("abcde");
cout<<"str2:"<<str2<<endl;
str1+=str2;
cout<<"str1+=str2:"<<str1<<endl;
str1+="www";
cout<<"str1+=www:"<<str1<<endl;
str1+='M';
cout<<"str1+='M':"<<str1<<endl;
cout<<endl;
cout<<endl;
String str3("123456");
String str4("www");
cout<<"str3:"<<str3<<"\nstr4:"<<str4<<endl;
str3.insert(3,str4);
cout<<"str3.insert(3,str4):"<<str3<<endl;
String str5("abcdef");
cout<<"str5:"<<str5<<endl;
str3.insert(3,str5,2,3);
cout<<"str3.insert(3,str5,2,3):"<<str3<<endl;
cout<<endl;
cout<<endl;
cout<<"str5:"<<str5<<endl;
str5.insert(4,"789456",3);
cout<<"str5.insert(4,\"789456\",3):"<<str5<<endl;
cout<<endl;
cout<<endl;
String str6("hanxu");
cout<<"str6:"<<str6<<endl;
str6.insert(3,"LOVE");
cout<<"str6.insert(3,\"LOVE\"):"<<str6<<endl;
cout<<endl;
cout<<endl;
String str7("smth");
cout<<"str7:"<<str7<<endl;
str7.insert(2,2,'o');
cout<<"str7.insert(2,'o',2):"<<str7<<endl;
return 0;
return 0;
}
三、模擬實現的測試程式碼和(1)中測試部分程式碼完全相同,執行結果也相同,證明本次模擬達到了c++標準庫的實現要求,模擬正確;
接下來的文章,用物件導向的思想,利用c++語言實現順序表和雙連結串列
相關文章
- string類的實現
- Proteus實現簡單51程式的設計與模擬
- 簡單實現.NET Hook與事件模擬Hook事件
- 【Tomcat】Tomcat工作原理及簡單模擬實現Tomcat
- 簡單的模擬(洛谷)
- sort回撥的簡單模擬
- 模擬簡單的動態代理
- 虛擬Dom與Diff的簡單實現
- 實現一個簡單的虛擬DOM
- 實戰模擬│單點登入 SSO 的實現
- 自實現string類
- 模擬實現簡易版shell
- promise的模擬實現Promise
- 簡單易用的前端模擬資料前端
- 進擊的模組化+webpack的簡單實現Web
- PAT-B 1012 數字分類【簡單模擬】
- 從module的簡單實現到模組化
- 簡單模擬死鎖
- javascript模擬new的實現JavaScript
- JavaScript 模擬new的實現JavaScript
- 透過簡單實現 PHP 請求模擬賺了 50 元PHP
- Bert文字分類實踐(一):實現一個簡單的分類模型文字分類模型
- strlen函式的模擬實現函式
- 1046 Shortest Distance(簡單模擬)
- AOP的簡單實現
- 簡單的 HashMap 實現HashMap
- 實現簡單的BitMap
- ArrayList的簡單實現
- 使用Mongoose類庫實現簡單的增刪改查Go
- qsort的模擬實現和練習
- 從零到有模擬實現一個Set類
- Python 超簡單實現人類面部情緒的識別Python
- SourceGenerator 使用姿勢(1):生成代理類,實現簡單的AOP
- 簡單的實現vue原理Vue
- 簡單的實現React原理React
- [Linux]簡單的shell實現Linux
- java實現簡單的JDBCJavaJDBC
- Java 簡單實現撲克牌抽象類Java抽象
- 使用 Raku 編寫簡單的文字識別模擬程式