(入门自用)--C++---模拟实现string--深浅拷贝

深浅拷贝

浅拷贝

string s1("hello world");

string s2(s1);

 深拷贝

第一种写法:

string(const string& s)
    :_str(new char[s.capacity+1])
    ,_size(s.szie())
    ,_capacity(s.capacity())
    {
        strcpy(_str,s._str);
    }

//赋值时也会出现浅拷贝问题
//运算符重载  s1=s3
string& operator=(const string& s)
{
    if(this!=&s)//避免自己给自己赋值
    {
        char*tmp=new[s._capacity+1];
        strcpy(tmp,s._str);
        delete[] _str;//释放赋值前s1的空间
        _capacity=s._capacity;
        _size=s._size;
        _str=tmp; 
    }
    return *this;
} 

第二种写法:

//拷贝构造
//初始化列表的意义是 不让tmp里面都是随机值从而导致析构无法正常运行
string(const string&s)
    :_str(nullptr)
    ,_size(0)
    ,_capacity(0)
{
    string tmp(s._str);//调的是构造函数 会根据s._str的大小填充_size _capacity
    swap(_str,tmp._str);
    swap(_size,tmp._size);
    swap(_capacity,tmp._capacity);
    //swap(tmp);
}

//赋值
string& operator=(const string& s)
{
    if(this!=&s)
    {
        //string tmp(s._str);
        string tmp(s);//这里已经写好了拷贝构造 用什么都可以
        swap(_str,tmp._str);
        swap(_size,tmp._size);
        swap(_capacity,tmp._capacity);
        //swap(tmp);
    }
    return *this;
}

//赋值写法2
string& operator=(string s)
{
    swap(s);
    return *this;
}

//上述的swap可以复用

void swap(string& tmp)
{    
    //加::的意思是调用的是全局的swap函数 不是string类里面的 刚写的这个swap函数
    //不写:: 调用时会现在类里面找 只能找到刚写的这个函数 而参数不匹配而发生报错
    ::swap(_str,tmp._str);
    ::swap(_size,tmp._size);
    ::swap(_capacity,tmp._capacity);
}

s1.swap(s2);//调用类里面的swap 这里成员全部交换

swap(s1,s2);//调用全局的swap 这里成员全部交换但srt的地址就不再是之前的两个中的了

构造析构

string(const char* str = "")
{
    _size = strlen(str);
    _capacity = _size;
    _str = new char[_capacity + 1];
    strcpy(_str, str);
}
~string()
{
	delete[] _str;
	_str = nullptr;
	_size = _capacity = 0;
}

增删查改

插入

//扩容    ----size---代表存了几个数据 对应最后一个位置的下一个位置的下标
void reserve(size_t n)//这里n的含义是我需要存储的数据个数
{
    if(n>capacity)
    {
        char*tmp=new char[n+1];//留一个给\0
        strcpy(tmp,_str);
        delete[] _str;
        _str=tmp;
        _capacity=n;
    }
}

//插入字符
void push_back(char ch)
{
    if(_size==_capacity)
    {
        reserve(_capacity==0?4;_capacity*2)//这里string构造函数中 
                                        //_capacity的初始值如果不是0可以不用三目
    }
    _str[_size]=ch;
    _size++;
    _str[_size]='\0';//这里一定要处理    
}

//插入字符的 +=运算符重载
string& operator+=(char ch)
{
    push_back(ch);
    return *this;
}

//插入字符串
void append(const char*str)
{
    size_t len=strlen(str);
    //满了扩容
    if(_size+len>_capacity)
    {
        reserve(_size+len);
    }
    strcpy(_str+size,str);//'\0'也拷贝过去
    _size+=len;

}
//插入字符串的+=运算符重载
string& operator+=(const char*str)
{
    append(str);
    renturn *this;
}



// insert
string& insert(size_pos,char ch)//在pos位置插入一个字符
{
    assert(pos<=_size);
    if(_size==_capacity)
    {
        reserve(_capacity==0?4:_capacity*2);
    }
    //移数据
    size_t end=_size+1;
    while(end>pos)
    {
        _str[end]=_str[end-1];
        --end;
    }
    _str[pos]=ch;
    ++size;
    return *this;    
}
string& insert(size_t pos,const char*str)//在pos位置插入一个字符串
{
    assert(pos<=_size);
    size_t len=strlen(str);
    if(_size+len>_capacity)
    {
        reserve(_capacity==0?4:_capacity*2);
    }
    size_t end=_size+len;
    while(end>=pos+len)
    {
        _str[end]=_str[end-len];
        --end;
    }
    strncpy(_str+pos,str,len);//strcpy会把\0也拷贝过来
    _size+=len;
    return *this;
}

删除

class string
{
public:
    void earse(size_t pos,size_t len= npos)//删除
    {
        assert(pos<_size);
        if(len==npos||pos+len>=_size)//删的值很大
        {
            _str[pos]='\0';
            _size=pos;
        }
        else
        {
            strcpy(_str+pos,_str+pos+len);
            _size-=len;
        }
    }

static size_t npos;//声明
private:
size_t _capacity;
size_t _size;
char*_str;

}
size_t string::npos=-1;//定义

创建补充 也可以插入删除数据

//开空间+初始化
void resize(size_t n,char ch ='\0')//改变size 默认放\0
{
    if(n>_size)
    {
        reserve(n);
        for(size_t i=_size;i<n;i++)
        {
            _str[i]=ch;
        }
        _str[n]='\0';
        _size=n;
    }
    else
    {
        _str[n]='\0';
        _size=n;
    }
}

查找

class string
{
public:
    size_t find(char ch,size_t pos=0) const //pos为缺省值 不给就从零开始找
    {
        assetr(pos<_size);
        for(size_t i=pos;i<_size;i++)
        {
            if(ch==_str[i])
            {
                return i;
            }
        }
        return npos;
    }
    size_t find(const char*sub,size_t pos=0)const
    {
        assert(sub);
        assert(pos<_size);
        const char*ptr=strstr(_str+pos,sub);//C自带函数 strstr(起始位置,关键词)
                                            //返回值为指针
        if(ptr==nullptr)
            return npos;
        else
            return ptr-_str;//指针减指针得下标
    }

static size_t npos;
private:
size_t _capacity;
size_t _size;
char*_str;
}
size_t string::npos=-1;//定义

截取

string substr(size_t pos,size_t len = npos) const
{
    assert(pos<_size);
    size_t reallen=len;
    if(len==npos||pos+len>_size)//截完了
    {
        reallen=_size-pos;
    }
    string sub;//存放截取数据做返回值的
    for(size_t i=0;i<reallen;i++)
    {
        sub+=_srt[pos+i];
    }
    return sub;
}

流插入 流提取

class string
{
public:
    size_t size() const
    {
        return _size;
    }
    void clear()
    {
        _str[0]='\0';
        _size=0;
    }
private:
size_t _capacity;
size_t _size;
char*_str;
};
ostream& operator<<(ostream& out, const string& s)
{
    for(size_t i=0;i<s.size();i++)
    {
        out<<s[i];
    }
}

istream& operator>>(istream& in,string& s) 
{
    char ch;
    //in>>ch;会忽略空格和换行 导致不能结束输入
    ch=in.get() 
    while(ch!=' '&&ch!='\n')//输入字符串很长时不断加等 扩容繁琐
    {
        s+=ch;
        ch=in.get();
    }
    return in;
}
//流插入的优化
istream& operator>>(istream& in,string& s)//输入字符串时先存在其他地方再加等减少扩容
{        
    s.clear();
    char ch;
    ch=in.get();
    const size_t N=32;
    char buff[N];//存在于栈上 出作用域自动销毁
    size_t i=0; 
    while(ch!=' '&&ch!='\n')
    {
        buff[i++]=ch;
        if(i==N-1)//存满了
        {
            buff[i]='\0';
            s+=buff;
            i=0;
        }
        ch=in.get();//输入
    }
    buff[i]='\0';
    s+=buff;
    return in;
}

大小比较

bool operator>(const string& s) const
{
    return strcmp(_str,s._str)>0;
}
bool operator==(const string& s)const
{
    return strcmp(_str,s._str)==0;
}
bool operator>=(const string& s) const
{
    return *this>s||*this==s;
}
bool operator<=(const string& s) const
{
    return !*this>s;
}
bool operator<(const string& s) const
{
    return !*this>=s;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值