模拟实现C++中的string类

本文主题

模拟实现C++标准库中的string类函数

我的string类实现的方式

实现了大部分string类类似的功能,有一部分没有实现,使用的是深拷贝的方式建立字符串,这个和VS中的库一样。
由于代码是按照自己的思路写的,所以会有很挫的代码,望大神指正。
VS采用的是PJ版本的库。P.J.Plauger版本是由P.J.Plauger开发,它继承HP版本,并不属于open source范畴,网上有人评价其可读性就是一坨屎。。。这个我太菜不好妄加评论。
而Linux的库则使用SGI版本,由Silicon Graphics Computer System, Inc公司发展,继承HP版本,这个版本使用的是string类实现方式是写时拷贝,就是仅拷贝的时候就共用一块空间,使用时再去另开空间修改。主要设计者仍然是STL之父Alexandar Stepanov,被Linux的C++编译器GCC所采用。SGI STL是开源软件,源码可读性非常高。

代码

github地址:点此下载

#include <iostream>

using namespace std;

class String
{
public:
    //Member Function

    //构造函数(constructor)
    String(const char* str = "")
    {
        int size = strlen(str);
        _str = new char[size + 1];
        _capacity = size + 1;
        _size = size;
        char* cur = _str;
        while (*cur++ = *str++);//strlen拷贝一下
    }

    String(const String& s)
        :_str(NULL)
    {
        //拷贝构造利用构造函数进行拷贝
        String temp(s._str);
        //交换临时和this的值,当出了作用域temp自动释放
        std::swap(_str, temp._str);
        _size = temp._size;
        _capacity = temp._capacity;
    }

    //析构函数(destructor)
    ~String()
    {
        //析构唯一要做的事情就是delete不能忘
        delete[] _str;
    }

    //operator=: String assignment
    String& operator=(const String& s)
    {
        if (this != &s)
        {
            //剑指offer第一题
            String temp = s;
            std::swap(_str, temp._str);
            _size = temp._size;
            _capacity = temp._capacity;
        }
        return *this;
    }

    String& operator=(const char ch)
    {
        clear();
        insert(0, ch);
        return *this;
    }

    String& operator=(const char* str)
    {
        clear();
        insert(0, str);
        return *this;
    }

    //Capacity相关函数

    //size: Return length of string
    size_t size() const
    {
        return _size;
    }

    //length: Return length of string
    size_t length() const
    {
        return _size;
    }

    //resize: Resize string
    void resize(size_t size, char c)
    {
        //直接将字符串长度的最后一位置为'\0'就好了
        if (size >= _size)
        {
            //长度不能超过字符串
            size = _size;
        }
        *(_str + size) = '\0';
        char* cur = _str;
        while (*cur)
        {
            *cur++ = c;
        }
    }

    void resize(const size_t size)
    {
        if (size < _size)
        {
            *(_str + size) = '\0';
        }
    }

    //capacity: Return size of allocated storage
    size_t capacity()
    {
        return _capacity;
    }

    //reserve: Request a change in capacity
    void reserve(const size_t size)
    {
        expand(size);
    }

    //clear: Clear string
    void clear()
    {
        *(_str + 0) = '\0';
        _size = 0;
    }

    //empty: Test if string is empty
    bool empty() const
    {
        if (_size == 0)
        {
            return true;
        }
        return false;
    }

    //Element access

    //operator[]: Get character of string
    char& operator[](const size_t pos) const
    {
        if (pos >= _size)
        {
            return *(_str + _size);
        }
        return *(_str + pos);
    }

    //at: Get character in string
    char& at(const size_t pos) const
    {
        return (*this)[pos];
    }

    //Modifiers

    //operator+=: Append to string
    String& operator+=(const char* str)
    {
        return insert(_size, str);
    }

    String& operator+=(const String& s)
    {
        return insert(_size, s._str);
    }

    String& operator+=(const char ch)
    {
        return insert(_size, ch);
    }

    //append: Append to string
    String& append(const char* str)
    {
        return insert(_size, str);
    }

    String& append(const char ch)
    {
        return insert(_size, ch);
    }

    String& append(const String& s)
    {
        return insert(_size, s._str);
    }

    //push_back: Append character to string
    String& push_back(const char ch)
    {
        return insert(_size, ch);
    }

    //insert: Insert into string
    String& insert(const size_t pos, const char* str)
    {
        if (pos <= _size)
        {
            int len = strlen(str);
            //检查空间是否足够
            if (_size + len >= _capacity)
            {
                expand(_size + len);
            }
            const char* end = _str + _size;
            int i = 0;
            for (i = _size + len; i >= (int)pos + len; i--)
            {
                //拷贝目标串
                *(_str + i) = *end--;
            }
            end = str + len - 1;
            for (; i >= (int)pos; i--)
            {
                //拷贝后半部分串
                *(_str + i) = *end--;
            }
            _size = _size + len;
        }
        return *this;
    }

    String& insert(const size_t pos, const char ch)
    {
        //把一个字符变成一个字符的字符串,然后调用插入
        char* str = new char[2];
        *(str + 0) = ch;
        *(str + 1) = '\0';
        insert(pos, str);
        delete[] str;
        return *this;
    }

    String& insert(const String& s)
    {
        //继续赋用
        return insert(_size, s._str);
    }

    //erase: Erase characters from string
    String& erase(const size_t pos, const size_t count = 1)
    {
        if (pos <= _size)
        {
            //抹去长度超过字符串长度,直接移动尾
            if (pos + count >= _size)
            {
                *(_str + pos) = '\0';
                _size = pos;
            }
            else
            {
                //直接拷贝后半部分没有删除的字符串
                char* front = _str + pos;
                char* back = _str + pos + count;
                while (*front++ = *back++);
                _size -= count;
            }
        }
        return *this;
    }

    //replace: Replace portion of string
    String& replace(const size_t pos, size_t len, const char* str)
    {
        //检查空间
        if (pos + len >= _capacity)
        {
            expand(pos + len);
        }
        for (int i = 0; i < len; i++)
        {
            *(_str + pos + i) = *(str + i);
        }
        if (pos + len > _size)
        {
            //长度超过原串,尾部加'\0'
            _size = pos + len;
            *(_str + _size) = '\0';
        }
        return *this;
    }

    String& replace(const size_t pos, size_t len, const String& s)
    {
        return replace(pos, len, s._str);
    }

    //swap: Swap string values
    void swap(String& s)
    {
        //交换两个类
        std::swap(_str, s._str);
        std::swap(_size, s._size);
        std::swap(_capacity, s._capacity);
    }

    //pop_back: Delete last character
    String& pop_back()
    {
        return erase(_size - 1);
    }

    //String operations

    //c_str: Get C string equivalent
    char* c_str()
    {
        return _str;
    }

    //find: Find content in string
    size_t find(const char* s, size_t pos = 0) const
    {
        //查找子串,和strstr类似
        const char* start = NULL;
        const char* cur = _str;
        const char* s_cur = s;
        while (*cur)
        {
            start = cur;
            if (*cur == *s)
            {
                s_cur = s;
                while (*cur == *s_cur && *cur)
                {
                    cur++, s_cur++;
                }
                if (*s_cur == '\0')
                {
                    return start - _str;
                }
            }
            cur = ++start;
        }
        return npos;
    }

    size_t find(char c, size_t pos = 0) const
    {
        //找第一个出现的字母
        const char* cur = _str;
        while (*cur)
        {
            if (*cur == c)
            {
                return cur - _str;
            }
            cur++;
        }
        return std::string::npos;
    }

    //substr: Generate substring
    String substr(size_t pos = 0, size_t len = npos) const
    {
        //截断字符串
        int length = len;
        if (len = npos)
        {
            length = _size - pos;
        }
        char *str = new char[length + 1];
        for (int i = 0; i < length; i++)
        {
            *(str + i) = *(_str + pos + i);
        }
        *(str + length) = '\0';
        String temp = str;
        delete[] str;
        return temp;
    }

    String operator+(const String& s)
    {
        String temp = *this;
        temp.append(s._str);
        return temp;
    }

    friend ostream& operator<<(ostream& out, String& s);
private:
    void expand(size_t size)
    {
        //扩大空间
        char* temp = new char[size + 1];
        char* temp_cur = temp;
        char* _str_cur = _str;
        while (*temp_cur++ = *_str_cur++);
        std::swap(_str, temp);
        _capacity = size + 1;
    }

private:
    char* _str;
    int _size;
    int _capacity;

    static size_t npos;
};

size_t String::npos = -1;

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


//Member function就不测了,每个函数都要用

//测试空间函数相关
void testCapacity()
{
    String s1 = "hello world";
    cout << "size->" << s1.size() << "  expect->11" << endl;
    cout << "length->" << s1.length() << "  expect->11" << endl;
    s1.resize(5);//预期结果->hello
    cout << "resize->" << s1 << "  expect->hello" << endl;
    cout << "capacity->" << s1.capacity() << "  expect->12" << endl;
    s1.reserve(1000);
    cout << "reserve->" << s1.capacity() << "  expect->1000 + 1" << endl;
    s1.clear();
    cout << "clear->" << s1 << "  expect->" << endl;
    cout << "clear->" << s1.size() << "  expect->0" << endl;
    cout << "empty->" << s1.empty() << "  expect->1" << endl;
}

void testElementAccess()
{
    //预期输出->hello world
    String s1 = "hello world";
    cout << "s1->" << s1 << endl;
    cout << "operator[]:s1[0]->" << s1[0] << "  expect->h" << endl;
    cout << "s1.at(0)->" << s1.at(0) << "  expect->h" << endl;
}

void testModifiers()
{
    String s1 = "hello ";
    String s2 = "world";

    //operator+=
    s1 += s2;
    cout << "s1 += s2->" << s1 << "  expect->hello world" << endl;

    //apend
    s1.clear();
    s1.append("hello ");
    s1.append(s2);
    cout << "append->" << s1 << "  expect->hello world" << endl;

    //pop_back and push_back
    s1.pop_back();
    s1.push_back('d');
    cout << "pop_back and push_back->" << s1 << "  expect->hello world" << endl;

    //insert
    s1 = s2;
    s1.insert(0, "hello ");
    cout << "insert->" << s1 << "  expect->hello world" << endl;

    //erase
    s1.erase(0, 11);
    cout << "erase->" << s1 << "  expect->" << endl;

    //replace
    s1 = "hello";
    s1.replace(0, 8, "my world");
    cout << "replace->" << s1 << "  expect->my world" << endl;

    //swap
    s1.swap(s2);
    cout << "swap->" << s1 << "  expect->world" << endl;
}

void testStringOperations()
{
    String s1 = "hello world";

    //c_str
    char* temp = s1.c_str();
    cout << "c_str->" << temp << "  expect->hello world" << endl;

    //find
    cout << "find->" << s1.find("ello") << "  expect->1" << endl;

    //substr
    String s2 = s1.substr(6, 5);
    cout << "substr->" << s2 << "  expect->world" << endl;
}

int main()
{
    testStringOperations();
    system("pause");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Boring_Wednesday/article/details/80767148