一个精简的string类

C++ 基础内容, 不值一提

AuthorJacky Wu       2006-4-17

引用该文章,必须注明其出处              http://blog.csdn.net/imwkj

 

今天在看数据结构的时候发现一个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()函数没有实现,但是算法和正向匹配相似,只需反向的建立失效数组和反向的索引字串就可以了,这里就不在实现它了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值