c++string类的简单实现

来源:互联网 发布:网络策划是做什么的 编辑:程序博客网 时间:2024/05/17 22:30

     本文只是实现String的一些简单功能,实现构造函数、拷贝构造函数、赋值函数、析构函数这几个非常重要的部分。因为String里涉及动态内存的管理,这时就要求程序员自己实现这些函数进行深复制,即不止复制指针,需要连同内存的内容一起复制,析构函数释放对应的内存。

除了以上几个个必须的函数,这里还实现了其他一些比较常用的函数 

    1.常见=,+,==,<<,>>等运算符的重载,可以加深对String的认识和运算符重载的理解。

    2.对字符串的常用操作,如添加、删除、翻转、查找。

String类的整体实现如下:

String.h

class String
{
public:
String(const char *str = NULL); //通用构造函数
String(const size_t len, const char ch);//构造几个相同字符的字符串
String(const String &str); //拷贝构造函数
~String(); //析构函数

String operator+(const String &str) ; //重载+
String& operator=(const String &str); //重载=
String& operator+=(const String &str); //重载+=
bool operator==(const String &str) const; //重载==
String operator+(const char *s) ; //重载+
String& operator=(const char *s); //重载=
String& operator+=(const char *s); //重载+=
bool operator==(const char *s) const; //重载==
bool operator!=(const String& str); //重载!=
bool operator<(const String& str); //重载<
bool operator<=(const String& str); //重载<=
bool operator>(const String& str); //重载>
bool operator>=(const String& str); //重载>=
char& operator[](size_t n) const; //重载[]
String substr(size_t pos, size_t n);//截取
String& append(const String& other); //在末尾追加,相当于+=
String& append(const char* str);
String& insert(size_t pos, const String& other);//在指定位置域插入
String& assign(String&other, size_t pos, size_t n);//用other替换pos开始的n个字符
String& erase(size_t pos, size_t n); //删除pos开始的n个字符
size_t find(const char* str, size_t index=0); //从指定位置查找字符串
size_t find(const char ch, size_t index=0);
size_t find(const String& str, size_t index=0);
String& replace_all(const char oldc, const char newc);//替换相应字符
String& replace(size_t index, const char ch);
String& reserve(); //反转
String& reserve(size_t p1, size_t p2); //第p1个到第p2个字符倒置
__int64 valueof(); //返回64位整数

size_t size() const; //获取长度
bool isEmpty();// 返回字符串是否为空
const char* c_str() const; //获取C字符串

friend istream& operator>>(istream &is, String &str);//输入
friend ostream& operator<<(ostream &os, String &str);//输出

private:
char *m_data; //字符串
size_t m_length; //长度
int my_find(const char *str, const char *substr);
void my_strcpy(const char * source, char * desnation, size_t start, size_t end) const;
void my_strcat(const char * source, char * desnation, size_t start, size_t end) const;
size_t my_strlen(const char *p) const;
void * my_memset(void* buffer, char c, size_t count);
char *my_strchr(char *str, char c);
void* my_memcpy(void* to, const void* from, size_t count);
void* my_memmove(void* to, const void* from, size_t count);
int my_strcmp(const char *s, const char *t) const;
int my_stricmp(const char *s, const char *t) const;
int my_strncmp(const char *s, const char *t, size_t count) const;
void swap(char &p1, char &p2);
};

String.cpp

#include "String.h"

String::String(const char *str)//通用构造函数
{
if (!str)
{
this->m_length = 0;
this->m_data = NULL;
}
else
{
this->m_length = my_strlen(str);
this->m_data = new char[this->m_length + 1];
my_strcpy(str, this->m_data,0,this->m_length);
}
}

String::String(const size_t len, const char ch)
{
if (NULL == ch)
{
this->m_data = NULL;
this->m_length = 0;
return;
}
this->m_length = len;
this->m_data = new char[len + 1];
my_memset(this->m_data,ch,len);
this->m_data[len] = '\0';
}

//拷贝构造函数需要进行深复制。
String::String(const String &str)//拷贝构造函数
{
this->m_length = str.size();
if (this->m_length == 0)
this->m_data = NULL;
else
{
this->m_data = new char[this->m_length + 1];
my_strcpy(str.c_str(),this->m_data,0,this->m_length);
}

}
//析构函数需要进行内存的释放及长度的归零。
String::~String()//析构函数
{
delete[] m_data;
m_data = NULL;
m_length = 0;
}
//重载字符串连接运算,这个运算会返回一个新的字符串。
String String::operator+(const String &str) //重载+
{
String newString;
newString.m_length = this->m_length + str.size();
newString.m_data = new char[newString.m_length + 1];
my_strcpy(this->m_data,newString.m_data,0,this->m_length);
my_strcat(str.m_data,newString.m_data, 0,str.m_length);
return newString;
}
//重载字符串赋值运算,这个运算会改变原有字符串的值,
String& String::operator=(const String &str)//重载=
{
if (this == &str) return *this;
if (this->m_length>0)
delete[] this->m_data;
this->m_length = str.m_length;
this->m_data = new char[this->m_length + 1];
my_strcpy(str.c_str(),this->m_data,0,this->m_length);
return *this;
}
//重载字符串 += 操作,总体上是以上两个操作的结合。
String& String::operator+=(const String &str)//重载+=
{
this->m_length += str.m_length;
char *newData = new char[this->m_length + 1];
my_strcpy(this->m_data,newData, 0,this->m_length-str.m_length);
my_strcat(str.m_data,newData, 0,str.m_length);
if((this->m_length-str.m_length)>0)
delete[]this->m_data;
this->m_data = newData;
return *this;
}
//重载相等关系运算,
bool String::operator==(const String &str) const//重载==
{
if (this->m_length != str.m_length) return false;
return my_strcmp(this->m_data, str.m_data) ? false : true;
}
String String::operator+(const char *s) //重载+
{
return this->operator+(String(s));
}
String& String::operator=(const char *s) //重载=
{
return this->operator=(String(s));
}
String& String::operator+=(const char *s) //重载+=
{
return this->operator+=(String(s));
}
bool String::operator==(const char *s) const //重载==
{
return this->operator==(String(s));
}
bool String::operator!=(const String& str)
{
return my_strcmp(this->m_data, str.m_data) != 0 ? true : false;
}
bool String::operator<(const String& str)
{
return my_strcmp(this->m_data, str.m_data) < 0 ? true : false;
}
bool String::operator<=(const String& str)
{
return my_strcmp(this->m_data, str.m_data) <= 0 ? true : false;
}
bool String::operator>(const String& str)
{
return my_strcmp(this->m_data, str.m_data) > 0 ? true : false;
}
bool String::operator>=(const String& str)
{
return my_strcmp(this->m_data, str.m_data) >= 0 ? true : false;
}
//重载字符串索引运算符,
char& String::operator[](size_t n) const//重载[]
{
if (n >this->m_length) return this->m_data[this->m_length]; //错误处理
else return this->m_data[n];
}
String String::substr(size_t pos, size_t n)
{
if ((pos + n) > this->m_length)
n = this->m_length - pos;
String str;
str.m_length = n;
str.m_data = new char[n + 1]; //也可以
for (size_t i = 0; i<n; i++)
str[i] = (*this)[pos + i];
str[n] = '\0';
return str;
}
// append 同 += 追加到末尾
String& String::append(const String& other)
{
*this += other;// 利用刚刚那重载的+=
return *this;
}
String& String::append(const char* str)
{
*this += str;
return *this;
}

//insert 从pos开始的插入other
String& String::insert(size_t pos, const String& other)
{
if (pos<0 || pos > this->m_length)
{
pos = this->m_length;
}
char *p_old = this->m_data;
this->m_length += other.m_length;
this->m_data = new char[this->m_length + 1];
for (size_t i = 0; i<pos; i++)
*(this->m_data + i) = *(p_old + i);
for (size_t i = pos; i<other.m_length + pos; i++)
*(this->m_data + i) = other.m_data[i - pos];
for (size_t i = other.m_length + pos; i<this->m_length; i++)
*(this->m_data + i) = p_old[i - other.m_length];
*(this->m_data + this->m_length) = '\0';
return *this;
}
//assign 替换 用other替换this的pos开始的n个字符
String& String::assign(String&other, size_t pos, size_t n)
{
if(pos<0 || pos>this->m_length)
return *this;
if (pos + n <= this->m_length&& n == other.m_length)
{
for (size_t i = pos; i < pos+n; i++)
*(this->m_data + i) = other[i - pos];
}
else
{
char *p_old = this->m_data;
this->m_length = this->m_length - n + other.m_length;
this->m_data = new char[this->m_length + 1];
for (size_t i = 0; i < pos; i++)
*(this->m_data + i) = *(p_old + i);
for (size_t i = pos; i < pos + other.m_length; i++)
*(this->m_data + i) = other.m_data[i - pos];
for (size_t i = pos + other.m_length; i < this->m_length; i++)
*(this->m_data + i) = *(p_old + n + i - other.m_length);
*(this->m_data +this->m_length) = '\0';
delete[] p_old;
}
return *this;
}
// erase 删除 从pos开始的n个字符
String& String::erase(size_t pos, size_t n)
{
if ((pos + n)>this->m_length)
n=this->m_length - pos;
char *p_old = this->m_data;
this->m_length -= n;
this->m_data = new char[this->m_length + 1];
for (size_t i = 0; i<pos; i++)
*(this->m_data + i) = p_old[i];
for (size_t i = pos; i<this->m_length; i++)
*(this->m_data + i) = p_old[i + n];
*(this->m_data + this->m_length) = '\0';
delete[] p_old;
return *this;
}
// 查找在字符串中第一个与str字符串匹配的位置,返回它的位置。
//搜索从index开始,如果没找到就返回-1
size_t String::find(const char* str, size_t index)
{
if (NULL == str || index >= this->m_length)
return -1;
return this->my_find(this->m_data+index, str);
}
size_t String::find(const char ch, size_t index)
{
if (NULL == ch || index >= this->m_length)
return -1;
size_t flag = -1;
for (size_t i = index; i<this->m_length; i++)
{
if (ch == this->m_data[i])
{
flag = i;
break;
}
}
return flag;
}
size_t String::find(const String& str, size_t index)
{
if (str.m_length==0 || index >= this->m_length)
return -1;
return this->my_find(this->m_data + index, str.m_data);
}
String& String::replace_all(const char oldc, const char newc)
{
if (NULL == oldc)
{
return *(this);
}
for (size_t i = 0; i<this->m_length; i++)
{
if ((*this)[i] == oldc)
{
(*this)[i] = newc;
}
}
return *(this);
}
String& String::replace(size_t index, const char ch)
{
if(index>=0&&index<this->m_length)
(*this)[index] = ch;
return *this;
}
String& String::reserve()
{
for (int i = 0; i < this->m_length / 2; i++)
this->swap((*this)[i], (*this)[this->m_length -1-i]);
return *this;
}
String& String::reserve(size_t p1, size_t p2) //第p1个到第p2个字符倒置
{
if (p1 >= 0 && p1 < this->m_length&&p2 >= 0 && p2 < this->m_length)
{
if (p2 < p1) this->swap((*this)[p1], (*this)[p2]);
for (int i = 0; i < (p2 - p1+1) / 2; i++)
this->swap((*this)[i+p1], (*this)[p2 - i]);
}
return *this;
}
__int64 String::valueof()
{
if (this->m_length>19|| this->m_length==0)
{
cout << "不符合要求转换失败!" << endl;
return 0;
}
__int64 sum = 0;
for (int i = this->m_data[0]=='-'?1:0; i<this->m_length; i++)
{
if ('0' <= this->m_data[i] && this->m_data[i] <= '9') sum = 10 * sum + this->m_data[i] - '0';
else
{
cout << "Transform error" << endl;
return 0;
}
}
if (this->m_data[0] == '-')
sum *= -1;
return sum;

}
//重载两个读取私有成员的函数,分别读取长度和C字符串。
size_t String::size() const//获取长度
{
return this->m_length;
}

bool String::isEmpty()// 返回字符串是否为空
{
return this->m_length == 0 ? true : false;
}

//重载输入运算符,先申请一块足够大的内存用来存放输入字符串,再进行新字符串的生成。
istream& operator>>(istream &is, String &str)//输入
{
char tem[10000]; //简单的申请一块内存
is >> tem;
str.m_length = str.my_strlen(tem);
str.m_data = new char[str.m_length + 1];
str.my_strcpy(tem, str.m_data, 0,str.m_length);
return is;
}
//重载输出运算符,只需简单地输出字符串的内容即可。注意为了实现形如cout << a << b的连续输出,这里需要返回输出流。上面的输入也是类似。
ostream& operator<<(ostream &os, String &str)//输出
{
if(str.m_data)
os << str.m_data;
return os;
}
const char* String::c_str() const//获取C字符串
{
return this->m_data;
}

int String::my_find(const char *str, const char *substr)
{
int i, j, check, count = 0;
size_t len = my_strlen(str); /*取得字符串长度,不包括'\0'*/
size_t sublen = my_strlen(substr);
if (len < sublen)
return -1;
for (i = 0; i < len - sublen + 1; i++)
{
check = 1; /*检测标记*/
for (j = 0; j < sublen; j++)/*逐个字符进行检测,在sublen长度内,一旦出现不同字符便将check置为0*/
{
if (str[i + j] != substr[j])
{
check = 0;
break;
}
}
if (check == 1)
return i;
}
return -1;
}

void String::my_strcpy(const char * source, char * desnation, size_t start, size_t end) const
{
if (start >= my_strlen(source))
return;
size_t i = start;
for (; end == 0 ? i < my_strlen(source) : i < end; i++)
desnation[i - start] = source[i];
desnation[i - start] = 0;
}

void String::my_strcat(const char * source, char * desnation, size_t start, size_t end) const
{
if (start >= my_strlen(source))
return;
size_t i = start;
char * des = desnation + my_strlen(desnation);
for (; end == 0 ? i < my_strlen(source) : i < end; i++)
des[i - start] = source[i];
des[i - start] = 0;
}

size_t String::my_strlen(const char *p) const
{
if (p == NULL)
return 0;
char *pstart = const_cast<char *> (p);
while (*p++);
return p - pstart-1;
}

//memset():把指定内存区域的前count个字节设置成字符c
void * String::my_memset(void* buffer, char c, size_t count)
{
if(buffer == NULL)
return NULL;
char * p = (char *)buffer;
while (count--)
*p++ = (char)c;
return buffer;
}

//查找字符串s中首次出现字符c的位置
char * String::my_strchr(char *str, char c)
{
if(str == NULL)
return NULL;
for (; *str != c&&*str == '\0'; ++str);
return str;
}

//memcpy(), 拷贝不重叠的内存块
void* String::my_memcpy(void* to, const void* from, size_t count)
{
if (to == NULL || from == NULL)
return NULL;
void * result = to;
char * pto = (char *)to;
char * pfrom = (char *)from;
if(pto < pfrom || pto > pfrom + count - 1)
return NULL;
while (count--)
{
*pto++ = *pfrom++;
}
return result;
}

//memmove(), 拷贝重叠或者是不重叠的内存块
void* String::my_memmove(void* to, const void* from, size_t count)
{
if(to == NULL||from == NULL)
return NULL;
void * result = to;
char * pto = (char *)to;
char * pfrom = (char *)from;
if (pto < pfrom || pto > pfrom + count - 1)//to与from没有重叠
{
while (count--)
*pto++ = *pfrom++;
}
else//to与from有重叠,从后向前move
{
pto = pto + count - 1;
pfrom = pfrom + count - 1;
while (count--)
*pto-- = *pfrom--;
}
return result;
}
//字符串比较
int String::my_strcmp(const char *s, const char *t)const
{
if(s == NULL || t == NULL)
return 0;
while (*s && *t && *s == *t) 
{
s++;
t++;
}
return (*s - *t);
}


//字符串比较(不区分大小写比较,大写字母会被映射为小写字母)
int String::my_stricmp(const char *s, const char *t) const
{
if(s == NULL || t == NULL)
return 0;
char ch1, ch2;
while (*s && *t)
{
if ((ch1 = *s) >= 'A' && (ch1 <= 'Z'))
ch1 += 0x20;
if ((ch2 = *t) >= 'A' && (ch2 <= 'Z'))
ch2 += 0x20;
if (ch1 == ch2)
{
++s;
++t;
}
else break;
}
return(ch1 - ch2);
}


int String::my_strncmp(const char *s, const char *t, size_t count) const
{
if(s == NULL||t == NULL)
return 0;
while (*s && *t && *s == *t && count--)
{
s++;
t++;
}
return(*s - *t);
}
void String::swap(char &p1, char &p2)
{
char tem = p1;
p1 = p2;
p2 = tem;
}

原创粉丝点击