??string類(lèi),想必大家都不陌生,這是一個(gè)用來(lái)管理字符串的類(lèi)。讓我們使用字符串時(shí)更方便,更遍歷。所以今天我們就來(lái)簡(jiǎn)單的實(shí)現(xiàn)一下string類(lèi)。
我們要管理一個(gè)字符串,那么首先得有一個(gè)字符串。所以我們用char* 類(lèi)型的指針,來(lái)指向一個(gè)塊存儲(chǔ)字符串的地址。_size則記錄字符串的長(zhǎng)度,_cacpcity 為字符串的空間容量
private:
char* _str;
size_t _size;
size_t _cacpcity;
構(gòu)造函數(shù)
構(gòu)造函數(shù)我們?cè)趯?shí)例化一個(gè)string對(duì)象的時(shí)候,可以string s("hello world");
直接創(chuàng)建,也可以string s();
使它初始時(shí)為空,所以我們可以用缺省的構(gòu)造函數(shù)。如果不傳參數(shù),那么默認(rèn)初始化為空。
//缺省的構(gòu)造函數(shù)
string(const char* str = "")
: _size(strlen(str))
,_cacpcity(_size)
{ //開(kāi)辟一塊內(nèi)存
_str = new char[_cacpcity + 1];//有效容量是cacpcity,要多一個(gè)用來(lái)存放\0
strcpy(_str, str);
}
析構(gòu)函數(shù)析構(gòu)函數(shù)我們只需要釋放 _str指向的空間即可。
//析構(gòu)函數(shù)
~string()
{ delete[] _str;
_str = nullptr;
_size = _cacpcity = 0;
}
拷貝構(gòu)造函數(shù)拷貝構(gòu)造,就是拷貝一個(gè)字符串 例如:string s1("hello world"); string s2(s1);
。所以我們開(kāi)辟一塊與要拷貝字符串一樣大小的空間,再把它一一復(fù)制給新字符串即可。
//拷貝構(gòu)造
string(const string& s)
:_size(s._size)
, _cacpcity(s._cacpcity)
{ //開(kāi)辟一塊和s一樣的空間
_str = new char[_cacpcity+1];
strcpy(_str, s._str);
}
操作符重載
賦值操作符重載如果我們想用 = 操作符來(lái)給字符串賦值。那我們可以重載 = 操作符。
//賦值操作符重載
string& operator=(const string& s)
{ //如果不是自己給自己賦值
if (this != &s)
{ //創(chuàng)建一塊新空間
char* tmp = new char[s._cacpcity+1];
//拷貝
strcpy(tmp, s._str);
//銷(xiāo)毀舊空間
delete[] _str;
_str = tmp;
_size = s._size;
_cacpcity = s._cacpcity;
}
return *this;
}
當(dāng)然也可以復(fù)用拷貝構(gòu)造函數(shù)。
比較操作符重載<重載
//字符串比較函數(shù)重載
bool operator<(const string& s)
{ return strcmp(_str, s._str)< 0;
}
== 重載
bool operator==(const string& s)
{ return strcmp(_str, s._str) == 0;
}
<= 重載
bool operator<=(const string& s)
{ return (*this< s) || (*this == s);
}
? >重載
bool operator>(const string& s)
{ return !((*this)<= s);
}
?>=重載
bool operator>=(const string& s)
{ return !(*this< s);
}
!=重載
bool operator!=(const string& s)
{ return !(*this == s);
}
獲取字符串長(zhǎng)度直接返回_size 即可
//獲取長(zhǎng)度
size_t size()
{ return _size;
}
下標(biāo)訪問(wèn)字符串也可以進(jìn)行下標(biāo)訪問(wèn),所以我們重載[]即可
//下標(biāo)訪問(wèn)
char& operator[](size_t pos)
{ return _str[pos];
}
當(dāng)然,如果訪問(wèn)的是const修飾的字符串,那我們只能讀,不能寫(xiě)。
//只讀
const char& operator[](size_t pos) const
{ return _str[pos];
}
迭代器//定義2個(gè)迭代器,一個(gè)是可讀可寫(xiě),一個(gè)是只讀
typedef char* iterator;
typedef const char* const_iterator;
//迭代器開(kāi)始位置
iterator begin()
{ return _str;
}
const_iterator begin() const
{ return _str;
}
//迭代器末尾位置
iterator end()
{ return _str + _size;
}
const_iterator end()const
{ return _str + _size;
}
尾插一個(gè)字符就是在字符串末端插入一個(gè)字符,我們只需要在_size的位置插入,隨后_size++即可。不過(guò)要保證容量必須充足。
//尾插一個(gè)字符
void push_back(char c)
{ //檢查容量
if (_size == _cacpcity)
{ AddCacpcity(_cacpcity == 0 ? 15 : _cacpcity * 2);
}
_str[_size] = c;
_size++;
_str[_size] = '\0';
}
擴(kuò)容函數(shù)
void AddCacpcity(size_t newCacpcity)
{ //末尾位置留一個(gè)\0,所以+1
char* str = new char[newCacpcity + 1];
//舊字符串的內(nèi)容拷貝到新字符串
strcpy(str, _str);
//銷(xiāo)毀舊字符串
delete[] _str;
_str = str;
_cacpcity = newCacpcity;
}
追加字符串如果想在尾部追加字符串的話,我們可以實(shí)現(xiàn)一個(gè) append()函數(shù)。
//追加一個(gè)字符串
void append(const char* str)
{ //檢查容量
if (_cacpcity< (_size)+strlen(str))
{ AddCacpcity(_size + strlen(str));
}
//直接在末尾的位置加上str
strcpy(_str + _size, str);
_size += strlen(str);
}
然后我們可以重載 +=運(yùn)算符,拿來(lái)復(fù)用 append()函數(shù)。
string& operator+=(const char* str)
{ append(str);
return *this;
}
然后我們重載 +運(yùn)算符,但需要注意的是,+運(yùn)算符不改變當(dāng)前字符串,所以我們要值返回。
//+重載
string operator+(const char* str)
{ string s(*this);
s += str;
return s;
}
字符串清空直接把第一個(gè)字符改成\0即可
//清空
void clear()
{ _str[0] = '\0';
_size = 0;
}
字符串交換我們用std命名空間里面的swap函數(shù),對(duì)每個(gè)成員進(jìn)行交換。
//字符串交換
void swap(string& s)
{ std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_cacpcity, s._cacpcity);
}
以C的方式返回字符c語(yǔ)言的字符串其實(shí)就是一個(gè)char*指針,遇到\0結(jié)束,所以我們直接返回str就可以了。
//以c的方式返回字符串
const char* c_str()const
{ return _str;
}
判斷字符串是否為空直接判斷第一個(gè)元素是否是 \0
//判斷字符串是否為空
bool empty()const
{ return _str[0] == '\0';
}
修改長(zhǎng)度修改長(zhǎng)度我們要分多種情況,一般長(zhǎng)度減少時(shí),我們不改變現(xiàn)有容量。容量不夠時(shí),我們才增容。 如果 長(zhǎng)度減少,或者不變,我們只需要把 減少的新長(zhǎng)度給_size,然后把當(dāng)前位置變成\0。如果是增加長(zhǎng)度,我們要考慮容量,不夠的話需要增容,然后memset函數(shù)把增容的部分改成你指定的字符(默認(rèn)\0)。
//修改長(zhǎng)度
void resize(size_t n, char c = '\0')
{ //如果修改的值比當(dāng)前長(zhǎng)度小
if (n<= _size)
{ //截?cái)? _size = n;
_str[_size] = '\0';
}
//如果修改的值比當(dāng)前長(zhǎng)度大
else
{ //擴(kuò)容
if(n >_cacpcity)
{AddCacpcity(n);
}
//從size位置到n的位置設(shè)置為c
memset(_str + _size, c, n - _size);
//最后位置填上\0
_size = n;
_str[_size] = '\0';
}
}
指定大小擴(kuò)容之前寫(xiě)過(guò)一個(gè)擴(kuò)容函數(shù),直接把指定的大小傳過(guò)去即可。還是老規(guī)矩,減少不處理。
//指定容量。只增加,減少不處理
void reserve(size_t n)
{ if (n >_cacpcity)
{ AddCacpcity(n);
}
}
查找字符該查找只會(huì)找到從指定位置開(kāi)始,第一個(gè)出現(xiàn)的字符。如果要查找第二個(gè),那么就在第一個(gè)字符的后面開(kāi)始查找。
// 返回c在string中第一次出現(xiàn)的位置
size_t find(char c, size_t pos = 0) const
{ for (int i = pos; i< _size; i++)
{ if (_str[i] == c)
return i;
}
return nops;
}
nops是一個(gè)無(wú)符號(hào)的數(shù),代表找不到返回的值。
static const size_t nops = -1;
查找子串C語(yǔ)言中有strstr函數(shù),我們可以復(fù)用。
// 返回子串s在string中第一次出現(xiàn)的位置
size_t find(const char* s, size_t pos = 0) const
{ char* tmp = strstr(_str, s);
if (tmp == NULL)
return nops;
return tmp - _str;
}
指定位置插入字符只需要把pos位置后面的字符都往后移動(dòng)一格,隨后把字符放進(jìn)pos位置。
// 在pos位置上插入字符c/字符串str,并返回該字符的位置
string& insert(size_t pos, char c)
{ //判斷容量
if (_size == _cacpcity)
{ AddCacpcity(_cacpcity == 0 ? 15 : _cacpcity * 2);
}
//pos位置后往后移
size_t end = _size + 1;
while (pos< end)
{ _str[end] = _str[end - 1];
end--;
}
_str[pos] = c;
_size++;
return *this;
}
指定位置插入字符串插入字符是都往后移動(dòng)一格,插入字符串那就是把pos位置后面的字符都像后 移動(dòng)字符串的長(zhǎng)度格。然后把字符串從pos位置開(kāi)始寫(xiě)入。
//插入字符串
string& insert(size_t pos, const char* str)
{ size_t len = strlen(str);
//判斷容量
if (_cacpcity< (len + _size))
{ AddCacpcity(len + _size);
}
//移動(dòng)len格
size_t end1 = _size+1;
size_t end2 = _size + len ;
while (pos< end1 )
{ _str[end2] = _str[end1-1] ;
end1--;
end2--;
}
int i = pos;
while (*str)
{ _str[i++] = *str++;
}
_size += len;
return *this;
}
刪除指定區(qū)間從pos位置開(kāi)始,刪除len個(gè)空間。那么我們需要先判斷 len是否大于pos后面的長(zhǎng)度,如果大于那就是后面全部刪除,那么我們只需要把pos位置置空成\0即可。如果不大于就說(shuō)明在中間刪除,那么就從pos的第len個(gè)位置開(kāi)始往pos后面的位置覆蓋,覆蓋到\0結(jié)束。
// 刪除
string& erase(size_t pos, size_t len)
{ //如果要?jiǎng)h除的長(zhǎng)度大于后面的剩余長(zhǎng)度
if (len >= _size - pos)
{ len = _size - pos;
_size -= len;
_str[pos] = '\0';
return *this;
}
//把后面的往前移,覆蓋式刪除
size_t begin = pos+len;
while (_str[begin])
{ _str[begin-len] = _str[begin];
begin++;
}
_size -= len;
return *this;
}
全部代碼:
namespace wyl
{class string
{public:
typedef char* iterator;
typedef const char* const_iterator;
//缺省的構(gòu)造函數(shù)
string(const char* str = "")
: _size(strlen(str))
,_cacpcity(_size)
{ //開(kāi)辟一塊內(nèi)存
_str = new char[_cacpcity + 1];
strcpy(_str, str);
}
//析構(gòu)函數(shù)
~string()
{ delete[] _str;
_str = nullptr;
_size = _cacpcity = 0;
}
//拷貝構(gòu)造
string(const string& s)
:_size(s._size)
, _cacpcity(s._cacpcity)
{ //開(kāi)辟一塊和s一樣的空間
_str = new char[_cacpcity+1];
strcpy(_str, s._str);
}
//賦值操作符重載
string& operator=(const string& s)
{ //如果不是自己給自己賦值
if (this != &s)
{ //創(chuàng)建一塊新空間
char* tmp = new char[s._cacpcity+1];
//拷貝
strcpy(tmp, s._str);
//銷(xiāo)毀舊空間
delete[] _str;
_str = tmp;
_size = s._size;
_cacpcity = s._cacpcity;
}
return *this;
}
//獲取長(zhǎng)度
size_t size()
{ return _size;
}
//下標(biāo)訪問(wèn)
char& operator[](size_t pos)
{ return _str[pos];
}
//只讀
const char& operator[](size_t pos) const
{ return _str[pos];
}
//迭代器開(kāi)始位置
iterator begin()
{ return _str;
}
const_iterator begin() const
{ return _str;
}
//迭代器末尾位置
iterator end()
{ return _str + _size;
}
const_iterator end()const
{ return _str + _size;
}
// 擴(kuò)容
void AddCacpcity(size_t newCacpcity)
{ char* str = new char[newCacpcity + 1];
strcpy(str, _str);
delete[] _str;
_str = str;
_cacpcity = newCacpcity;
}
//尾插一個(gè)字符
void push_back(char c)
{ //檢查容量
if (_size == _cacpcity)
{ AddCacpcity(_cacpcity == 0 ? 15 : _cacpcity * 2);
}
_str[_size] = c;
_size++;
_str[_size] = '\0';
}
string& operator+=(char c)
{ push_back(c);
return *this;
}
//追加一個(gè)字符串
void append(const char* str)
{ if (_cacpcity< (_size)+strlen(str))
{ AddCacpcity(_size + strlen(str));
}
strcpy(_str + _size, str);
_size += strlen(str);
}
string& operator+=(const char* str)
{ append(str);
return *this;
}
//+重載
string operator+(const char* str)
{ string s(*this);
s += str;
return s;
}
string operator+(const string& str)
{ string s(*this);
s += str._str;
return s;
}
//清空
void clear()
{ _str[0] = '\0';
_size = 0;
}
//字符串交換
void swap(string& s)
{ std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_cacpcity, s._cacpcity);
}
//以c的方式返回字符串
const char* c_str()const
{ return _str;
}
//判斷字符串是否為空
bool empty()const
{ return _str[0] == '\0';
}
//修改長(zhǎng)度
void resize(size_t n, char c = '\0')
{ //如果修改的值比當(dāng)前長(zhǎng)度小
if (n<= _size)
{ //截?cái)? _size = n;
_str[_size] = '\0';
}
//如果修改的值比當(dāng)前長(zhǎng)度大
else
{ //擴(kuò)容
if(n >_cacpcity)
{AddCacpcity(n);
}
//從size位置到n的位置設(shè)置為c
memset(_str + _size, c, n - _size);
//最后位置填上\0
_size = n;
_str[_size] = '\0';
}
}
//指定容量。只增加,減少不處理
void reserve(size_t n)
{ if (n >_cacpcity)
{ AddCacpcity(n);
}
}
//字符串比較函數(shù)重載
bool operator<(const string& s)
{ return strcmp(_str, s._str)< 0;
}
bool operator<=(const string& s)
{ return (*this< s) || (*this == s);
}
bool operator>(const string& s)
{ return !((*this)<= s);
}
bool operator>=(const string& s)
{ return !(*this< s);
}
bool operator==(const string& s)
{ return strcmp(_str, s._str) == 0;
}
bool operator!=(const string& s)
{ return !(*this == s);
}
// 返回c在string中第一次出現(xiàn)的位置
size_t find(char c, size_t pos = 0) const
{ for (int i = pos; i< _size; i++)
{ if (_str[i] == c)
return i;
}
return nops;
}
// 返回子串s在string中第一次出現(xiàn)的位置
size_t find(const char* s, size_t pos = 0) const
{ char* tmp = strstr(_str, s);
if (tmp == NULL)
return nops;
return tmp - _str;
}
// 在pos位置上插入字符c/字符串str,并返回該字符的位置
string& insert(size_t pos, char c)
{ //判斷容量
if (_size == _cacpcity)
{ AddCacpcity(_cacpcity == 0 ? 15 : _cacpcity * 2);
}
//pos位置后往后移
size_t end = _size + 1;
while (pos< end)
{ _str[end] = _str[end - 1];
end--;
}
_str[pos] = c;
_size++;
return *this;
}
//插入字符串
string& insert(size_t pos, const char* str)
{ size_t len = strlen(str);
//判斷容量
if (_cacpcity< (len + _size))
{ AddCacpcity(len + _size);
}
//移動(dòng)len格
size_t end1 = _size+1;
size_t end2 = _size + len ;
while (pos< end1 )
{ _str[end2] = _str[end1-1] ;
end1--;
end2--;
}
int i = pos;
while (*str)
{ _str[i++] = *str++;
}
_size += len;
return *this;
}
// 刪除
string& erase(size_t pos, size_t len)
{ //如果要?jiǎng)h除的長(zhǎng)度大于后面的剩余長(zhǎng)度
if (len >= _size - pos)
{ len = _size - pos;
_size -= len;
_str[pos] = '\0';
return *this;
}
//把后面的往前移,覆蓋式刪除
size_t begin = pos+len;
while (_str[begin])
{ _str[begin-len] = _str[begin];
begin++;
}
_size -= len;
return *this;
}
private:
char* _str;
size_t _size;
size_t _cacpcity;
static const size_t nops = -1;
};
}
總結(jié):string類(lèi)的細(xì)節(jié)還有很多,在這里只能簡(jiǎn)單實(shí)現(xiàn)一下。在實(shí)現(xiàn)的過(guò)程中需要注意的幾點(diǎn)。
1.避免內(nèi)存越界,否則析構(gòu)時(shí)銷(xiāo)毀會(huì)出錯(cuò)。
2.釋放new出來(lái)的內(nèi)存,避免內(nèi)存泄漏。
3.需要深拷貝,否則會(huì)出現(xiàn)析構(gòu)多次的情況。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)頁(yè)標(biāo)題:【C++】STL---string類(lèi)的模擬實(shí)現(xiàn)-創(chuàng)新互聯(lián)
網(wǎng)站地址:http://chinadenli.net/article14/hdgge.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、網(wǎng)站導(dǎo)航、Google、網(wǎng)站改版、面包屑導(dǎo)航、企業(yè)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容