??博客主頁:小智_x0___0x_
??歡迎關注:??點贊??收藏??留言
??系列專欄:C++初階
??代碼倉庫:小智的代碼倉庫
模擬實現(xiàn)
成員變量
string類中需要三個成員變量分別記錄元素個數(shù)、容量和內(nèi)容。還需要一個size_t
類型npos-1表示整型的最大值。
private:
size_t _size;//個數(shù)
size_t _capacity;//容量
char* _str;//字符數(shù)組
public:
const static size_t npos;
const size_t string::npos = -1;//npos代表的整型的最大值。
構造函數(shù)
//構造函數(shù)
string(const char* str = "")
{
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity + 1];
memcpy(_str, str, _size + 1);
}
這段代碼是string
類的構造函數(shù)。構造函數(shù)是在創(chuàng)建對象時自動調(diào)用的函數(shù),用于初始化對象的數(shù)據(jù)成員。
這個構造函數(shù)接受一個const char*
類型的參數(shù)str
,默認值為一個空字符串。
在函數(shù)體內(nèi),首先使用strlen
函數(shù)獲取參數(shù)str
的長度,并將其賦值給私有成員變量_size
,表示字符串的個數(shù)。
接著,將_capacity
的值初始化為_size
,表示容量與個數(shù)相等。
然后,使用new
運算符動態(tài)分配一個大小為_capacity + 1
的字符數(shù)組,并將指針賦值給私有成員變量_str
。
最后,使用memcpy
函數(shù)將參數(shù)str
中的字符串復制到新分配的字符數(shù)組中,并在最后一個位置設置為\0
,表示字符串的結束。
因此,這個構造函數(shù)的作用是將一個C風格的字符串轉換為string
對象。
析構函數(shù)
//析構函數(shù)
~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
這段代碼是string
類的析構函數(shù)。析構函數(shù)是在對象被銷毀時自動調(diào)用的函數(shù),用于釋放對象占用的資源。
在函數(shù)體內(nèi),首先使用delete[]
運算符釋放_str
指向的動態(tài)分配的字符數(shù)組。
然后,將_str
賦值為nullptr
,表示指針不再指向任何內(nèi)存地址。
最后,將_size
和_capacity
的值都設為0,表示對象已經(jīng)被銷毀。
因此,這個析構函數(shù)的作用是釋放string
對象占用的內(nèi)存空間,并將對象的數(shù)據(jù)成員重置為初始值。
拷貝構造
//拷貝構造
string(const string& str)
{
_str = new char[str._capacity + 1];
memcpy(_str, str._str, str._size + 1);
_size = str._size;
_capacity = str._capacity;
}
這段代碼是string
類的拷貝構造函數(shù)??截悩嬙旌瘮?shù)是在創(chuàng)建一個新對象并用已有對象進行初始化時自動調(diào)用的函數(shù),用于將一個對象的值復制到另一個對象中。
這個拷貝構造函數(shù)接受一個const string&
類型的引用參數(shù)str
,表示要被復制的對象。
在函數(shù)體內(nèi),首先使用new
運算符動態(tài)分配一個大小為str._capacity + 1
的字符數(shù)組,并將指針賦值給私有成員變量_str
。
然后,使用memcpy
函數(shù)將參數(shù)str
中的字符串復制到新分配的字符數(shù)組中,并在最后一個位置設置為\0
,表示字符串的結束。
接著,將_size
和_capacity
的值分別賦值為參數(shù)str
對應的私有成員變量值,表示新對象的大小和容量與原對象相同。
因此,這個拷貝構造函數(shù)的作用是創(chuàng)建一個新的string
對象,并將參數(shù)str
中的數(shù)據(jù)成員值復制到新對象中。
c_str()
//返回C語言類型的字符串
const char* c_str() const
{
return _str;
}
這段代碼是string
類的c_str
函數(shù),用于返回一個指向以空字符結尾的字符數(shù)組的指針,該字符數(shù)組包含了當前string
對象中存儲的字符串。
這個函數(shù)沒有參數(shù),返回值為const char*
類型。
在函數(shù)體內(nèi),直接返回私有成員變量_str
,該變量是一個指向字符數(shù)組的指針,指向當前string
對象中存儲的字符串。
由于返回值是一個指向常量字符的指針,因此該函數(shù)被聲明為const
類型成員函數(shù),表示該函數(shù)不會修改對象的數(shù)據(jù)成員。
因此,這個函數(shù)的作用是返回當前string
對象中存儲的字符串的C語言類型表示。
size()
//返回長度
size_t size() const
{
return _size;
}
這段代碼是string
類的size
函數(shù),用于返回當前string
對象中存儲的字符串的長度,即字符的個數(shù)。
這個函數(shù)沒有參數(shù),返回值為size_t
類型。
在函數(shù)體內(nèi),直接返回私有成員變量_size
,該變量表示當前string
對象中存儲的字符串的長度。
由于該函數(shù)不會修改對象的數(shù)據(jù)成員,因此被聲明為const
類型成員函數(shù)。
因此,這個函數(shù)的作用是返回當前string
對象中存儲的字符串的長度。
重載[]運算符
//重載[]運算符
char& operator[](size_t pos)
{
assert(pos < _size);
return _str[pos];
}
const char& operator[](size_t pos) const
{
assert(pos < _size);
return _str[pos];
}
這段代碼是string
類對[]
運算符進行重載的實現(xiàn)。通過重載[]
運算符,可以使用類似數(shù)組下標的方式訪問和修改string
對象中的字符。
這個代碼片段包含了兩個重載版本,一個是非常量版本,另一個是常量版本。
在非常量版本中,重載的[]
運算符接受一個size_t
類型的參數(shù)pos
,表示要訪問或修改的字符的索引位置。
在函數(shù)體內(nèi),首先使用assert
函數(shù)來檢查索引位置是否越界,即是否小于字符串的長度_size
。
然后,返回私有成員變量_str
中索引位置為pos
的字符的引用,以便可以修改該字符的值。
在常量版本中,重載的[]
運算符也接受一個size_t
類型的參數(shù)pos
。
在函數(shù)體內(nèi),同樣使用assert
函數(shù)來檢查索引位置是否越界。
然后,返回私有成員變量_str
中索引位置為pos
的字符的常量引用,以保證該字符的值不會被修改。
因此,這段代碼的作用是重載string
類的[]
運算符,使得可以通過下標訪問和修改字符串中的字符。
擴容函數(shù)
reserve()
//擴容函數(shù)
void reserve(size_t n)
{
if (n > _capacity)
{
char* tmp = new char[n + 1];
memcpy(tmp, _str, _size+1);
delete[] _str;
_str = tmp;
_capacity = n;
}
}
這段代碼是string
類的reserve
函數(shù),用于增加當前string
對象的容量,以便可以存儲更多的字符。
這個函數(shù)接受一個size_t
類型的參數(shù)n
,表示要增加的容量大小。
在函數(shù)體內(nèi),首先判斷參數(shù)n
是否大于當前對象的容量_capacity
。如果是,則需要進行擴容操作。
在擴容操作中,首先使用new
運算符動態(tài)分配一個大小為n+1
的字符數(shù)組,并將指針賦值給臨時變量tmp
。
然后,使用memcpy
函數(shù)將當前對象中的字符串復制到新分配的字符數(shù)組中,這個函數(shù)比strcpy
更快,因為不需要在找到\0
之后繼續(xù)復制。
接著,使用delete[]
運算符釋放當前對象中原來的字符數(shù)組。
最后,將指向新分配的字符數(shù)組的指針賦值給私有成員變量_str
,表示當前對象已經(jīng)擴容。同時,將私有成員變量_capacity
的值更新為新的容量大小。
因此,這個函數(shù)的作用是增加當前string
對象的容量,以便可以存儲更多的字符。
resize()
void resize(size_t n, char ch = '\0')
{
if (n < _size)
{
_size = n;
_str[_size] = '\0';
}
else
{
reserve(n);
for (size_t i = _size; i < n; i++)
{
_str[i] = ch;
}
_size = n;
_str[_size] = '\0';
}
}
這段代碼是string
類的resize
函數(shù),用于改變當前string
對象中存儲的字符串的長度。
這個函數(shù)接受一個size_t
類型的參數(shù)n
,表示要改變的字符串長度。同時,還接受一個可選的char
類型參數(shù)ch
,表示在擴展字符串時要填充的字符,默認值為\0
。
在函數(shù)體內(nèi),首先判斷參數(shù)n
是否小于當前對象中存儲的字符串的長度_size
。如果是,則需要縮小字符串的長度。
在縮小字符串長度的操作中,首先將私有成員變量_size
的值更新為n
,表示當前對象中存儲的字符串的長度已經(jīng)縮小到了n
。
然后,在新的字符串長度之后添加一個空字符\0
,以便可以正確地表示新的字符串。
如果參數(shù)n
大于等于當前對象中存儲的字符串的長度_size
,則需要擴展字符串的長度。
在擴展字符串長度的操作中,首先調(diào)用成員函數(shù)reserve(n)
來確保當前對象中分配的內(nèi)存空間足夠存儲新的字符串。
然后,在當前對象中存儲的字符串的末尾添加字符ch
,直到新字符串的長度達到了n
。
最后,將私有成員變量_size
的值更新為n
,表示當前對象中存儲的字符串的長度已經(jīng)擴展到了n
。同時,在新字符串長度之后添加一個空字符\0
,以便可以正確地表示新的字符串。
因此,這個函數(shù)的作用是改變當前string
對象中存儲的字符串的長度,并根據(jù)需要在新字符串中添加或刪除字符。
尾插
push_back()
//push_back()
void push_back(char ch)
{
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : 2 * _capacity);
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
}
這段代碼是string
類的push_back
函數(shù),用于向當前string
對象中添加一個字符。
這個函數(shù)接受一個char
類型的參數(shù)ch
,表示要添加的字符。
在函數(shù)體內(nèi),首先判斷當前對象中存儲的字符串的長度_size
是否等于當前對象的容量_capacity
。如果是,則需要進行擴容操作。
在擴容操作中,調(diào)用成員函數(shù)reserve(_capacity == 0 ? 4 : 2 * _capacity)
來增加當前對象的容量。如果當前對象的容量為0,則增加容量到4;否則,將容量增加到原來的2倍。
然后,在私有成員變量_str
中索引位置為_size
的位置添加字符ch
,表示將該字符添加到當前對象的末尾。
接著,將私有成員變量_size
的值加1,表示當前對象中存儲的字符串的長度已經(jīng)增加了1個字符。
最后,在新字符串長度之后添加一個空字符\0
,以便可以正確地表示新的字符串。
因此,這個函數(shù)的作用是向當前string
對象中添加一個字符,并在需要時自動擴容以確保有足夠的空間存儲該字符。
append()
void append(const char* str)
{
size_t len = strlen(str);
if (len + _size > _capacity)
{
reserve(len + _size);
}
memcpy(_str + _size, str, len + 1);
_size += len;
}
這段代碼是string
類的append
函數(shù),用于將一個以空字符結尾的C字符串附加到當前string
對象中。
這個函數(shù)接受一個const char*
類型的參數(shù)str
,表示要附加的C字符串。
在函數(shù)體內(nèi),首先使用strlen
函數(shù)計算出C字符串的長度,并將其存儲在臨時變量len
中。
然后,判斷將要附加的C字符串的長度加上當前對象中存儲的字符串的長度是否大于等于當前對象的容量。如果是,則需要進行擴容操作。
在擴容操作中,調(diào)用成員函數(shù)reserve(len + _size)
來增加當前對象的容量,以確保有足夠的空間存儲將要附加的C字符串。
接著,使用memcpy
函數(shù)將C字符串復制到當前對象中存儲的字符串的末尾。這個函數(shù)比strcpy
更快,因為不需要在找到\0
之后繼續(xù)復制。
最后,將私有成員變量_size
的值增加C字符串的長度len
,表示當前對象中存儲的字符串的長度已經(jīng)增加了C字符串的長度。
因此,這個函數(shù)的作用是將一個以空字符結尾的C字符串附加到當前string
對象中,并在需要時自動擴容以確保有足夠的空間存儲該字符串。
重載+=運算符
//重載+=運算符
string& operator+=(char ch)
{
push_back(ch);
return *this;
}
string& operator+=(const char* str)
{
append(str);
return *this;
}
這里都是都是復用了上面的push_back()和append()
插入函數(shù)insert
插入字符
//在指定位置插入n個字符
void insert(size_t pos, size_t n, char ch)
{
assert(pos <= _size);
if (_size + n > _capacity)
{
reserve(_size + n);
}
size_t end = _size;
while (end >= pos && end != npos)//npos整型最大值
{
_str[end + n] = _str[end];
--end;
}
for (size_t i = pos; i < pos + n; i++)
{
_str[i] = ch;
}
_size += n;
}
這段代碼是string
類的insert
函數(shù),用于在當前string
對象中的指定位置插入指定數(shù)量的字符。
這個函數(shù)接受三個參數(shù):一個size_t
類型的參數(shù)pos
,表示要插入字符的位置;一個size_t
類型的參數(shù)n
,表示要插入的字符數(shù)量;一個char
類型的參數(shù)ch
,表示要插入的字符。
在函數(shù)體內(nèi),首先使用assert
函數(shù)檢查要插入的位置是否在當前對象中存儲的字符串的范圍內(nèi)。如果不在范圍內(nèi),則程序會終止。
然后,判斷將要插入的字符數(shù)量加上當前對象中存儲的字符串的長度是否大于等于當前對象的容量。如果是,則需要進行擴容操作。
在擴容操作中,調(diào)用成員函數(shù)reserve(_size + n)
來增加當前對象的容量,以確保有足夠的空間存儲將要插入的字符。
接著,從當前對象中存儲的字符串的末尾開始,將每個字符向后移動n個位置。這個操作是為了給將要插入的字符騰出空間。
然后,在指定位置插入n個字符。這個操作使用了一個for循環(huán),從pos開始,循環(huán)n次,每次將要插入的字符添加到當前對象中存儲的字符串中。
最后,將私有成員變量_size
的值增加n,表示當前對象中存儲的字符串的長度已經(jīng)增加了n個字符。
需要注意的是,在while循環(huán)中使用了變量npos
,這個變量是一個常量,表示無效的位置。在這個函數(shù)中,它被用來表示當前對象中存儲的字符串已經(jīng)被遍歷完了。
因此,這個函數(shù)的作用是在當前string
對象中指定位置插入指定數(shù)量的字符,并在需要時自動擴容以確保有足夠的空間存儲這些字符。
插入字符串
//在指定位置插入一個字符串
void insert(size_t pos, const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
size_t end = _size;
while (end >= pos && end != npos)//npos表示整型最大值
{
_str[end + len] = _str[end];
--end;
}
for (size_t i = pos; i < pos + len; i++)
{
_str[i] = str[i - pos];
}
_size += len;
}
這段代碼是string
類的insert
函數(shù),用于在當前string
對象中的指定位置插入一個C風格字符串。
該函數(shù)首先檢查要插入的位置是否在當前對象中存儲的字符串的范圍內(nèi),然后計算要插入的字符串長度。如果將要插入的字符數(shù)量加上當前對象中存儲的字符串的長度大于等于當前對象的容量,則需要進行擴容操作。
在擴容操作中,調(diào)用成員函數(shù)reserve(_size + len)
來增加當前對象的容量,以確保有足夠的空間存儲將要插入的字符串。
接著,從當前對象中存儲的字符串的末尾開始,將每個字符向后移動len個位置。這個操作是為了給將要插入的字符串騰出空間。
然后,在指定位置插入字符串。這個操作使用了一個for循環(huán),從pos開始,循環(huán)len次,每次將要插入的字符添加到當前對象中存儲的字符串中。
最后,將私有成員變量_size
的值增加len,表示當前對象中存儲的字符串的長度已經(jīng)增加了len個字符。
erase
//指定位置刪除n個字符
void erase(size_t pos, size_t len = npos)
{
assert(pos <= _size);
if (len == npos || pos + len >= _size)
{
_str[pos] = '\0';
_size = pos;
_str[_size] = '\0';
}
else
{
size_t end = pos + len;
while (end <= _size)
{
_str[pos++] = _str[end++];
}
_size -= len;
}
}
這段代碼是string
類的erase
函數(shù),用于從當前string
對象中的指定位置開始刪除指定數(shù)量的字符。
這個函數(shù)接受兩個參數(shù):一個size_t
類型的參數(shù)pos
,表示要刪除字符的起始位置;一個size_t
類型的參數(shù)len
,表示要刪除的字符數(shù)量,其默認值為npos
,表示刪除從起始位置到當前對象末尾的所有字符。
在函數(shù)體內(nèi),首先使用assert
函數(shù)檢查要刪除的位置是否在當前對象中存儲的字符串的范圍內(nèi)。如果不在范圍內(nèi),則程序會終止。
然后,判斷要刪除的字符數(shù)量是否等于npos
或者要刪除的字符數(shù)量加上要刪除的起始位置是否大于等于當前對象中存儲的字符串的長度。如果是,則將當前對象中存儲的字符串從指定位置開始到末尾的所有字符都刪除,并將當前對象中存儲的字符串的長度更新為指定位置。
否則,從指定位置開始,將要刪除的字符向后移動len個位置。這個操作使用了一個while循環(huán),從pos開始,循環(huán)到pos+len結束,每次將要刪除的字符向后移動一個位置。
最后,將私有成員變量_size
的值減去len,表示當前對象中存儲的字符串的長度已經(jīng)減少了len個字符。
需要注意的是,在if語句中,將pos位置處的字符設置為’\0’,是為了在刪除操作后保證當前對象中存儲的字符串以’\0’結尾。
查找函數(shù)find
查找字符
//在指定位置查找一個字符
size_t find(char ch, size_t pos = 0)
{
assert(pos < _size);
for (size_t i = pos; i < _size; i++)
{
if (_str[i] == ch)
{
return i;
}
}
return npos;
}
這段代碼是string
類的find
函數(shù),用于在當前string
對象中的指定位置開始查找一個字符。
這個函數(shù)接受兩個參數(shù):一個char
類型的參數(shù)ch
,表示要查找的字符;一個size_t
類型的參數(shù)pos
,表示從哪個位置開始查找,其默認值為0。
在函數(shù)體內(nèi),首先使用assert
函數(shù)檢查要查找的起始位置是否在當前對象中存儲的字符串的范圍內(nèi)。如果不在范圍內(nèi),則程序會終止。
然后,使用一個for循環(huán)從指定位置開始遍歷當前對象中存儲的字符串。如果遍歷到的字符等于要查找的字符,則返回該字符在當前對象中存儲的字符串中的位置。
如果整個字符串都被遍歷完了,還沒有找到要查找的字符,則返回常量npos
,表示未找到。
需要注意的是,在這個函數(shù)中,變量npos
表示整型最大值,被用來表示未找到要查找的字符。
查找字符串
//在指定位置查找一個字符串
size_t find(const char* str, size_t pos = 0)
{
assert(pos < _size);
const char* ptr = strstr(_str + pos, str);
if (ptr)
{
return ptr - _str;
}
else
{
return npos;
}
}
這段代碼是string
類的find
函數(shù),用于在當前string
對象中的指定位置開始查找一個字符串。
這個函數(shù)接受兩個參數(shù):一個const char*
類型的參數(shù)str
,表示要查找的字符串;一個size_t
類型的參數(shù)pos
,表示從哪個位置開始查找,其默認值為0。
在函數(shù)體內(nèi),首先使用assert
函數(shù)檢查要查找的起始位置是否在當前對象中存儲的字符串的范圍內(nèi)。如果不在范圍內(nèi),則程序會終止。
然后,使用C標準庫函數(shù)strstr
在當前對象中存儲的字符串中查找要查找的字符串。這個函數(shù)返回一個指向第一次出現(xiàn)要查找的字符串的指針,如果沒找到則返回NULL
。
如果找到了要查找的字符串,則返回該字符串在當前對象中存儲的字符串中的位置。由于strstr
函數(shù)返回的是指向要查找的字符串在當前對象中存儲的字符串中的位置的指針,因此需要將這個指針減去當前對象中存儲的字符串的首地址,才能得到該字符串在當前對象中存儲的字符串中的位置。
如果整個字符串都被遍歷完了,還沒有找到要查找的字符串,則返回常量npos
,表示未找到。
需要注意的是,在這個函數(shù)中,變量npos
表示整型最大值,被用來表示未找到要查找的字符串。
substr()
//截取一段字符串
string substr(size_t pos = 0, size_t len = npos)
{
assert(pos < _size);
size_t n = len;
if (len == npos || pos + len > _size)
{
n = _size - pos;
}
string tmp;
tmp.reserve(n);
for (size_t i = pos; i < pos + n; i++)
{
tmp += _str[i];
}
return tmp;
}
這段代碼是string
類的substr
函數(shù),用于從當前string
對象中的指定位置開始獲取一個子字符串。
這個函數(shù)接受兩個參數(shù):一個size_t
類型的參數(shù)pos
,表示子字符串的起始位置,其默認值為0;一個size_t
類型的參數(shù)len
,表示子字符串的長度,其默認值為npos
,表示獲取從起始位置到當前對象末尾的所有字符。
在函數(shù)體內(nèi),首先使用assert
函數(shù)檢查要獲取子字符串的起始位置是否在當前對象中存儲的字符串的范圍內(nèi)。如果不在范圍內(nèi),則程序會終止。
然后,判斷要獲取的子字符串的長度是否等于npos
或者要獲取的子字符串的長度加上要獲取的子字符串的起始位置是否大于當前對象中存儲的字符串的長度。如果是,則將要獲取子字符串的長度設置為從指定位置開始到當前對象末尾的所有字符的長度。
接著,創(chuàng)建一個臨時的string
對象tmp
,并使用reserve
函數(shù)為這個對象分配足夠的內(nèi)存空間。這個內(nèi)存空間大小為要獲取子字符串的長度。
最后,使用一個for循環(huán)從指定位置開始,將要獲取的子字符串中的每個字符添加到臨時的string
對象中。循環(huán)結束后,返回臨時的string
對象。
需要注意的是,在這個函數(shù)中,變量npos
表示整型最大值,被用來表示要獲取從起始位置到當前對象末尾的所有字符。
重載<運算符
bool operator<(const string& s) const
{
int ret = memcmp(_str, s._str, _size < s._size ? _size : s._size);
return ret == 0 ? _size < s._size : ret < 0;
}
這段代碼是string
類的小于運算符重載函數(shù),用于比較當前string
對象和另一個string
對象的大小關系。
這個函數(shù)接受一個const string&
類型的參數(shù)s
,表示要比較的另一個string
對象。
在函數(shù)體內(nèi),使用C標準庫函數(shù)memcmp
比較當前對象中存儲的字符串和另一個對象中存儲的字符串的前綴部分,比較的長度為兩個字符串中長度更短的那個。返回值為0表示兩個字符串相等,返回值小于0表示當前對象中存儲的字符串小于另一個對象中存儲的字符串,返回值大于0表示當前對象中存儲的字符串大于另一個對象中存儲的字符串。
然后,使用三目運算符判斷兩個字符串是否相等。如果相等,則比較兩個字符串的長度,返回長度更短的那個字符串小于另一個字符串。如果不相等,則返回比較結果。
需要注意的是,在這個函數(shù)中,使用了C標準庫函數(shù)memcmp
來進行字符串的比較,而不是使用循環(huán)遍歷比較每個字符。這是因為memcmp
函數(shù)可以利用CPU的特殊指令集進行優(yōu)化,從而提高比較效率。
重載==運算符
bool operator==(const string& s) const
{
return _size == s._size
&& memcmp(_str, s._str, _size) == 0;
}
這段代碼是string
類的等于運算符重載函數(shù),用于比較當前string
對象和另一個string
對象是否相等。
這個函數(shù)接受一個const string&
類型的參數(shù)s
,表示要比較的另一個string
對象。
在函數(shù)體內(nèi),首先比較當前對象中存儲的字符串的長度和另一個對象中存儲的字符串的長度是否相等,如果不相等,則直接返回false
,表示兩個對象不相等。
然后,使用C標準庫函數(shù)memcmp
比較當前對象中存儲的字符串和另一個對象中存儲的字符串是否相等。比較的長度為兩個字符串中長度更短的那個。返回值為0表示兩個字符串相等,返回值不為0表示兩個字符串不相等。
最后,使用邏輯運算符&&
將前面兩個比較的結果合并起來,如果兩個比較都為真,則返回true
,表示兩個對象相等;否則返回false
,表示兩個對象不相等。
重載<=、>、>=、!=運算符
bool operator<=(const string& s) const
{
return *this < s || *this == s;
}
bool operator>(const string& s) const
{
return !(*this <= s);
}
bool operator>=(const string& s) const
{
return !(*this < s);
}
bool operator!=(const string& s) const
{
return !(*this == s);
}
上面這些代碼也都是復用了'>'和'=='
的代碼。
string中的swap函數(shù)
void swap(string& s)
{
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
這段代碼是string
類的swap
函數(shù),用于交換當前string
對象和另一個string
對象的內(nèi)容。
這個函數(shù)接受一個string&
類型的參數(shù)s
,表示要交換內(nèi)容的另一個string
對象。
在函數(shù)體內(nèi),使用C++標準庫函數(shù)std::swap
來交換當前對象中存儲的字符串和另一個對象中存儲的字符串、當前對象中存儲的字符串的長度和另一個對象中存儲的字符串的長度、當前對象中存儲的字符串的容量和另一個對象中存儲的字符串的容量。
重載=運算符
第一種重載方法
string& operator=(const string& s)
{
if (this != &s)
{
char* tmp = new char[s._capacity + 1];
memcpy(tmp, s._str, s._size+1);
delete[] _str;
_str = tmp;
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
第二種重載方法
string& operator=(const string& s)
{
if (this != &s)
{
string tmp(s);
swap(tmp);
}
return *this;
}
第三種重載方法
string& operator=(string tmp)
{
swap(tmp);
return *this;
}
迭代器
typedef char* iterator;
typedef const char* const_iterator;
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
const_iterator begin() const
{
return _str;
}
const_iterator end() const
{
return _str + _size;
}
這段代碼是string
類的迭代器相關函數(shù),用于提供對string
對象中存儲的字符串字符的訪問。
在這個代碼中,首先使用typedef
關鍵字定義了兩個類型別名iterator
和const_iterator
,分別表示可變迭代器和不可變迭代器。可變迭代器可以用于修改string
對象中存儲的字符串,而不可變迭代器則不能。
然后,定義了兩個函數(shù)begin()
和end()
,分別返回可變迭代器和不可變迭代器。這兩個函數(shù)用于返回一個指向當前對象中存儲的字符串的首字符的指針和一個指向當前對象中存儲的字符串的尾字符的下一個字符的指針。
流插入
ostream& operator<<(ostream& out, const string& s)
{
for (auto ch : s)
{
out << ch;
}
return out;
}
這段代碼是string
類的輸出運算符重載函數(shù),用于將當前string
對象的內(nèi)容輸出到輸出流中。
這個函數(shù)接受一個ostream&
類型的參數(shù)out
,表示要輸出到的輸出流,以及一個const string&
類型的參數(shù)s
,表示要輸出的string
對象。
在函數(shù)體內(nèi),使用C++11中的范圍for循環(huán)遍歷當前對象中存儲的字符串中的每個字符。對于每個字符,使用輸出運算符<<
將其輸出到輸出流中。
最后,返回輸出流的引用。
流提取
istream& operator>>(istream& in, string& s)
{
s.clear();
char ch = in.get();
// 處理前緩沖區(qū)前面的空格或者換行
while (ch == ' ' || ch == '\n')
{
ch = in.get();
}
char buff[128];
int i = 0;
while (ch != ' ' && ch != '\n')
{
buff[i++] = ch;
if (i == 127)
{
buff[i] = '\0';
s += buff;
i = 0;
}
ch = in.get();
}
if (i != 0)
{
buff[i] = '\0';
s += buff;
}
return in;
}
這段代碼是一個重載了輸入流操作符(>>)的函數(shù),用于從輸入流中讀取字符串數(shù)據(jù)。:文章來源:http://www.zghlxwxcb.cn/news/detail-547412.html
- 首先,函數(shù)會清空字符串
s
,以確保其為空。 - 接下來,使用
in.get()
函數(shù)讀取輸入流中的一個字符,并將其賦值給變量ch
。 - 在一個循環(huán)中,檢查字符
ch
是否是空格或換行符。如果是,則繼續(xù)調(diào)用in.get()
讀取下一個字符,直到遇到非空格和非換行符的字符為止,這樣可以跳過輸入流中前面的空格或換行。 - 創(chuàng)建一個字符數(shù)組
buff
,起初為空。然后,在另一個循環(huán)中,將非空格和非換行符的字符存入buff
中,并逐個增加索引i
。 - 檢查索引
i
是否達到了上限(127),即是否已經(jīng)存滿了buff
數(shù)組。如果是,將buff
數(shù)組最后一個字符設置為字符串結束符(‘\0’),并將其內(nèi)容添加到字符串s
的末尾。然后,重置索引i
為0。 - 繼續(xù)執(zhí)行循環(huán),直到遇到空格或換行符。在每次循環(huán)迭代時,將非空格和非換行符的字符存入
buff
中,并逐個增加索引i
。 - 最后,檢查索引
i
是否不為0,即是否有未添加到字符串s
的字符。如果是,將buff
數(shù)組最后一個字符設置為字符串結束符(‘\0’),并將其內(nèi)容添加到字符串s
的末尾。 - 返回輸入流
in
,以支持鏈式輸入操作。
總體來說,該代碼通過循環(huán)讀取輸入流中的字符,并根據(jù)空格和換行符的位置將字符拼接成一個字符串。這樣,使用該函數(shù)可以便捷地從輸入流中讀取一個帶有空格或換行符分隔的字符串。
??小結??
今天我們認識了C++string類的模擬實現(xiàn)
相信大家看完有一定的收獲。種一棵樹的最好時間是十年前,其次是現(xiàn)在!
把握好當下,合理利用時間努力奮斗,相信大家一定會實現(xiàn)自己的目標!加油!創(chuàng)作不易,辛苦各位小伙伴們動動小手,三連一波????~~~
,本文中也有不足之處,歡迎各位隨時私信點評指正!
本節(jié)課的代碼已上傳gitee倉庫文章來源地址http://www.zghlxwxcb.cn/news/detail-547412.html
到了這里,關于【C++】String類的模擬實現(xiàn)。的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!