国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C++——string模擬實現(xiàn)

這篇具有很好參考價值的文章主要介紹了C++——string模擬實現(xiàn)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言:上篇文章我們對string類及其常用的接口方法的使用進行了分享,這篇文章將著重進行對這些常用的接口方法的內(nèi)部細節(jié)進行分享和模擬實現(xiàn)。


目錄

一.基礎(chǔ)框架

二.遍歷字符串

1.[]運算符重載

2.迭代器

3.范圍for

三.常用方法

1.增加

2.刪除

3.調(diào)整

4.交換

5.查找

6.截取

7.比較

四.流操作

總結(jié)


一.基礎(chǔ)框架

首先我們要清楚,string類定義的是字符串對象,所以就類似于線性表,有長度,容量等成員變量:

	class string
	{
	public:
		//構(gòu)造函數(shù)
		string(const char* str = "")
			:_size(strlen(str))
		{
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}
		//析構(gòu)函數(shù)
		~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = 0;
			_capacity = 0;
		}
		//轉(zhuǎn)換C語言格式
		const char* c_str() const
		{
			return _str;
		}
		//清除
		void clear()
		{
			_size = 0;
			_str[_size] = '\0';
		}
        //深拷貝s2(s1)
		string(const string& s)
		{
			_str = new char[_capacity + 1];
			strcpy(_str, s._str);
			_size = s._size;
			_capacity = s._capacity;
		}
		//s1 = s2
		string& operator=(const string& s)
		{
			char* tmp = new char[s._capacity + 1];
			strcpy(tmp, s._str);
			delete[] _str;
			_str = tmp;
			_size = s._size;
			_capacity = s._capacity;
		}
	private:

		char* _str;
		size_t _size;
		size_t _capacity;
	};

其中不能缺少的就是構(gòu)造函數(shù)、析構(gòu)函數(shù)和拷貝構(gòu)造函數(shù),這里我們直接用缺省函數(shù)將無參構(gòu)造和帶參構(gòu)造結(jié)合為一體

但是由于如果我們不自己寫一個深拷貝函數(shù),就會默認執(zhí)行淺拷貝成員函數(shù),這樣會導(dǎo)致兩個字符串同源,所以需要給出深拷貝函數(shù)。

值得注意的是真正的strlen不會統(tǒng)計字符串中的‘\0’,所以我們給_str開空間時應(yīng)+1。


二.遍歷字符串

1.[]運算符重載

上篇文章中我們知道遍歷字符串有三種方式:[]運算符重載,迭代器,以及范圍for。下面我們就來一一實現(xiàn)。

首先我們需要將字符串的長度方法size和容量方法capacity定義出來:

		//長度
		size_t size() const
		{
			return _size;
		}
		//容量
		size_t capacity() const
		{
			return _capacity;
		}

一般情況下當方法里調(diào)用的成員無需發(fā)生改變時,都會將這些方法用const修飾。?

[]運算符重載自然是通過運算符重載函數(shù)來實現(xiàn):

		//遍歷
		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}

這里我們添加assert函數(shù)來斷言,防止越界訪問。

返回值使用引用格式,能夠?qū)崿F(xiàn)可讀可寫

C++——string模擬實現(xiàn),c++,開發(fā)語言

?但此時會產(chǎn)生一個問題,如果我想讓一個const修飾的對象來調(diào)用該方法,就會導(dǎo)致權(quán)限放大而出錯。

如果給這個方法加上const,那我們就無法修改其內(nèi)容了。

所以我們使用函數(shù)重載,為其單獨創(chuàng)造一個只讀的const修飾的函數(shù)方法

		const char& operator[](size_t pos) const
		{
			assert(pos < _size);
			return _str[pos];
		}

2.迭代器

我們已經(jīng)了解迭代器的本質(zhì)和指針類似,我們這里我們就先用指針的實現(xiàn)迭代器的功能

		//迭代器
		typedef char* iterator;
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}

用typedef將char*指針重命名為iterator,再定義出begin和end兩個方法,便能實現(xiàn)迭代器功能:

C++——string模擬實現(xiàn),c++,開發(fā)語言

值得注意的是,const修飾的對象想要調(diào)用迭代器,也必須調(diào)用對應(yīng)const修飾的迭代器,所以迭代器我們也需要進行重載

		typedef const char* const_iterator;
		const_iterator begin() const
		{
			return _str;
		}
		const_iterator end() const
		{
			return _str + _size;
		}

迭代器這樣的模擬實現(xiàn)方法也能幫助我們更深入的了解其內(nèi)部構(gòu)造。


3.范圍for

范圍for實際上并沒有那么復(fù)雜,其本質(zhì)也是迭代器

所以只要有迭代器的存在,保證iterator、begin。end這些單詞不變,不管是我們自己實現(xiàn)的還是C++庫內(nèi)的,都可以使用范圍for:

C++——string模擬實現(xiàn),c++,開發(fā)語言

但是如果iterator、begin。end這些單詞發(fā)生變化,就無法在使用范圍for。?


三.常用方法

1.增加

增加無非有四種方式:尾插單個字符push_back、尾插字符串a(chǎn)ppend和+=運算符重載,以及任意位置的插入insert,增加字符就意味著要考慮擴容問題,這就要實現(xiàn)reserve方法來配合使用。

尾插單個字符可以通過每次擴容兩倍容量,但是如果尾插一個長度為len的字符串,每次擴容兩倍或是更多倍都并不一定就能滿足容量, 所以這里直接擴容size+len個空間

		//擴容
		void reserve(size_t len)
		{
			if (len > _capacity)
			{
				char* tmp = new char[len + 1];
				strcpy(tmp, _str);
				delete[] _str;
				_str = tmp;
				_capacity = len;
			}
		}
		//尾插單字符
		void push_back(char ch)
		{
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}
			_str[_size] = ch;
			_size++;
			_str[_size] = '\0';
		}
		//尾插字符串
		void append(const char* str)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				reserve(_size + len);
			}
			strcpy(_str + _size, str);
			_size += len;
		}

因為字符串的末尾都要有'\0'的存在,所以擴容時,要始終保持實際容量比字符串容量多1

當尾插單個字符時,因為該字符是直接覆蓋了'\0',所以尾插之后要再字符串末尾再補上'\0'

而尾插字符串時,因為strcpy在進行拷貝時也會直接將'\0'拷貝,所以無需再補。?

+=運算符的重載,就是以上述兩個方法為基層的擴展

		//+=運算符重載
		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}
		string& operator+=(const char* str)
		{
			append(str);
			return *this;
		}

測試如下:

C++——string模擬實現(xiàn),c++,開發(fā)語言


任意位置的插入, 則需要進行字符串的挪動

		//任意位置插入
		//單字符
		void insert(char ch, size_t pos)
		{
			assert(pos <= _size);
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}
			size_t end = _size + 1;
			while (end > pos)
			{
				_str[end] = _str[end - 1];
				end--;
			}
			_str[pos] = ch;
			_size++;

		}
		//字符串
		void insert(const char* str, size_t pos)
		{
			assert(pos <= _size);
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				reserve(_size + len);
			}
			size_t end = _size + len;
			while (end >= pos + len)
			{
				_str[end] = _str[end - len];
				end--;
			}
			for (size_t i = 0; i < len; i++)
			{
				_str[pos++] = str[i];
			}
			_size += len;
		}

在進行字符串插入時,要注意的是我們要從pos位置將后邊的字符向后空出len個位置

同時我們不能使用strcpy進行插入,因為它會將要插入的字符串的'\0'一并插入,導(dǎo)致一個位置的字符被覆蓋,所以這里我們采用循環(huán)插入。

?測試如下:

C++——string模擬實現(xiàn),c++,開發(fā)語言


2.刪除

string類中只有一個常用的刪除方法:erase,它的功能是在指定位置后刪除若干個字符,如果沒有指定要刪除的字符數(shù)量,則默認將后邊的字符全刪除

		//刪除
		void erase(size_t pos, size_t len = npos)
		{
			assert(pos < _size);
			if (len == npos || len >= _size - pos)
			{
				_str[pos] = '\0';
				_size = pos;
			}
			strcpy(_str + pos, _str + pos + len);
			_size -= len;
		}

采用缺省函數(shù)的方式,如果我們沒有傳入len,他就會等于npos,npos在C++中表示一個常數(shù),表示不存在的位置。

如果len無傳入或是len的長度不小于要刪除的字符串長度,這都可以認為是要將pos位置后的字符串全部刪除,此時便可直接在pos位置用'\0'

使用npos需要在類中定義public成員變量:

?? ?public:
?? ??? ?static const int npos;

以及在類外賦值:

?? ?const int string::npos = -1;

?測試如下:

C++——string模擬實現(xiàn),c++,開發(fā)語言


3.調(diào)整

在string中有一個方法可以兼?zhèn)湓黾雍蛣h除兩種簡單功能,名為resize,它的作用是調(diào)整字符串

傳入一個參數(shù)n,和一個字符ch,如果當前字符串長度小于n,則擴容字符串長度至n個,并將多出的位置用字符ch填充,如果不傳字符ch,則默認填充'\0'。

如果當前字符串長度大于n,則將字符串長度縮減到n

		//調(diào)整
		void resize(size_t n, char ch = '\0')
		{
			if (n <= _size)
			{
				_str[n] = '\0';
				_size = n;
			}
			else
			{
				reserve(n);
				for (size_t i = _size; i < n; i++)
				{
					_str[i] = ch;
				}
				_str[n] = '\0';
				_size = n;
			}
		}

測試如下:

C++——string模擬實現(xiàn),c++,開發(fā)語言


4.交換

自己實現(xiàn)string類中的swap交換函數(shù),有一個很好用的方法,那就是借用std庫中的swap函數(shù)

		//交換
		void swap(string& s)
		{
			std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_capacity, s._capacity);
		}

?因為std庫中的swap函數(shù)是模版函數(shù),可以進行任意類型的交換,所以我們直接投機取巧,將兩者的成員變量依次進行交換,測試如下:

C++——string模擬實現(xiàn),c++,開發(fā)語言

?但是這樣的寫法并不是我們所熟悉的swap(s1,s2),所以我們可以通過函數(shù)重載擴展一下

		void swap(string& x, string& y)
		{
			x.swap(y);
		}

值得注意的是這個函數(shù)要寫在string類的外邊,按照就近原則去調(diào)用它,否則會默認先調(diào)用庫里的模版swap函數(shù)。?

測試如下:

C++——string模擬實現(xiàn),c++,開發(fā)語言


5.查找

string類中的查找也分為查找單個字符、查找字符串以及在指定的pos位置向后去查找找到返回下標,找不到返回npos,所以依然要使用缺省函數(shù)

		//查找
		//單字符
		size_t find(char ch, size_t pos = 0) const
		{
			assert(pos < _size);
			for (size_t i = pos; i < _size; i++)
			{
				if (_str[i] == ch)
					return i;
			}
			return npos;
		}
		//字符串
		size_t find(const char* str, size_t pos = 0) const
		{
			assert(pos < _size);
			const char* p = strstr(_str + pos, str);
			if (p)
				return p - _str;
			else
				return npos;
		}

在查找字符串時我們使用到了strstr函數(shù)其返回值為所找到的字符串的首字符指針。

測試如下:

C++——string模擬實現(xiàn),c++,開發(fā)語言


6.截取

截取字符串方法substr,其作用是從字符串的pos位置開始向后截取len長度的字符,當然無論是pos位置還是長度len都可以沒有,依然是缺省函數(shù)

		//截取
		string substr(size_t pos = 0, size_t len = npos)
		{
			string sub;
			if (len >= _size - pos)
			{
				for (size_t i = pos; i < _size; i++)
				{
					sub += _str[i];
				}
			}
			else
			{
				for (size_t i = pos; i < pos + len; i++)
				{
					sub += _str[i];
				}
			}
			return sub;
		}

測試如下:

C++——string模擬實現(xiàn),c++,開發(fā)語言


7.比較

字符串直接的比較需要我們實現(xiàn)運算符重載

	bool operator==(const string& s1, const string& s2)
	{
		int ret = strcmp(s1.c_str(), s2.c_str());
		return ret == 0;
	}
	bool operator<(const string& s1, const string& s2)
	{
		int ret = strcmp(s1.c_str(), s2.c_str());
		return ret < 0;
	}
	bool operator<=(const string& s1, const string& s2)
	{
		return s1 < s2 || s1 == s2;
	}
	bool operator>(const string& s1, const string& s2)
	{
		return !(s1 <= s2);
	}
	bool operator>=(const string& s1, const string& s2)
	{
		return !(s1 < s2);
	}
	bool operator!=(const string& s1, const string& s2)
	{
		return !(s1 == s2);
	}

這一塊的方法,我們建議實現(xiàn)在類外,定義兩個參數(shù),這樣能夠允許一個字符串和一個string對象進行比較。

因為在類內(nèi)定義因為默認類內(nèi)的成員函數(shù)的第一個參數(shù)都是隱藏的非靜態(tài)string對象,所以靜態(tài)的普通字符串傳入就會使權(quán)限放大而出錯。

測試如下:

?C++——string模擬實現(xiàn),c++,開發(fā)語言


四.流操作

直接上代碼:

	//流輸出
	ostream& operator<<(ostream& out, const string& s)
	{
		for (auto ch : s)
		{
			out << ch;
		}
		return out;
	}
	//流提取
	istream& operator>>(istream& in, string& s)
	{
		s.clear();
		char ch;
		ch = in.get();
		while (ch != ' ' && ch != '\n')
		{
			s += ch;
			ch = in.get();
		}
		return in;
	}

輸出較為簡單,直接使用范圍for循環(huán)輸出。

而對于提取到的字符會直接覆蓋s中原有的字符串,所以要先進行清除;此外,因為in默認會跳過空格和回車而不提取它們,這會導(dǎo)致死循環(huán),所以我們使用in.get()函數(shù)來提取。

測試如下:

C++——string模擬實現(xiàn),c++,開發(fā)語言


總結(jié)

關(guān)于string類及其內(nèi)部常用方法的模擬實現(xiàn)就分享到這里啦。

最后希望能得到您的一鍵三連支持,我們下期再見!文章來源地址http://www.zghlxwxcb.cn/news/detail-838908.html

到了這里,關(guān)于C++——string模擬實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【C++】string類模擬實現(xiàn)

    【C++】string類模擬實現(xiàn)

    ?? 作者簡介:一名在后端領(lǐng)域?qū)W習,并渴望能夠?qū)W有所成的追夢人。 ?? 個人主頁:不 良 ?? 系列專欄:??C++ ???Linux ?? 學習格言:博觀而約取,厚積而薄發(fā) ?? 歡迎進來的小伙伴,如果小伙伴們在學習的過程中,發(fā)現(xiàn)有需要糾正的地方,煩請指正,希望能夠與諸君一同

    2024年02月15日
    瀏覽(19)
  • C++: string的模擬實現(xiàn)

    C++: string的模擬實現(xiàn)

    注意:本文會用到strcpy,strstr,strncpy,strlen這幾個函數(shù) 我會說明它們的功能和用法 如果大家想要徹底了解這幾個函數(shù) 可以看一下我之前的博客: 征服C語言字符串函數(shù)(超詳細講解,干貨滿滿) 比如說leetcode字符串相加這道題 既然string的模擬實現(xiàn)對我們這么重要 那就讓我們一起踏上

    2024年02月04日
    瀏覽(20)
  • 【C++】:string的模擬實現(xiàn)

    【C++】:string的模擬實現(xiàn)

    朋友們、伙計們,我們又見面了,本期來給大家解讀一下有關(guān)string的模擬實現(xiàn),如果看完之后對你有一定的啟發(fā),那么請留下你的三連,祝大家心想事成! C 語 言 專 欄: C語言:從入門到精通 數(shù)據(jù)結(jié)構(gòu)專欄: 數(shù)據(jù)結(jié)構(gòu) 個? 人? 主? 頁?: stackY、 C + + 專 欄? ?: C++ Linux 專

    2024年02月08日
    瀏覽(21)
  • C++模擬實現(xiàn)string類

    C++模擬實現(xiàn)string類

    在C語言中,字符串是以’\\0’結(jié)尾的字符的集合,為了操作方便,C標準庫中已經(jīng)提供了一些str系列的庫函 數(shù),但是這些庫函數(shù)與字符串是分離的,不符合面向?qū)ο缶幊痰乃枷?,而且底層空間需要用戶自己管理,很可能會造成越界訪問。 C++中對于string的定義為:typedef basic_s

    2024年02月13日
    瀏覽(50)
  • C++ string類模擬實現(xiàn)

    C++ string類模擬實現(xiàn)

    目錄 string類成員變量 一.構(gòu)造函數(shù) 二.析構(gòu)函數(shù) 三.拷貝構(gòu)造 四.size(),capacity() 五.operator [ ] 六. operator = ?七.字符串比較 ?八.reserve() 九.push_back(),append() 十.operator+= ?十一.insert() ?十二.迭代器 ?十二.erase() 十三.swap() ?十四.find() 十五.流提取,流輸出 十六

    2024年02月14日
    瀏覽(19)
  • C++:string類模擬實現(xiàn)

    C++:string類模擬實現(xiàn)

    1.獲取容器大小(_size)和容量(_capacity) 2.擴容(reserve) 3.更改容器大小 1.尾插 2.指定位置插入 3.指定位置刪除 4.清空 5.交換兩個對象 1.截取子串 2.取得C格式字符串 3.賦值

    2024年02月13日
    瀏覽(17)
  • [C++]string及其模擬實現(xiàn)

    [C++]string及其模擬實現(xiàn)

    目錄 string及其模擬實現(xiàn):: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1.構(gòu)造函數(shù) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?2.拷貝構(gòu)造函數(shù) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?3.賦值運算符重載 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?4.析構(gòu)函數(shù) ? ? ? ?

    2024年02月07日
    瀏覽(24)
  • C++ 模擬實現(xiàn)string類

    目錄 一、類的定義 二、初始化銷毀 1、構(gòu)造函數(shù) 2、辨析三種定義? 3、析構(gòu)函數(shù) 三、賦值? 1、拷貝構(gòu)造函數(shù) 2、賦值運算符 四、成員訪問 ?operator[ ] 五、比較大小判斷相等 六、容量操作? 1、size() 2、reserve 3、push_back 4、append 5、加等運算符? 6、C風格 7、insert 插入字符? 插入

    2024年02月05日
    瀏覽(14)
  • 【C++學習手札】模擬實現(xiàn)string

    【C++學習手札】模擬實現(xiàn)string

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????????????? ?? 慕斯主頁 : 修仙—別有洞天 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????????????????? ?? 今日夜電波 :缶ビール—みゆな ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    2024年02月04日
    瀏覽(297)
  • C++ string模擬實現(xiàn)(部分接口)

    C++的string類是一個類模板,用于表示和操作任何字符類型的字符串。 string類內(nèi)部使用字符數(shù)組來存儲字符,但是所有的內(nèi)存管理,分配和空終止都由string類自己處理 ,所以使用起來很方便。string類的長度可以在運行時改變,因為它使用動態(tài)內(nèi)存分配類似于vector。 string類提供

    2024年02月13日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包