C++ 基础内容, 不值一提 Author:Jacky Wu 2006-4-17 引用该文章,必须注明其出处 http://blog.youkuaiyun.com/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); //删除自串中n到m之间的字符 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] ,注意,i在while循环内会增加 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()函数没有实现,但是算法和正向匹配相似,只需反向的建立失效数组和反向的索引字串就可以了,这里就不在实现它了。 |