简单的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++语言实现顺序表和双链表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值