【C++】STL---string類的模擬實現(xiàn)-創(chuàng)新互聯(lián)

目錄
  • 前言
  • 類的屬性
  • 構(gòu)造函數(shù)
    • 構(gòu)造函數(shù)
    • 析構(gòu)函數(shù)
    • 拷貝構(gòu)造函數(shù)
  • 操作符重載
    • 賦值操作符重載
    • 比較操作符重載
  • 獲取字符串長度
  • 下標訪問
  • 迭代器
  • 尾插一個字符
  • 追加字符串
  • 字符串清空
  • 字符串交換
  • 以C的方式返回字符
  • 判斷字符串是否為空
  • 修改長度
  • 指定大小擴容
  • 查找字符
  • 查找子串
  • 指定位置插入字符
  • 指定位置插入字符串
  • 刪除指定區(qū)間
  • 總結(jié):

創(chuàng)新互聯(lián)主營門頭溝網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,手機APP定制開發(fā),門頭溝h5成都小程序開發(fā)搭建,門頭溝網(wǎng)站營銷推廣歡迎門頭溝等地區(qū)企業(yè)咨詢前言

??string類,想必大家都不陌生,這是一個用來管理字符串的類。讓我們使用字符串時更方便,更遍歷。所以今天我們就來簡單的實現(xiàn)一下string類。


類的屬性

我們要管理一個字符串,那么首先得有一個字符串。所以我們用char* 類型的指針,來指向一個塊存儲字符串的地址。_size則記錄字符串的長度,_cacpcity 為字符串的空間容量

private:
		char* _str;
		size_t _size;
		size_t _cacpcity;
構(gòu)造函數(shù) 構(gòu)造函數(shù)

我們在實例化一個string對象的時候,可以string s("hello world");直接創(chuàng)建,也可以string s();使它初始時為空,所以我們可以用缺省的構(gòu)造函數(shù)。如果不傳參數(shù),那么默認初始化為空。

//缺省的構(gòu)造函數(shù) 
		string(const char* str = "")
			: _size(strlen(str))
			,_cacpcity(_size)
		{	//開辟一塊內(nèi)存
			_str = new char[_cacpcity + 1];//有效容量是cacpcity,要多一個用來存放\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)造,就是拷貝一個字符串 例如:string s1("hello world"); string s2(s1);。所以我們開辟一塊與要拷貝字符串一樣大小的空間,再把它一一復(fù)制給新字符串即可。

//拷貝構(gòu)造
		string(const string& s)
			:_size(s._size)
			, _cacpcity(s._cacpcity)
		{	//開辟一塊和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);
				//銷毀舊空間
				delete[] _str;
				_str = tmp;
				_size = s._size;
				_cacpcity = s._cacpcity;
			}
			return *this;
		}

當然也可以復(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);
		}
獲取字符串長度

直接返回_size 即可

//獲取長度
		size_t size()
		{	return _size;
		}
下標訪問

字符串也可以進行下標訪問,所以我們重載[]即可

//下標訪問
		char& operator[](size_t pos)
		{	return _str[pos];
		}

當然,如果訪問的是const修飾的字符串,那我們只能讀,不能寫。

//只讀
		const char& operator[](size_t pos) const
		{	return _str[pos];
		}
迭代器
//定義2個迭代器,一個是可讀可寫,一個是只讀
		typedef char* iterator;
		typedef const char* const_iterator;
//迭代器開始位置
		iterator begin()
		{	return _str;
		}
		const_iterator begin() const
		{	return _str;
		}

		//迭代器末尾位置
		iterator end()
		{	return _str + _size;
		}

		const_iterator end()const
		{	return _str + _size;
		}
尾插一個字符

就是在字符串末端插入一個字符,我們只需要在_size的位置插入,隨后_size++即可。不過要保證容量必須充足。

//尾插一個字符
		void push_back(char c)
		{	//檢查容量
			if (_size == _cacpcity)
			{		AddCacpcity(_cacpcity == 0 ? 15 : _cacpcity * 2);
			}
			_str[_size] = c;
			_size++;
			_str[_size] = '\0';
		}

擴容函數(shù)

void AddCacpcity(size_t newCacpcity)
		{		//末尾位置留一個\0,所以+1
				char* str = new char[newCacpcity + 1];
				//舊字符串的內(nèi)容拷貝到新字符串
				strcpy(str, _str);
				//銷毀舊字符串
				delete[] _str;
				_str = str;
				_cacpcity = newCacpcity;
		}
追加字符串

如果想在尾部追加字符串的話,我們可以實現(xiàn)一個 append()函數(shù)。

//追加一個字符串
		void append(const char* str)
		{	//檢查容量
			if (_cacpcity< (_size)+strlen(str))
			{		AddCacpcity(_size + strlen(str));
			}
			//直接在末尾的位置加上str
			strcpy(_str + _size, str);
			_size += strlen(str);
		}

然后我們可以重載 +=運算符,拿來復(fù)用 append()函數(shù)。

string& operator+=(const char* str)
		{	append(str);
			return *this;

		}

然后我們重載 +運算符,但需要注意的是,+運算符不改變當前字符串,所以我們要值返回。

//+重載
		string operator+(const char* str)
		{	string s(*this);
			s += str;

			return s;
		}
字符串清空

直接把第一個字符改成\0即可

//清空
		void clear()
		{	_str[0] = '\0';
			_size = 0;
		}
字符串交換

我們用std命名空間里面的swap函數(shù),對每個成員進行交換。

//字符串交換
		void swap(string& s)
		{	std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_cacpcity, s._cacpcity);
		}
以C的方式返回字符

c語言的字符串其實就是一個char*指針,遇到\0結(jié)束,所以我們直接返回str就可以了。

//以c的方式返回字符串
		const char* c_str()const
		{	return _str;
		}
判斷字符串是否為空

直接判斷第一個元素是否是 \0

//判斷字符串是否為空
		bool empty()const
		{	return _str[0] == '\0';
		}
修改長度

修改長度我們要分多種情況,一般長度減少時,我們不改變現(xiàn)有容量。容量不夠時,我們才增容。 如果 長度減少,或者不變,我們只需要把 減少的新長度給_size,然后把當前位置變成\0。如果是增加長度,我們要考慮容量,不夠的話需要增容,然后memset函數(shù)把增容的部分改成你指定的字符(默認\0)。

//修改長度
		void resize(size_t n, char c = '\0')
		{	//如果修改的值比當前長度小
			if (n<= _size)
			{		//截斷
				_size = n;
				_str[_size] = '\0';
			}
			//如果修改的值比當前長度大
			else
			{		//擴容
				if(n >_cacpcity)
				{AddCacpcity(n);
				}
				//從size位置到n的位置設(shè)置為c
				memset(_str + _size, c, n - _size);
				//最后位置填上\0
				_size = n;
				_str[_size] = '\0';
			}
		}
指定大小擴容

之前寫過一個擴容函數(shù),直接把指定的大小傳過去即可。還是老規(guī)矩,減少不處理。

//指定容量。只增加,減少不處理
		void reserve(size_t n)
		{	if (n >_cacpcity)
			{		AddCacpcity(n);
			}
		}
查找字符

該查找只會找到從指定位置開始,第一個出現(xiàn)的字符。如果要查找第二個,那么就在第一個字符的后面開始查找。

// 返回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是一個無符號的數(shù),代表找不到返回的值。

static const size_t nops = -1;
查找子串

C語言中有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位置后面的字符都往后移動一格,隨后把字符放進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;
		}
指定位置插入字符串

插入字符是都往后移動一格,插入字符串那就是把pos位置后面的字符都像后 移動字符串的長度格。然后把字符串從pos位置開始寫入。

//插入字符串
		string& insert(size_t pos, const char* str)
		{	size_t len = strlen(str);
			//判斷容量
			if (_cacpcity< (len + _size))
			{		AddCacpcity(len + _size);
			}
			//移動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位置開始,刪除len個空間。那么我們需要先判斷 len是否大于pos后面的長度,如果大于那就是后面全部刪除,那么我們只需要把pos位置置空成\0即可。如果不大于就說明在中間刪除,那么就從pos的第len個位置開始往pos后面的位置覆蓋,覆蓋到\0結(jié)束。

// 刪除
		string& erase(size_t pos, size_t len)
		{	//如果要刪除的長度大于后面的剩余長度
			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)
		{	//開辟一塊內(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)
		{	//開辟一塊和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);
				//銷毀舊空間
				delete[] _str;
				_str = tmp;
				_size = s._size;
				_cacpcity = s._cacpcity;
			}
			return *this;
		}

		//獲取長度
		size_t size()
		{	return _size;
		}
		
		//下標訪問
		char& operator[](size_t pos)
		{	return _str[pos];
		}
		//只讀
		const char& operator[](size_t pos) const
		{	return _str[pos];
		}

		//迭代器開始位置
		iterator begin()
		{	return _str;
		}
		const_iterator begin() const
		{	return _str;
		}

		//迭代器末尾位置
		iterator end()
		{	return _str + _size;
		}

		const_iterator end()const
		{	return _str + _size;
		}

		// 擴容
		void AddCacpcity(size_t newCacpcity)
		{		char* str = new char[newCacpcity + 1];
				strcpy(str, _str);
				delete[] _str;
				_str = str;
				_cacpcity = newCacpcity;
		}

		//尾插一個字符
		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;
		}

		//追加一個字符串
		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';
		}

		//修改長度
		void resize(size_t n, char c = '\0')
		{	//如果修改的值比當前長度小
			if (n<= _size)
			{		//截斷
				_size = n;
				_str[_size] = '\0';
			}
			//如果修改的值比當前長度大
			else
			{		//擴容
				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);
			}
			//移動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)
		{	//如果要刪除的長度大于后面的剩余長度
			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類的細節(jié)還有很多,在這里只能簡單實現(xiàn)一下。在實現(xiàn)的過程中需要注意的幾點。

1.避免內(nèi)存越界,否則析構(gòu)時銷毀會出錯。
2.釋放new出來的內(nèi)存,避免內(nèi)存泄漏。
3.需要深拷貝,否則會出現(xiàn)析構(gòu)多次的情況。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)頁標題:【C++】STL---string類的模擬實現(xiàn)-創(chuàng)新互聯(lián)
網(wǎng)站地址:http://bm7419.com/article14/hdgge.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化網(wǎng)站導航、Google、網(wǎng)站改版、面包屑導航企業(yè)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化