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

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至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指向对象中因此还需要放入一次。

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

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

JavaScript怎么用Immerjs实现不可变数据 - 开发技术

本篇内容主要讲解“JavaScript怎么用Immerjs实现不可变数据”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript怎么用Immerjs实现不可变数据”吧!Immerjs 是一个用于管理 JavaSc...

vm挂起虚拟机后无法开机

1、虚拟机文件所在目录下面找到扩展名为vmss的文件; 2、删除该文件,重新启动虚拟机ok;...

QThreadPool

#include<QThreadPool> #include<QDebug> class HelloWorldTask : public QRunnable { public: void run() { qDebug() << "...

UVa 11729 Commando War (贪心)

11729 - Commando WarTime limit: 1.000 secondshttp://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=456&page=show_...

怎么使用el-menu递归实现多级菜单组件 - 开发技术

今天小编给大家分享一下怎么使用el-menu递归实现多级菜单组件的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1. 效果:2. 实现:创建外层菜单Asi...

最新可用的谷歌google镜像/Sci-Hub可用网址/Github镜像等等各种可用镜像网址总结

最新可用的谷歌google镜像/Sci-Hub可用网址/Github镜像等等各种可用镜像网址总结。 一、谷歌学术镜像 网址一http://scholar.scqylaw.com/ (附 sci-hub) 网址二https://ac.scmor.com/ (附 sci-hub比较全面) 网址三htt...