zoukankan      html  css  js  c++  java
  • String C++完整实现。

    String C++实现

    改进:

    /*
    版权信息:狼
    文件名称:String.h
    文件标识:
    摘    要:对于上版本简易的String进行优化跟进。
      改进
      1.(将小块内存问题与大块分别对待)小内存块每个对象都有,当内存需求大于定义大小时利用动态分配
      2.实现大块内存的写时拷贝功能,提高效率,优化空间利用
      3.类似new[]实现机制:将动态内存块大小信息保存为隐藏“头”
      4.对于大块内存采取动态增长型。不够时扩容为当前大小的2倍
     
    当前版本:1.2
    修 改 者:狼
    完成日期:2015-12-12
     
    取代版本:1.1
    原 作 者:狼
    完成日期:2015-12-11
    */
    #ifndef _STRING_H
    #define _STRING_H
    #include<iostream>
    using namespace ::std;
     
    namespace COW
    {
     class String
     {
     friend  void Check_Interface(String &S);
     friend ostream& operator << (ostream&os, String &Str);
    
     public:
      String(const char* str = "");
      String(String& Str);
      String& operator=(const String& Str);
      ~String();
     
     public:
      int Find(char ch)const;
      int Find(const char* str)const;
      void PushBack(char ch);
      void Insert(size_t pos, char ch);
      void Insert(size_t pos, const char* str);
      bool Erase(size_t pos);
      bool Erase(size_t pos, size_t n);
      size_t Strlen()const;
     
     private:
      void InitInfo(size_t inUse); //初始化capacity and inUse
      void CheckMem(size_t add = 1); //对于内存操作时的增否处理
      const char* GetAdd()const; //获取当前字符串所在位置
      size_t capacity()const;  //读取头,获得有效容量长度
      int inCount()const;  //获取引用计数
      void decrease();//减少引用计数。
      void increase();//增加引用计数。
     
     private:
      enum{BufSize = 16};  //利用枚举进行数组初始化
      char *_str;    //内容块,“头”代替capacity
      char _buff[BufSize]; // 小内存块处理。
     };
     ostream& operator << (ostream&os, String &Str);
    }
    #endif
     
    #include"String.h"
    #pragma warning (disable:4351 4996)
     
    using namespace COW;
     
    String::String(const char *Str)
     :_str(NULL)
     , _buff()
    {
     //采用动态分配
     if (strlen(Str) >= BufSize)
     {
      //1.记录引用计数,2.记录当前有效大小   strlen()+1
      _str = new char[strlen(Str) + 5+4];
      
      InitInfo(strlen(Str)+1);
     
      char *cur = const_cast<char*>(GetAdd());
      strcpy(cur, Str); //有效位置
     }
     else//静态存储
     {
      strcpy(_buff, Str);
     }
    }
    String::String(String& Str)
     :_str(NULL)
     , _buff()
    {
     // 1.如果是小块内存。浅拷贝
     if (Str._str == NULL)
     {
      strcpy(_buff,Str._buff);
     }
     else
     {
      _str = Str._str;
      this->increase();
     }
    }
    String& String::operator=(const String& Str)
    {
     //都是动态 且指向一处
     if (_str == Str._str&&_str != NULL)
      return *this;
     
     //两个都是小内存时
     if (Str._str == NULL&&_str==NULL)
     {
      strcpy(_buff, Str._buff);
     }
     //如果*this 是小内存(不存在内存变更,不用处理buff),Str 动态。
     else if (_str==NULL&&Str._str!=NULL)
     {
      _str = Str._str;
      this->increase();
     }
      
     //*this 动态,Str小内存。减少*this._str计数。。.更改buff
     else if(_str!=NULL&&Str._str==NULL)
     {
      this->decrease();
      _str = NULL;
      strcpy(_buff,Str._buff);
     }
     
     //两个都是动态分配 但不同
     else
     {
      this->decrease();
      _str = Str._str;
      this->increase();
     }
     return *this;
    }
    ///////问题1...命名空间冲突时
    ostream& COW::operator << (ostream&os, String &Str)
    {
     if (Str._str)
     {
      os << (Str._str + 8);
     }
     else
      os << Str._buff;
     return os;
    }
     
    
    ////////////////////////core_func
    inline void String::increase()
    {
     *(int*)_str += 1;
    }
     
    inline void String::decrease()
    {
     if (_str != NULL)
     {
     
      //////问题2,,每次decrease之后必须变更_str..为NULL或者指向新块
      if ((*(int*)_str) - 1 != 0)
      {
       (*(int*)_str) -= 1;
      }
      else
      {
       delete[]_str;
       _str = NULL;
      }
     }
    }
    String::~String()
    {
     this->decrease();
     _str = NULL;
    }
     
    ///获取字符串的核心地址
    const char *String::GetAdd()const
    {
     //忘记给对正确起始点
     return _str ? _str+8 : _buff;
    }
     
    size_t String::capacity()const
    {
     return *((int*)_str+1);
    }
    int String::inCount()const 
    {
     return *((int*)_str);
    }
     
    //设置头 信息
    void String::InitInfo(size_t inUse)
    {
     *((int*)_str) = 1;
     *((int*)_str + 1) = inUse;
    }
     
    void String::CheckMem(size_t add)
    {
     if (_str == NULL)
     {
      //小内存,且变动后不越界。
      if (strlen(_buff) + add < 16)
       return;
      //小内存,变动后越界
      else
      {
       _str = new char[strlen(_buff) + add + 9];
     
       InitInfo(strlen(_buff) + add+1);
      }
     }
     else
     {
      //容量足够,且引用计数为1;
      if (strlen(_str + 8) + add < capacity()&& inCount()==1)
      {
       //,但是写时拷贝,需要更新空间,所以顺带增加宽度
       //if (inCount() != 1)
       //{
       // int new_mem = (strlen(_str + 8) + add) * 2 + 9;
       // this->decrease();
       // 
       // _str = new char[new_mem];
       // //少了+1  会造成后续始终有一个字节浪费问题
       // InitInfo((strlen(_str + 8) + add) * 2 + 1);
       //}
       return;
      }
      else
      {
       //扩容后,容量为当前串长的2倍。  匹配使用,,用realloc 会出现问题
       //realloc(_str, (strlen(_str+8) + add) * 2 + 8);
      
       //不能delete,,写时拷贝忘记了。。引用计数问题忘记了?
       //delete[] _str;、
       //先计算所需,再decrease(),因为可能赋值为NULL,不得求Strlen
       int new_mem = (strlen(_str + 8) + add) * 2 + 9;
       this->decrease();
       _str = new char[new_mem];
       
       //少了+1  会造成后续始终有一个字节浪费问题
       InitInfo(new_mem-8);
      }
     } 
    }
     
    //////////////////publicFunc
    int String::Find(char ch)const
    {
     char *cur = const_cast<char*>(GetAdd());
     int pos = -1;
     while (*cur)
     {
      pos++;
      if (*cur == ch)
       return pos;
      cur++;
     }
     return -1;
    }
     
    int String::Find(const char* str)const
    {
     if (str == NULL)
      return -1;
     char *cur = const_cast<char*>(GetAdd());
     int pos = -1;
     int len = strlen(str);
     while (*(cur + len))
     {
      pos++;
      ///简直,,if 后边有个;bug
      if (strncmp(cur, str, len) == 0)
       return pos;
      cur++;
     }
     return -1;
    }
    void String::PushBack(char ch)
    {
     //首先保存内容。然后判断空间,然后存储。
     char p[100];
     char *st = const_cast<char*>(GetAdd());
     
     strcpy(p, st);
     
     CheckMem(); //默认为1;
     
     st = const_cast<char*>(GetAdd());
     strcpy(st, p);
     
     st[strlen(st)+1] = '';
     st[strlen(st)] = ch;
     
    }
     
    size_t String::Strlen()const
    {
     return strlen(GetAdd());
    }
     
    void String::Insert(size_t pos, char ch)
    {
     //越界有效化。。。
     if (pos >= Strlen())
     {
      pos = Strlen()-1;
     }
     //首先保存内容。然后判断空间,然后存储。
     char p[100];
     char *st = const_cast<char*>(GetAdd());
     
     strcpy(p, st);
     
     CheckMem(); //默认为1;
     
     st = const_cast<char*>(GetAdd());
     strncpy(st, p, pos);
     
     st[pos] = ch;
     
     //不能用strcat,前边字符串不存在''
     strcpy(st + pos + 1, p + pos);
    }
     
    void String::Insert(size_t pos, const char* str)
    {
     //越界有效化。。。
     if (pos >= Strlen())
     {
      pos = Strlen();
     }
     //首先保存内容。然后判断空间,然后存储。
     char p[100];
     char *st = const_cast<char*>(GetAdd());
     
     strcpy(p, st);
     
     int len = strlen(str);
     CheckMem(len); //默认为1;
     
     st = const_cast<char*>(GetAdd());
     strncpy(st, p, pos);
     
     strcpy(st + pos, str);
     
     strcpy(st + pos + len, p + pos);
    }
     
    bool String::Erase(size_t pos)
    {
     char *cur = const_cast<char*>(GetAdd());
     size_t len = Strlen();
     if (pos >= len)
      return false;
     memmove(cur+ pos, cur + pos + 1, len + 1);
     return true;
    }
     
    bool String::Erase(size_t pos, size_t n)
    {
     char *cur = const_cast<char*>(GetAdd());
     size_t len = strlen(cur + pos + 1);
     if (pos >= len)
      return false;
     memmove(cur + pos, cur + pos + n, len + 1);
     return true;
    }
     
    //////friend 友员函数不能跨越命名空间访问私有成员????????????
    void Check_Interface(COW::String &S)
    {
     //char  COW::String::*ch = S._str;
     //const char *ch = S._str;
     cout << endl;
    }
     
    ///////////////////////////Test
    #include"String.h"
    using namespace COW;
     
    void Test_COPY_EPU()
    {
     
     String S1("hellow     world!");
     String S2("hellow world");
     String S3;
     S3 = S2;
     String S4;
     S4 = S1;
     //少对多,少对少
     cout << "小内存赋值" << S3 << endl;
     cout << "小内存赋值" << S4 << endl;
     
     //多对多,多对少
     String S5("change             world");
     S5 = S1;
     cout << S5 << endl;
     S5 = S2;
     cout << S5 << endl;
     //多多且等
     String S6 = S1;
     S6 = S1;
     cout << S6 << endl;
    }
    void Test_Find_Erase()
    {
     String S1("hellow     world!");
     String S2("hellow world");
     cout << S1.Find('l') << endl;
     cout << S2.Find('z') << endl;
     cout << S1.Find("low") << endl;
     char*p = NULL;
     cout << S2.Find(p) << endl;
     
     S2.Erase(4);
     S2.Erase(4, 3);
     cout << S2 << endl;
    }
     
    void Test_Push_Insert()
    {
     String S1("hellow     world!");
     String S2("hellow   world");
     //S1.PushBack('l');
     //S1.PushBack('v');
     //S2.PushBack('l');
     //S2.PushBack('v');
     int pos = S1.Find('l');
     S1.Insert(pos,'v');
     S1.Insert(100, "lv");
     cout << S1 << endl;
     cout << S2 << endl;
     
    }
    void main()
    {
     //Test_COPY_EPU();
     //Test_Find_Erase();
     Test_Push_Insert();
    }
  • 相关阅读:
    如何设置backBarButtonItem的title和action
    让navigationItem.leftBarButtonItem具有backBarButtonItem的外观样式
    在Xcode中添加空模板
    reason:'CALayer position contains NaN: [160 nan]'
    git的注册与使用:代码的版本控制器
    iOS开发零基础教程之Git的一些常用命令
    iOS开发零基础教程之生成git所需的SSH keys
    iOS开发零基础教程之在终端(Terminal)里安装oh my zsh
    iOS开发零基础教程之Homebrew的安装
    [原]ibatis 数据库时间 插入数据
  • 原文地址:https://www.cnblogs.com/lang5230/p/StringCOW1_2.html
Copyright © 2011-2022 走看看