一个精简的string类

来源:互联网 发布:linux 命令行修改权限 编辑:程序博客网 时间:2024/05/14 14:28

今天在看数据结构的时候发现一个String类的ADT表示以及实现让人看着很不舒服,于是乎愚蠢的自己实现了一个String类,这个类的接口功能和标准库中的string类是一致的,由于里面的字串操作函数都是自己实现的,所以效率一定很低,(标准库中的字串操作函数是汇编实现的J~~~),经过简单的测试,my String似乎已经正确实现,由于只实现了标准的string的一般的操作,并没有实现迭代操作,所以只能将String类称作“一个精简的,但是异常低效的stringJ”,好了,不说了,看代码吧,有错误大家请热烈的扔鸡蛋 J.

1:类中有些地方使用了“自动构造类型转换”,所以实现的功能还是比较多的。

2:使用了库函数memcpy来实现数据的移动,这样做似乎比循环移动数据要高效

3:实现了字符串模式匹配的KMP算法

 

     文件String.h

#ifndef STRING_H_

#define STRING_H_

 

#include <iostream>

 

#ifndef NOPOS

#define NOPOS -0

#endif

 

//size_t : long unsigned int

class String {

  

public:

   String();

   String( const char* ch );            //由字符数组构造

   String( const String& str);

   virtual ~String();

  

   String& Append(const String& s );             

//在当前串追加一个字符串

   inline size_t Size() const {   return m_iLength;}

   //当前字符串长度

   const char* c_str() const;                    

//返回当前串的一个拷贝

   int Compare( const String& s, size_t n) const ;  

   //将当前串从n位置与S进行比较,如果比较部分相同,返回0

   //如果相同部分在N前返回-1,如果在N后,则返回1

   const char* Data() const;                     

//返回串中的内容

   String& Erase( size_t n, size_t m);           

   //删除自串中nm之间的字符

   size_t Find(const String& s, size_t n=0);     

   //n位置开始,搜索字串s如果搜到,则返回首次出现该字串的位置,

   //如果没有,返回常数NOPOS

   String& Insert(size_t n, const String& s);    

//n位置出插入字串s

  

   const char* operator[] (size_t i) const;

   char* operator[](size_t i);                   

//返回索引i处字符的地址

   int rFind(const String& s, int n=NOPOS);      

//反向搜索字串s

   String& operator=(const String& str);

  

   //friend function

friend std::istream& operator>>(std::istream& sin, String& s);

friend std::ostream& operator<<(std::ostream& sout, String& s);

 

   friend String operator+( const String& s1, const String& s2);

   friend bool operator== ( const String& s1, const String& s2);

   friend bool operator!= ( const String& s1, const String& s2);

   friend bool operator>( const String& s1, const String& s2);

   friend bool operator>=( const String& s1, const String& s2);

   friend bool operator<( const String& s1, const String& s2);

   friend bool operator<=( const String& s1, const String& s2);

 

protected:

   //reimplement cstring functions

   char* strcat(char *t, const char *s);

   size_t strlen( const char *s) const;

   char* strcpy( char *t, const char *s);

   int strcmp(const char*t, const char*s, size_t n) const;

   char* strinsert(size_t n, char **dstr, const char *sstr);

  

   void fail(int *fail, const char* ch); //给失效匹配数组赋值的函数

private:

   char* cstr;

   size_t m_iLength;

 

};

 

#endif /*STRING_H_*/

 

     ※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

※文件String.cpp

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

#include "String.h"

 

#include <memory.h>

#include <iostream>

 

 

String::String()

{

   cstr = new char[1];

   *cstr = '/n';   //新建空的字串

   m_iLength= 0;

}

 

String::String(const char* ch )

{

  

   m_iLength = strlen(ch);

   cstr = new char[m_iLength+1];

   strcpy(cstr, ch);  //拷贝字符串,包括'/0'

}

 

String::String( const String& str)

{

   m_iLength = str.m_iLength;

   cstr = new char[m_iLength+1];

   strcpy(cstr, str.cstr);

}

 

String::~String()

{

   delete[] cstr;

}

 

 

String& String::Append(const String& s)

{

   char *ch ;

   if(s.m_iLength>0)

   {

      ch = new char[m_iLength+s.m_iLength+1];

      memcpy(ch, cstr, m_iLength+1);

      strcat(ch, s.cstr);

      m_iLength = strlen(ch);

      delete[] cstr;

      cstr = ch;

   } 

   return *this;  

}

 

 

const char*  String::c_str() const

{

   return cstr;

}

 

int String::Compare(const String& s, size_t n) const

{

   return strcmp(cstr, s.cstr, n);  

}

 

const char* String::Data() const

{

   return cstr;

}

 

String& String::Erase( size_t n, size_t m)

{

   if(m==0) return *this;

   if((n+m) > m_iLength) m = m_iLength - n;

   char* str2 = new char[m_iLength-m+1];

  

   //拷贝内存区

   memcpy(str2, cstr, n);

   memcpy(str2+n, cstr+n+m, m_iLength-m+1);

   delete[] cstr;

   cstr = str2;

  

   m_iLength -= m; //重设字串长度;

   return *this;

  

}

 

String& String::Insert( size_t n, const String& s)

{

 

   strinsert(n, &cstr, s.cstr);//&cstr 显然,这里要改变cstr 指针

   m_iLength = strlen(cstr);

   return *this;  

}

 

String& String::operator=(const String& str)

{

   m_iLength = str.m_iLength;

   cstr = new char[m_iLength+1];

   strcpy(cstr, str.cstr); 

   return *this;

}

 

const char* String::operator[] (size_t i) const

{

   if(i<0) i=0;

   if(i>m_iLength+1) i=m_iLength+1;

   return cstr+i; 

}

char* String::operator[](size_t i)

{

  

   if(i<0) i=0;

   if(i>m_iLength+1) i=m_iLength+1;

   return cstr+i; 

}

 

String operator+( const String& s1, const String& s2)

{

   String ts1(s1);

   return ts1.Append(s2);  

}

 

bool operator== ( const String& s1, const String& s2)

{

   if( s1.Size() != s2.Size()) return false;

   if(!s1.Compare(s2,s2.Size())) return true;  //利用字符比较

   return false;

}

 

bool operator!= ( const String& s1, const String& s2)

{

   return !operator==(s1, s2);

}

 

bool operator>( const String& s1, const String& s2)

{

   return (s1.Compare(s2,s2.Size()) >0);

}

 

bool operator>=( const String& s1, const String& s2)

{

   return (s1.Compare(s2,s2.Size()) >0 || s1.Compare(s2,s2.Size()) == 0);

}

 

bool operator<( const String& s1, const String& s2)

{

   return (s1.Compare(s2,s2.Size()) < 0); 

}

 

bool operator<=( const String& s1, const String& s2)

{

   return (s1.Compare(s2,s2.Size()) < 0 || s1.Compare(s2,s2.Size()) == 0);

}

 

 

std::istream& operator>>(std::istream& sin, String& s)

{

   char* ch;

   sin >> ch;

   s = ch;

   return sin;

}

 

std::ostream& operator<<(std::ostream& sout, String& s)

{

   sout << s.cstr;

   return sout;

}

 

 

//----------------------------------------------------

//Protected function defines

//练手,愚蠢的再次实现几个字符串操作函数

//以后再也不能干这样的蠢事!!!!!!!!!

//----------------------------------------------------

 

size_t String::strlen( const char *s) const

{

   if(s == NULL) return 0;

   const char* p = s;

   size_t size = 0;

   while(*p++)

   {

      size++; 

   }

   return size;

}

 

char* String::strcpy( char *t, const char *s)

{

   if(t!=NULL && s!=NULL)

   {

      char* tmptr1 = t;

      const char* tmptr2 = s;

      while((*tmptr1++ = *tmptr2++) != '/0');

   }

   return t;

}

 

char* String::strcat(char *t, const char *s)

{

   if( t==NULL && s==NULL ) return t;

   char* tmptr1 = t;

   const char* tmptr2 = s;

   while((*tmptr1)) tmptr1++;

   while((*tmptr1++ = *tmptr2++) != '/0');

   return t;

}

 

int String::strcmp(const char *t, const char *s, size_t n) const

{

   size_t len1 = strlen(t);

   size_t len2 = strlen(s);

   if(len1 < len2)

   {

      n = len1;

   }

   else

   {

      n = len2;

   }

  

   int cmpresult = 0; //字典序比较结果

   const char* tmpch1 = t;

   const char* tmpch2 = s;

  

   size_t i = 0;

   while( (*tmpch1 == *tmpch2) && i<n )

   {

      i++;

      tmpch1++;

      tmpch2++;

   }

 

   if(   *tmpch1 > *tmpch2 )

   {

      cmpresult = 1;

   }

   else if(*tmpch1 < *tmpch2)

   {

      cmpresult = -1;

   }

   return cmpresult;

}

 

char* String::strinsert(size_t n, char** dstr, const char *sstr)

{

 

   size_t len1 = strlen(*dstr);

   size_t len2 = strlen(sstr);

   size_t len3 = len1+len2;

  

   if(len2>0)

   {

      if(n<0) n=0;

      if(n>len1) n=len1;      

      char* tmptr = new char[len3+1];

      memcpy(tmptr, *dstr, n); //拷贝前n个字符串

      memcpy(tmptr+n, sstr, len2);   //插入sstr

      memcpy(tmptr+n+len2, *dstr+n,len1-n+1); //拷贝后n+1个字符串

      delete[] *dstr;

      *dstr = tmptr;

   }

   return *dstr;  

}

 

 

//----------------------------

//经典的字符串模式匹配KMP算法!

//----------------------------

size_t String::Find(const String& s, size_t n)

{

  

   if((m_iLength-n)<s.m_iLength || n>m_iLength) return NOPOS; //没必要进行匹配

   int *Fary = new int[s.m_iLength]; //失效匹配数组

   fail(Fary, s.cstr);               //初始化失效匹配数组

   size_t posT = n;   //目标串长索引

   size_t posP = 0;   //匹配串长索引

   while( posT < m_iLength && posP < s.m_iLength)

   {

      while(cstr[posT++] == s.cstr[posP++]); 

//注意最后一次比较 posP越界

  

      if((posP-1) == s.m_iLength)           //查到匹配串

      { 

         break;

//退出while( posT < m_iLength && posP < s.m_iLength)

      }

      else

      { 

         //未匹配成功,重新设定POS,并在匹配

         posT += Fary[posP] + 1;

         posP = Fary[posP] + 1;  

      } 

   }

  

   delete[] Fary;  //删除失效匹配数组

   if( posP < s.m_iLength)

   {

      //没有查找到匹配项目

      return NOPOS;  

   }

   else

   {

      return posT - s.m_iLength;

   }

}

 

//-------------------------------------------

//用于失效匹配数组的初始化

//-------------------------------------------

void String::fail(int *fail, const char* ch)

{

   int len = strlen(ch);

   fail[0] = -1;      //首匹配字符

   for(int i=1; i<len; i++)

   {

      fail[i] = -1;

     

      // 循环计算fail[i] ,注意,iwhile循环内会增加

      while(ch[i] == ch[fail[i-1]+1])

      {

         fail[i] = fail[i-1]+1;

         i++; 

      }

      if(ch[i] == ch[fail[i-1]])     //不可以丢失这里的比较

      {

         fail[i] = 0;

      }

      else

      {

         fail[i] = -1;

      }    

   } 

}

//一个反向匹配函数rFind()函数没有实现,但是算法和正向匹配相似,只需反向的建立失效数组和反向的索引字串就可以了,这里就不在实现它了。
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 在宿舍休息不好怎么办 发现员工拿回扣怎么办 qq账号忘记了怎么办 如果忘记qq账号怎么办 美发店从网上进货怎么办 爱库存一个月没卖一万怎么办 小米小店加价怎么办 开餐饮配送公司怎么办 美团退款失败怎么办 皇帝吃不完的菜怎么办 钱包到家逾期会怎么办 餐厅订不到包间怎么办 医保卡信息错误怎么办 人人贷债权到期怎么办 做优惠券不赚钱怎么办 遥控器不管用了怎么办 空调遥控不管用怎么办 ios下东西失败怎么办 农产品自产自销怎么办免税证明 怀孕吃了螃蟹怎么办 怀孕吃甲鱼了怎么办 怀孕吃龙虾了怎么办 除湿机显示h1是怎么办 发喜糖没盒子怎么办 身份证被网贷的群发怎么办 数学不好找零钱怎么办 平安备用金秒拒怎么办 买二手房办按揭怎么办 房贷失败怎么办啊 贷款买房放款后怎么办 房贷审核不通过怎么办 按揭买房没流水怎么办 公积金办不下来怎么办 按揭办不下来怎么办 办房贷银行流水不够怎么办 买房银行不放贷怎么办 帮别人办电话卡怎么办 不知道客户号怎么办 建行快贷还里没额度了怎么办 我建行快贷暂无额度怎么办 建行快e贷还不上怎么办