string类的简单模拟实现

头文件:

#pragma once
#include<iostream>
#include<assert.h>
#include<string.h>

namespace tc
{

    class string

    {

        friend std::ostream& operator<<(std::ostream& _cout, const tc::string& s)
        {
            iterator it = s.begin();
            while (it != s.end())
            {
                _cout << *it;
                ++it;
            }

            return _cout;
        }

    public:

        typedef char* iterator;//简单的把迭代器理解为指针;

    public:

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

        ///
        string(const string& s)
            :_str(nullptr), _size(0), _capacity(0)
        {
            _size = strlen(s._str);
            _capacity = _size;
            string tmp(s._str);
            std::swap(tmp._str, _str);
        }
        ///
        string& operator=(const string& s)
        {
            string tmp(s);
            std::swap(_str, tmp._str);
            return *this;
        }

        ~string()
        {
            if (_str)
            {

                delete[] _str;
                _str = nullptr;
                _capacity = 0;
                _size = 0;
            }

        }



        //

        // iterator

        iterator begin() const
        {
            return _str;
        }
        iterator end() const
        {
            return (_str + _size);
        }



        /

        // modify

        void push_back(char c)
        {
            if (_size == _capacity)
            {
                reserve(_capacity * 1.5 + 3);
            }
            _str[_size] = c;
            ++_size;
            _str[_size] = '\0';
        }

        string& operator+=(char c)
        {
            push_back(c);
            return *this;
        }

        string& operator+=(const string& s)
        {
            *this += s._str;
            return *this;
        }
        string& operator+=(const char* str)
        {
            int newcapacity = _size + strlen(str);
            reserve(newcapacity);
            strcat(_str, str);
            _size = newcapacity;

            *(_str + _size) = '\0';
            return *this;
        }

        string& append(const char* str)
        {
            *this += str;
            return *this;
        }

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

        void clear()
        {
            _size = 0;
            _str[_size] = '\0';
        }

        const char* c_str()const
        {
            return _str;
        }



        /

        // capacity

        size_t size() const
        {
            return _size;
        }

        size_t capacity() const
        {
            return _capacity;
        }

        bool empty()const
        {
            return (_size == 0);
        }

        void resize(size_t n, char c = '\0')
        {
            int oldsize = _size;
            if (n > oldsize)
            {
                if (n > _capacity)
                {
                    reserve(n);
                }
                
                //多余的地方用字符c填充
                memset(_str + _size, c, n - _size);
            }

            _size = n;
            _str[_size] = '\0';
        }

        void reserve(size_t n)
        {
            int oldcapacity = _capacity;
        
            if (n > oldcapacity)
            {
                int newcapacity = n + 1;
                char* tmp = new char[newcapacity];
                if (tmp == nullptr)
                {
                    assert(0);
                }

                strcpy(tmp, _str);
                delete[] _str;
                _str = tmp;
                _capacity = n;
            }
        }



        /

        // access

        char& operator[](size_t index)
        {
            assert(index < _size);
            return *(_str + index);
        }

        const char& operator[](size_t index)const
        {
            assert(index < _size);
            return *(_str + index);
        }

        char& at(size_t index)
        {
            if (index >= _size)
                throw std::out_of_range("index >= _size");

            return _str[index];
        }

        const char& at(size_t index)const
        {
            if (index >= _size)
                throw std::out_of_range("index >= _size");

            return _str[index];
        }


        /

        //relational operators

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

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

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

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

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

        bool operator!=(const string& s)
        {
            return (strcmp(_str, s._str) != 0);

        }



        // 返回c在string中第一次出现的位置

        size_t find(char c, size_t pos = 0) const
        {
            for (int i = pos; i < _size; ++i)
            {
                if (*(_str + i) == c)
                {
                    return i;
                }
            }

            return npos;
        }
        size_t rfind(char c, size_t pos = npos) const
        {
            if (pos == npos || pos >= _size)
                pos = _size - 1;

            int i = pos;
            while (i >= 0)
            {
                if (_str[i] == c)
                    return i;

                --i;
            }

            return npos;
        }

        // 返回子串s在string中第一次出现的位置

        // 在pos位置上插入字符c/字符串str,并返回该字符的位置

        iterator insert(iterator pos, char c)
        {
            if (pos <begin() || pos >end())
            {
                return end();
            }
            if (_size == _capacity)
            {
                reserve(_size * 1.5 + 3);
            }

            iterator it = end() - 1;
            while (it >= pos)
            {
                *(it + 1) = *it;
                --it;
            }
            ++_size;
            _str[_size] = '\0';

            *(it + 1) = c;
        }


        // 删除pos位置上的元素,并返回该元素的下一个位置

        iterator erase(iterator pos, size_t len)
        {
            if (pos < begin() || pos >= end())
            {
                return end();
            }
            iterator it = pos + 1;
            while (it != end())
            {
                *(it - 1) = *it;
                it++;
            }

            --_size;
            _str[_size] = '\0';

            return pos;
        }

    private:

        char* _str;

        size_t _capacity;

        size_t _size;
        const static int npos = -1;

    };

}

源文件:

	#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
	#include"mystring.h"
	
	int main()
	{
		tc::string s1("my");
		const char* str = "name is ";
		tc::string s2(str);
		tc::string s3("csdn");

		std::cout << s1 << std::endl;
		std::cout << s2 << std::endl;
		std::cout << s3 << std::endl;

		tc::string s4;
		s4 += s1;
		s4 += s2;
		s4 += s3;
		std::cout << s4 << std::endl;


		s4.push_back('~');
		std::cout << s4 << std::endl;

		size_t index = s4.find('y', 0);
		tc::string::iterator it = s4.begin() + index + 1;
		s4.insert(it, ' ');
		index = s4.find('e', 0);
		it = s4.begin() + index + 1;
		s4.insert(it, ' ');

		std::cout << s4 << std::endl;
		return 0;
	}

其实没什么难点,string内部实现的其实就是一个维护字符类型的顺序表;

但要注意:

1、在开辟空间的时候,不能直接给oldcapacity * 1.5,要加上一个随机值,不然第一次是0,那乘出来也是0,就开不了空间了;

2、构造函数中,给出一个字符串的情况下,要提防给出nullptr,对nullptr进行操作是不合法的,所以要赋值成"",

而对于用常量字符串构造的情况下,需要在初始化列表中给出指针的默认值,在2019以上的vs版本,会给出无初始化的指针为nullptr,而在低版本编译器中,会给出值为随机值,是一个野指针,对其进行操作也是不合法的;

而给出一个string对象的情况下,传引用可以少调用一次拷贝函数,我们可以通过swap函数交换它们指针的方式,先创建一个临时变量tmp然后让tmp中的_str和this->_str交换即可,不可以直接用传进来的引用swap。。。这样意思就变了

3、对于构造函数来说,其实有很多种写法

比如:

string(const string& s):_str(nullptr)
{
    string tmp(s._str);
    std::swap(tmp._str,_str);
}

这个方法实现的前提是,给出了用指针拷贝构造的方法

或者

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

这种就比较好理解,意思就是直接给_str初始化指向堆上一段大小为strlen(s) + 1的空间(+1是为了放\0),然后用strcpy将s._str中的内容拷贝进this->_str

对于运算符重载其实也有几种写法:

string& operator=(const string& s)
{
    string tmp(s);
    std::swap(s._str,_str);
    return *this;
}
string& operator=(const string s)
{
    string tmp(s);
    std::swap(_str,tmp._str);
    return *this;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值