1. 程式人生 > >c++string類的簡單實現

c++string類的簡單實現

     本文只是實現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;
}