从零开始的C++(十)-CSDN博客

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

    string 成员函数的模拟实现

    1.构造函数

    
            string(const char* str = "")
                :_capacity(0)
                ,_size(0)
                ,_str(nullptr)
            {
                int len = strlen(str);
                _str = new char[len + 1];
                strcpy(_str, str);
                _size = _capacity = len;
            }
    
            void swap(string& s)
            {
                char* tmp = s._str;
                s._str = _str;
                _str = tmp;
    
                int tmp_int = s._size;
                s._size = _size;
                _size = tmp_int;
    
                tmp_int = s._capacity;
                s._capacity = _capacity;
                _capacity = tmp_int;
    
    
            }
            string(const string& s)
            {   
                //法一
               /* int len = strlen(s._str);
                _str = new char[len + 1];
                strcpy(_str, s._str);
                _size = _capacity = len;*/
    
                //法二
                string tmp(s);
                swap(tmp);
    
    
            }

    对于传字符串的构造函数利用参数化列表初始化了成员函数再在函数内实现空间开辟、字符串拷贝、成员赋值。

    对于传同类对象的拷贝构造一种方法是重新开辟空间并把内容拷贝过去实现深拷贝。一种方法是服用传字符串的构造函数此时临时对象的内容就是所需要的内容所以用一个swap函数将临时对象的成员内容和this指向的对象的成员内容互换然后函数结束后对临时对象调用析构处理了原本属于this指向的对象的内容的销毁。

    2.赋值函数

          string& operator=(const string& s)
            {   
                //法一
               /* _size = s._size;
                _capacity = s._capacity;
    
                char* tmp = new char[_capacity+1];
                strcpy(tmp, s._str);
                delete[] _str;
                _str = tmp;
                return *this;*/
    
                //法二
                string tmp(s._str);
                swap(tmp);
            }
    

    赋值函数的内容和传递对象的拷贝构造十分相似都是将一个对象的内容深拷贝到另一个对象中因此方法也有两种原理和上述类似。

    3.析构函数

    
            ~string()
            {
                delete[]_str;
                _size = _capacity = 0;
    
    
            }
    

    析构函数的主要作用就是销毁开辟的空间。

    4.插入内容

            void reverse(size_t n)
            {    
                if (n > _capacity)
                {
                    _capacity = n;
                    char* tmp = new char[_capacity + 1];
                    strcpy(tmp, _str);
                    _str = tmp;
                }
              
            }
    
            void push_back(char c)
            {    
                //扩容
                if (_size == _capacity)
                {
                    reverse(2 * _capacity + 1);
                }
                _str[_size] = c;
                _str[++_size] = '\0';
    
            }
    
            string& operator+=(char c)
            {
                 push_back(c);
                 return *this;
            }
    
            void append(const char* str)
            {   
                int len = strlen(str);
                if (_size+len> _capacity)
                {
                    reverse(_size + len);
                }
                strcat(_str, str);
                _size += len;
    
            }
    
            string& operator+=(const char* str)
            {
                append(str);
                return *this;
            }

    push_back()用于插入一个字符append用于插入一个字符串重载+=能实现插入一个字符或一个字符串功能和push_back和append类似因此直接复用同时针对字符和字符串进行了函数重载。

    5.insert和erase

           // 在pos位置上插入字符c/字符串str并返回该字符的位置
    
            string& insert(size_t pos, char c)
            {
                assert(pos <= _size);
                *this += c;
                for (int i = _size; i > pos; i--)
                {
                    _str[i] = _str[i - 1];
                }
                _str[pos] = c;
                _str[_size] = '\0';
                return *this;
            }
    
            string& insert(size_t pos, const char* str)
            {  
                assert(pos <= _size);
                int len = _size + strlen(str);
                int len1 = strlen(str);
                reverse(len);
                for (int i =_size; i >=(int)pos ; i--)
                {
                    _str[i+len1] = _str[i];
                }
                for (int i = pos,j=0; i < pos+len1; i++)
                {
                    _str[i] = str[j++];
                }
                _size = len;
                return *this;
            }
    
    
    
            // 删除pos位置上的元素并返回该元素的下一个位置
    
            string& erase(size_t pos, size_t len=-1)
            {
                assert(pos <_size&&pos>=0);
                if (len == -1||pos+len>=_size)
                {
                    _size = pos;
                    _str[_size] = '\0';
                }
                else
                {
                    for (int i = pos + len; i < _size; i++)
                    {
                        _str[i - len] = _str[i];
                    }
                    _size -= len;
                    _str[_size] = '\0';
                }
    
                return *this;
            }
    

    insert函数实现在pos位置插入一个字符或一个字符串需要注意pos的类型是size_t如果是头插用pos做循环条件可能会进行无限循环即循环条件是大于或等于pos此时pos等于0但size_t类型永远大于或等于0。

    erase函数实现在pos位置删除len个字符如果len忽略或者len过大相当于删除pos位置往后所有字符因此需要判断len。

    6。流提取

        istream& operator>>(istream& _cin, bit::string& s)
        {    
            //充当临时缓冲区
            char tmp[101];
            s.clear();
            char ch;
             _cin.get(ch);
             int i = 0;
             while (ch != '\n' && ch != ' ')
             {
                 if (i == 100)
                 {
                     tmp[i] = '\0';
                     s += tmp;
                     i = 0;
                 }
                 tmp[i++] = ch;
                 _cin.get(ch);
             }
    
             if (i != 0)
             {
                 tmp[i] = '\0';
                 s += tmp;
             }
             return _cin;
        }

    对于流提取本函数的实现方式是一个字符一个字符的插入如果直接放入this指向对象中会存在多次扩容效率低。因此使用了一个临时缓冲区缓冲区未满的时候内容放入缓冲区中满了以后把缓冲区的内容全放入this指向的对象中再清空缓冲区。需要注意在退出循环后缓冲区中仍可能存在内容未放入this指向对象中因此还需要放入一次。

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
    标签: C++

    “从零开始的C++(十)-CSDN博客” 的相关文章

    php.ini详细错误指的是什么 - 编程语言

    这篇文章主要讲解了“php.ini详细错误指的是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“php.ini详细错误指的是什么”吧! PHP ini详细错误是一种配置错误,通常会在服务器...

    php中文字符无法正常显示中文如何解决 - 编程语言

    这篇文章主要介绍“php中文字符无法正常显示中文如何解决”,在日常操作中,相信很多人在php中文字符无法正常显示中文如何解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”php中文字符无法正常显示中文如何解决”的疑惑有所帮助!接下来,请...

    通过url删除ES中的数据

    curl -XDELETE "http://test-hostname:9200/product*_201704*"...

    如何用post的方式进行eventSource请求

    我们平时的工作中可能需要和服务端建立链接从而来接受服务端推送的数据常用的就是eventSource我们平时常用的就是通过get的方式创建一个eventSource但是我们如何通过post的方式创建呢首先我们介绍一下eventSource还有他和websocket的区别 1.eventSourc...

    java中的数字格式化

    import java.math.BigDecimal; import java.math.MathContext; public class Numb { private static double...

    ThingsBoard——Rest API获取token和刷新token

    ThingsBoard的REST API文档使用的是Swagger大多数的接口都可以通过这个地址来查看和测试后面带锁图标的接口表示需要鉴权 http://{{YOUR_HOST}}:{{PORT}}/swagger-ui.html 一、登录获取token 登录接口在login-endpoin...