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();
    }
  • 相关阅读:
    PAT顶级 1024 Currency Exchange Centers (35分)(最小生成树)
    Codeforces 1282B2 K for the Price of One (Hard Version)
    1023 Have Fun with Numbers (20)
    1005 Spell It Right (20)
    1092 To Buy or Not to Buy (20)
    1118 Birds in Forest (25)
    1130 Infix Expression (25)
    1085 Perfect Sequence (25)
    1109 Group Photo (25)
    1073 Scientific Notation (20)
  • 原文地址:https://www.cnblogs.com/lang5230/p/StringCOW1_2.html
Copyright © 2011-2022 走看看