C++ String类的实现

前面我们已经学过运算符重载、友元函数、动态内存开辟以及关于C++深浅拷贝的问题,综合上面所提到的知识,我们实现一下String类的基本功能

数据结构以及输入输出运算符的重载
class String
{
    friend ostream& operator<<(ostream& out, const String& s);
    friend istream& operator>>(istream& in, String& s);
public:
private:
    char* _str;
    size_t _sz;
    size_t _capacity;
};

ostream& operator<<(ostream& out, const String& s)
{
    out << s._str;
    return out;
}

istream& operator>>(istream& in, String& s)
{
    in >> s._str;
    return in;
}
构造和析构
//构造函数
String(char* s="")
        :_str(new char[strlen(s)+1])
        ,_sz(strlen(s))
        ,_capacity(strlen(s)+1)
    {
        strcpy(_str, s);
    }

//析构函数
~String()
    {
        if (_str)
        {
            delete[] _str;
            _str = NULL;
            _sz = 0;
            _capacity = 0;
        }
    }
  • 析构函数一定要判空,delete一个不存在的对象是非法的
拷贝构造&&赋值运算符重载
  • String类中有指针成员,所以在拷贝的时候要避免简单赋值浅拷贝带来的问题,我们使用深拷贝的方法来实现拷贝构造函数和赋值运算符的重载
    //拷贝构造函数(深拷贝的传统写法)
    String(const String& s)
        :_str(new char[strlen(s._str) + 1])
    {
        if (this != &s)
        {
            strcpy(_str, s._str);
            _sz = s._sz;
            _capacity = s._capacity;
        }
    }

    void Swap(String& s)
    {
        swap(_str, s._str);
        swap(_sz, s._sz);
        swap(_capacity, s._capacity);
    }

    //拷贝构造(深拷贝的现代写法)
    String(const String& s)
        :_str(NULL)
        , _sz(0)
        , _capacity(0)
    {
        String tmp=s._str;
        this->Swap(tmp);
    }
//赋值运算符重载的传统写法
    String& operator=(const String& s)
    {
        if (this != &s)
        {
            char* tmp = new char[strlen(s._str) + 1];
            strcpy(tmp, s._str);
            _sz = s._sz;
            _capacity = s._capacity;
        }
        return* this;
    }

    //赋值运算符重载的现代写法1
    String& operator=(const String& s)
    {
        String tmp = s._str;
        this->Swap(tmp);
        return *this;
    }

    //赋值运算符的现代写法2
    String& operator=(String& s)
    {
        s.Swap(*this);
        return *this;
    }
  • 我们先来简单的测试一下:
    这里写图片描述
增删查改
char operator[](int sz)
    {
        return _str[sz];
    }

    //检测容量是否够用,不够则重新开辟
    void CheckCapacity(int sz)
    {
        int tmp = 0;
        if (_capacity < _sz + sz + 1)
        {
            tmp = (2 * _capacity)>(_capacity + sz) ? (2 * _capacity) : (_capacity + sz);
            char* str = new char[_capacity];
            strcpy(str, _str);
            delete[] _str;
            char* _str = new char[tmp];
            strcpy(_str, str);
            _capacity = tmp;
        }
    }

    void PushBack(char ch)
    {
        CheckCapacity(1);
        _str[_sz++] = ch;
        _str[_sz] = '\0';
    }

    void PushBack(const char* str)
    {
        size_t len = strlen(str);
        CheckCapacity(len);
        strcpy(_str + _sz, str);
        _sz += len;
    }

    void PushFront(char ch)
    {
        CheckCapacity(1);
        int end = _sz;
        while (end >= 0)
        {
            _str[end + 1] = _str[end];
            end--;
        }
        _str[0] = ch;
    }

    void Insert(size_t pos, char ch)
    {
        CheckCapacity(1);
        int end = _sz;
        while (end >= pos)
        {
            _str[end + 1] = _str[end];
            --end;
        }
        _str[pos] = ch;
        ++_sz;
    }

    void Insert(size_t pos, const char* str)
    {
        assert(str);
        size_t len = strlen(str);
        CheckCapacity(len);
        int end = _sz;
        while (end >= (int)pos)
        {
            _str[end + len] = _str[end];
            end--;
        }
        while (*str)
        {
            _str[pos++] = *str++;
        }
        _sz += len;
    }

    void Insert(size_t pos,const char* s)
    {
        assert(pos < _size);
        assert(s);
        int len = strlen(s);
        CheckCapacity(len);
        int end = _size;
        while (end >= pos)
        {
            _str[end + len] = _str[end];
            end--;
        }
        while (*s)
        {
            _str[pos++] = *s++;
        }
        _size += len;
    }

    //使用strcpy会将'\0'拷贝过去,也可使用使用插入字符串的方法
    //void PushFront(const char* str)
    //{
    //  Insert(0, str);
    //}

    //删除指定位置后的所有字符
    void Erase(int pos)
    {
        assert(pos < _size);
        //_str[pos + 1] = '\0';  //虽然删除了字符但是_size的大小没有发生变化
        while (_size >= pos+1)
        {
            _str[_size-1] = _str[_size];
            _size--;
        }
    }

    //删除指定位置后的n个字符
    void Erase(size_t pos, size_t count)
    {
        if (pos + count >= _sz)
        {
            _str[pos] = '\0';
            _sz = pos;
        }
        else
        {
            strcpy(_str + pos, _str + pos + count);
            _sz = count;
        }
    }

    size_t Find(char ch) const
    {
        int pos = 0;
        do
        {
            if (_str[pos] == ch)
            {
                return pos;
            }
            pos++;
        } while (pos);
        return pos;
    }

    size_t Find(char* s)
    {
        int pos = 0;
        int tmp = 0;
        int ret = 0;
        while (_str[tmp] != '\0')
        {
            pos = tmp;
            while (_str[pos] == s[ret])
            {
                pos++;
                ret++;
            }//_str[pos]!=s[ret]
            if (s[ret] == '\0')
            {
                return tmp;
            }
            else
            {
                tmp++;
                ret = 0;
            }
        }
    }

    size_t Size()
    {
        return strlen(_str);
    }

    size_t Capacity()
    {
        return strlen(_str) + 1;
    }
常用运算符重载
    bool operator==(const String& s) const
    {
        return strcmp(_str, s._str) == 0;
    }

    bool operator!=(const String& s) const
    {
        return !(_str == s._str);
    }

    bool operator<(const String& s) const
    {
        return strcmp(_str, s._str) < 0;
    }

    bool operator>=(const String& s) const
    {
        return !(_str < s._str);
    }

    bool operator>(const String& s) const
    {
        return strcmp(_str, s._str)>0;
    }

    bool operator<=(const String& s) const 
    {
        return !(_str > s._str);
    }

    String& operator+=(const String& s)
    {
        CheckCapacity(strlen(s._str));
        strcat(_str, s._str);
        return *this;
    }

猜你喜欢

转载自blog.csdn.net/aurora_pole/article/details/80234846