综述: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++语言实现顺序表和双链表