C++容器string类

C++中对于字符串的处理进行了特殊的封装,使得这个容器既具有普通容器的性质,又能对于字符串进行处理。

下面对一些常用的string接口进行说明。

1.构造函数

首先来看string的构造函数。

string()//构造空的string类对象
string(const char* s) //利用C-string来构造类对象
string(const string& s)//拷贝构造

2.常用容量操作

size_t size() const;//返回字符串的有效长度
bool empty() const;//判断字符串是否为空
void clear();//清空有效字符串
void reserve (size_t n = 0);//为字符串申请空间

//resize构成函数重载,申请空间将多余的空间初始化为c
void resize (size_t n);
void resize (size_t n, char c);

(1)这里值得一提的是size()和length ()底层实现是一样的,但是实现size()出现的原因是为了和其他容器保持一致。一般而言使用size()。

(2)clear只清楚内容,不会清楚底层空间。

3.string类对象的访问

char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;
//string中重载了[]使得能够像数组一样访问元素

iterator begin();
const_iterator begin() const;
//string中定义了begin函数返回字符串首个字符的迭代器,在这里可以认为是指针

iterator end();
const_iterator end() const;
//end()与begin()相反end是返回最后一个元素的迭代器

reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
//反向迭代器,rbegin()就是返回最后一个元素的迭代器

reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
//反向迭代器,rend()就是返回第一个元素的迭代器

4.string常用修改操作

void push_back (char c);//字符串尾插字符

//重载+=能够在尾部添加字符
string& operator+= (const string& str);
string& operator+= (const char* s);
string& operator+= (char c);

//返回一个C格式的字符串
const char* c_str() const noexcept;

//从pos位置开始返回长度为len个字符
//这里的npos是一个静态成员变量,可以理解为字符串的末尾
string substr (size_t pos = 0, size_t len = npos) const;

5.string类的非成员函数

//流插入
istream& operator>> (istream& is, string& str);

//流提取
istream& operator<< (istream& is, string& str);

//获取一行字符串
istream& getline (istream& is, string& str, char delim);
istream& getline (istream& is, string& str);

最后可以大致模拟实现一个string容器

    class string
    {
    public:
        //这里定义string的正向迭代器
        //对于string来说,迭代器就可以看作是指针
        //const迭代器也是如此
        typedef char* iterator;
        typedef const char* const_iterator;

        iterator begin() { return _str; }//返回头指针
        const_iterator begin() const { return _str; }//返回const头指针

        iterator end() { return _str + _size; }//返回尾指针
        const_iterator end() const { return _str + _size; }//返回const尾指针

        //构造函数,这里初始化列表构造直接深拷贝
        string(const char* str = "")
            : _size(strlen(str))
            , _capacity(_size)
            , _str(new char[_capacity + 1])
        {
            memcpy(_str, str, _size + 1);
        }
        
        //拷贝构造
        string(const string& s)
            : _size(s._size)
            , _capacity(s._capacity)
            , _str(new char[_capacity + 1])
        {
            memcpy(_str, s._str, _size + 1);
        }
        
        
        void swap(string& s)
        {
            std::swap(_str, s._str);//交换两个字符串头指针的指向
            std::swap(_size, s._size);
            std::swap(_capacity, s._capacity);
        }
        
        //这里是传统写法进行赋值重载
        //string& operator=(const string& s)
        //{
        //    if (this != &s)//不是自己给自己赋值
        //    {
        //        //char* temp = new char[s._capacity + 1];//先开空间,拷贝,然后旧的空间可以释放,在指向新的空间
        //        //memcpy(temp, s._str, s._size);
        //        //delete[] _str;
        //        //_str = temp;//首元素地址

        //        //_size = s._size;
        //        //_capacity = s._capacity;

        //        string temp(s);//调用拷贝构造
        //        //std::swap(_str, temp._str);//交换两个字符串头指针的指向
        //        //std::swap(_size, temp._size);
        //        //std::swap(_capacity, temp._capacity);

        //        //this->swap(temp)
        //        swap(temp);
        //    }
        //    return *this;
        //}
        
        //现代写法进行赋值重载
        //传引用返回,如果不传引用this生命周期结束就销毁
        string& operator=(string& s)
        {
            swap(s);
            return *this;
        }

        ~string()
        {
            delete[] _str;
        }
        
        //转换为C格式的字符
        const char* c_str() const { return _str; }

        //返回当前字符串大小
        size_t size() const { return _size; }

        //[]重载和const[]重载
        char& operator[](size_t pos) { assert(pos < _size); return _str[pos]; }
        const char& operator[](size_t pos) const { assert(pos < _size); return _str[pos];}

        //开辟空间,扩容
        void reserve(size_t n)
        {
            if (n > _capacity)
            {
                char* temp = new char[n + 1];
                memcpy(temp, _str, _size + 1);
                delete[] _str;
                _str = temp;
                _capacity = n;
            }
        }
        
        //开辟空间初始化,可以复用reserve()
        void resize(size_t n, char c = '\0')
        {
            if (_size > n)
            {
                _size = n;
                _str[_size] = '\0';
            }
            else
            {
                reserve(n);
                for (size_t i = _size; i < n; i++)
                {
                    _str[i] = c;
                }
                _size = n;
                _str[_size] = '\0';
            }
        }

        //尾插一个字符,需要注意的是末尾的\0
        void push_back(char ch)
        {
            if (_size == _capacity)
            {
                size_t new_capacity = _capacity == 0 ? 4 : _capacity * 2;
                reserve(new_capacity);
            }
            _str[_size] = ch;
            _size++;
            _str[_size] = '\0';
        }
        
        //在字符串后面追加一个字符串
        //这里需要注意扩容
        void append(const char* str)
        {
            size_t len = strlen(str);
            if (_size + len > _capacity)
            {
                reserve(_size + len);
            }
            memcpy(_str + _size, str, len + 1);
            _size += len;
        }
        
        //+=重载,可以复用push_back()
        //这里是添加一个字符
        string& operator+=(char ch)
        {
            push_back(ch);
            return *this;
        }

        //+=重载,可以复用append()
        //这里是添加一个字符串
        string& operator+=(const char* str)
        {
            append(str);
            return *this;
        }

        //在pos位置插入n个数据,这里需要注意移动数据
        void insert(size_t pos, size_t n, char ch)
        {
            assert(pos <= _size);
            if (_size + n > _capacity)
            {
                reserve(_size + n);
            }
            size_t end = _size;
            while (end >= pos)
            {
                _str[end + n] = _str[end];
                end--;
            }
            for (size_t i = 0; i < n; i++)
            {
                _str[pos + i] = ch;
            }
            _size += n;
            _str[_size] = '\0';
        }
        
        //在pos位置插入字符串
        void insert(size_t pos, const char* str)
        {
            assert(pos <= _size);
            size_t len = strlen(str);
            if (_size + len > _capacity)
            {
                reserve(_size + len);
            }
            size_t end = _size;
            while (end >= pos)
            {
                _str[end + len] = _str[end];
                end--;
            }
            memcpy(_str + pos, str, len);
            _size += len;
            _str[_size] = '\0';
        }
        
        //从pos位置开始删除len长度的字符
        void erase(size_t pos, size_t len = npos)
        {
            assert(pos <= _size);
            if (len == npos || pos + len >= _size)
            {
                _str[pos] = '\0';
                _size = pos;
            }
            else
            {
                size_t end = pos + len;
                while (end < _size)
                {
                    _str[pos++] = _str[end++];
                }
                _size -= len;
                _str[_size] = '\0';
            }
        }
        
        //查找pos位置的字符
        size_t find(char ch, size_t pos = 0)
        {
            assert(pos <= _size);
            for (size_t i = pos; i < _size; i++)
            {
                if (_str[i] == ch)
                {
                    return i;
                }
            }
            return npos;
        }

        //查找字符串,这里可以使用C语言中的strstr()查找子串
        size_t find(const char* str, size_t pos = 0)
        {
            assert(pos <= _size);
            const char* ptr = strstr(_str + pos, str);
            if (ptr)
            {
                return ptr - _str;
            }
            return npos;
        }
        
        //从pos位置开始截取len长度的字符串
        string substr(size_t pos = 0, size_t len = npos)
        {
            size_t n = len;
            if (len == npos || pos + len > _size)
            {
                n = _size - pos;
            }
            string temp;
            temp.reserve(n);
            memcpy(temp._str, _str + pos, n);
            temp._size = n;
            temp._str[n] = '\0';
            return temp;
        }   
        
        //清除内容
        void clear()
        {
            _size = 0;
            _str[0] = '\0';
        }
        
        //这里可以直接使用C语言中的memcmp()
        bool operator<(const string s) const
        {
            //size_t i1 = 0;
            //size_t i2 = 0;
            //while (i1 < _size && i2 < s._size)
            //{
            //    if (_str[i1] < s._str[i2])
            //    {
            //        return true;
            //    }
            //    else if (_str[i1] > s._str[i2])
            //    {
            //        return false;
            //    }
            //    else
            //    {
            //        ++i1;
            //        ++i2;
            //    }
            //}
            //if (i1 == _size && i2 != s._size)
            //{
            //    return true;
            //}
            //else
            //{
            //    return false;
            //}

            //hello hello --false
            //helloxx hello --- fasle
            //hello helloxx --- true
            bool ret = memcmp(_str, s._str, _size < s._size ? _size : s._size);//按照长度小的进行比较
            return ret == 0 ? _size < s._size : ret < 0;
        }
        
        //这里也是使用C语言的memcmp()
        bool operator==(const string& s) const
        {
           return _size == s._size && memcmp(_str, s._str, _size) == 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);
        }

        bool operator!=(const string& s) const
        {
            return !(*this == s);
        }

    private:
        size_t _size;//当前string中有多少个元素
        size_t _capacity;//空间
        char* _str;

        static const size_t npos;
    };

    const size_t string::npos = -1;

    // 重载流插入运算符
    std::ostream& operator<<(std::ostream& out, const string& s)
    {
        for (size_t i = 0; i < s.size(); i++)
        {
            out << s[i];
        }
        return out;
    }

    // 重载流提取运算符
    std::istream& operator>>(std::istream& in, string& s)
    {
        s.clear();
        char ch;
        while (in.get(ch) && !isspace(ch))
        {
            s.push_back(ch);
        }
        return in;
    }

你可能感兴趣的:(c++,开发语言)