中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

【C++】string詳細(xì)介紹及模擬實現(xiàn)string類-創(chuàng)新互聯(lián)

【C++】string詳細(xì)介紹及模擬實現(xiàn)string類

創(chuàng)新互聯(lián)服務(wù)項目包括清河網(wǎng)站建設(shè)、清河網(wǎng)站制作、清河網(wǎng)頁制作以及清河網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,清河網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到清河省份的部分城市,未來相信會繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!文章目錄
  • 【C++】string詳細(xì)介紹及模擬實現(xiàn)string類
    • 1.什么是string
    • 2.string常用接口介紹
      • 2.1string類對象的常見構(gòu)造
      • 2.2string類對象的容量操作
      • 2.3string類對象的訪問及遍歷操作
      • 2.4string類對象的修改操作
      • 2.5string類非成員函數(shù)
    • 3.string類的模擬實現(xiàn)
      • PS.以下標(biāo)出的函數(shù)需要特別注意
        • 3.1構(gòu)造函數(shù)
        • 3.2重載=
        • 3.3重載[],reserve,resize
        • 3.4push_back,append
        • 3.5迭代器
        • 3.6insert
        • 3.7find
        • 3.8流提取,流輸入
    • 4.string模擬實現(xiàn)代碼

1.什么是string

提到string,我們先回頭看下C語言中的字符串

C語言中,字符串是以’\0’結(jié)尾的一些字符的集合,為了操作方便,C標(biāo)準(zhǔn)庫中提供了一些str系列的庫函數(shù),
但是這些庫函數(shù)與字符串是分離開的,不太符合OOP的思想,而且底層空間需要用戶自己管理,稍不留神可
能還會越界訪問

在OJ中,有關(guān)字符串的題目基本以string類的類型出現(xiàn),而且在常規(guī)學(xué)習(xí)中,為了簡單、方便、快捷、基本都在使用string類,很少有人去使用C庫中的字符串操作函數(shù)。

讓我們一起來認(rèn)識下string類

image-20221126185518478

1.字符串是表示字符序列的類。

2.標(biāo)準(zhǔn)的字符串類提供了對此類對象的支持,其接口類似于標(biāo)準(zhǔn)字符器的接口,但添加了專門用于操作單字節(jié)字符字符串的設(shè)計特性。

3.string類是使用char(即作為它的字符類型,使用它的默認(rèn)char_traits和分配器類型 )。

4.string類是basic_string模板類的一個實例,它使用char來實例化basic_string模板類,并用char_traits和allocator作為basic_string的默認(rèn)參數(shù)。

總結(jié):

1)string是表示字符串的字符串類

2)該類的接口與常規(guī)容器的接口基本相同,再添加了一些專門用來操作string的常規(guī)操作

3) string在底層實際是:basic_string模板類的別名,typedef basic_stringstring;

4)不能操作多字節(jié)或者變長字符的序列

在使用string類時,必須包含#include頭文件以及using namespace std;

若想了解更詳細(xì)內(nèi)容,請查詢正規(guī)文檔: string - C++ Reference (cplusplus.com)

2.string常用接口介紹

以下內(nèi)容均根據(jù)官方文檔中對string類的詳細(xì)介紹進(jìn)行整合編寫,如有錯誤,還望各位大佬指出,多多包涵

2.1string類對象的常見構(gòu)造

1)string() 功能:構(gòu)造空的string類對象,即空字符串

2)string(const char* s) 功能:用C-string來構(gòu)造string類對象

3)string(size_t n,char c) 功能:string類對象中包含n個字符c

4)string(const string& s) 功能:拷貝構(gòu)造函數(shù)

image-20221126193404045

圖中以四種不同的方式創(chuàng)建了5個string類對象,接下來讓我們分析一下各種創(chuàng)建方式

首先,我們可以看到s1打印在屏幕是一串空字符,而string s1創(chuàng)建時正好沒有給s1內(nèi)容,為一個空字符串;

s2很明顯,以Hello world為內(nèi)容初始化了;s3以5個X來進(jìn)行初始化。 s4和s5通過拷貝構(gòu)造函數(shù)對s2和s3進(jìn)行拷貝,存放的字符串內(nèi)容與其一樣。

2.2string類對象的容量操作

1) size 功能:返回字符串有效字符長度

image-20221126200248863

此接口功能簡單,不做過多贅述。

2)length 功能:返回字符串有效字符長度

image-20221126200605424

PS: length與size接口功能一樣,都是返回字符串有效字符長度。

3)capacity 功能:返回空間總大小

image-20221126201957948

這里我們可以看出size接口返回的值與capacity接口返回的值不同,往后我們再詳細(xì)分析原因。

4)empty 功能:檢測字符串是否為空串

image-20221126203407529

圖中g(shù)etline不懂的同學(xué)可以暫時理解為cin/scanf

讓我們測試一下,該接口的功能。

1

我們可以得知,empty接口功能,當(dāng)字符串為空返回真,不為空則返回假。

5)clear 功能:清空有效字符

image-20221126204255732

很明顯,使用clear接口之后,s1中的字符串內(nèi)容全部清理干凈了。

我們可以將clear理解為一個大掃除,會將目標(biāo)對象中的字符串全部清理干凈,“一個不?!保遣粫淖兛臻g大小。

6)reserve 功能:為字符串預(yù)留空間

image-20221126210243747

第63行中,我們使用reserve接口將s1空間擴(kuò)大到30,但m2的值卻是31,這是為什么?

image-20221126213331143

這里為什么m2的值沒有發(fā)生改變,明明用過了reserve接口?

接下來,讓我們一探究竟

image-20221126213437469

仔細(xì)閱讀,我們會得知,只有當(dāng)n大于當(dāng)前的capacity時,才會對其進(jìn)行預(yù)留空間的操作,并且預(yù)留空間是否正好為n也是未知數(shù),可能會比n大(正如我上面用的測試用例,n為30,預(yù)留空間卻成了31);當(dāng)n小于當(dāng)前的capacity,reserve接口不會做任何事情。

7)resize 功能:將有效字符的個數(shù)改成n個,多出的空間用字符c填充

image-20221126214643435

resize接口與reserve接口就不一樣了

在n小于capacity情況下,都將直接修改你字符串的個數(shù)(不是空間大?。⑶医財嗄愕淖址?;

在n大于capcacity情況下,resize也會幫你擴(kuò)容空間大小,并且你可以選擇是否填充字符來補滿剩余的空間大小。

image-20221126215121911

string類對象的容量操作相關(guān)接口就介紹到這。

注意:

1.size()與length()方法底層實現(xiàn)原理完全相同,引入size()的原因是為了與其他容器的接口保持一致,一般情況下基本都是用size()。

2.clear()只是將string中有效字符清空,不改變底層空間大小。

3.resize(size_t n) 與 resize(size_t n, char c)都是將字符串中有效字符個數(shù)改變到n個,不同的是當(dāng)字符個數(shù)增多時:resize(n)用0來填充多出的元素空間,resize(size_t n, char c)用字符c來填充多出的元素空間。注意:resize在改變元素個數(shù)時,如果是將元素個數(shù)增多,可能會改變底層容量的大小,如果是將元素個數(shù)減少,底層空間大小不變

4.reserve(size_t res_arg=0):為string預(yù)留空間,不改變有效元素個數(shù),當(dāng)reserve的參數(shù)小于string的底層空間總大小時,reserver不會改變?nèi)萘看笮 ?/font>

2.3string類對象的訪問及遍歷操作

1)operator[] 功能:返回pos位置的字符,const string類對象調(diào)用

image-20221126220640472

string類中對[]進(jìn)行重載,讓其返回pos位置的字符。 讓string[i]變成數(shù)組一樣(char[i])可以直接通過下標(biāo)訪問

讓我們看下調(diào)試展示,是否能到達(dá)我們所說的效果

1

很顯然,string[i]正如一個數(shù)組一樣可以通過下標(biāo)i逐一訪問。

2)begin+end

image-20221126223316133

begin接口獲得第一個字符的迭代器,end接口獲取最后一個字符下一個位置的迭代器。

用a記錄下第一個迭代器的位置,用b記錄下最后一個字符下一個位置的迭代器的位置

然后計算b-a得出的結(jié)果是否為該string類字符串的長度呢? 結(jié)果為是,這樣看來迭代器與指針有點異曲同工之妙。

再看下面一部分

image-20221126223657875

正如你想象的一樣,將str里面的內(nèi)容逐一打印出來了。

用for循環(huán)把迭代器的位置從begin位置逐漸向end位置移動,并將其對應(yīng)解引用的字符打印出來,

這樣看來越來越像指針了 :)

3)rbegin+rend

這兩個接口與 begin+end 屬于“逆行”關(guān)系。

rbegin接口返回一個逆向迭代器,指向最后一個字符;rend接口返回一個逆向迭代器,指向第一個元素的前一個位置。

image-20221127190740632

上圖應(yīng)該能讓大家更清楚的理解 “逆行” 關(guān)系。

2.4string類對象的修改操作

1) push back 功能:在字符串后尾插入字符c

image-20221127191840112

這與我們之前學(xué)過的數(shù)據(jù)結(jié)構(gòu),棧,隊列里面的pushback一樣,同樣是在數(shù)據(jù)尾部插入一個對應(yīng)的數(shù)據(jù)。

image-20221127192017447

也可以配著循環(huán)玩玩 😃

需要注意的是,push back在字符串空間不夠的時候會自動擴(kuò)容

image-20221127193157013

2)append 功能:在字符串后追加一個字符串

image-20221127195814278

往字符串后追加字符時使用append,可以有多種方式來進(jìn)行操作

image-20221127200243139

3)operator+= 功能:在字符串后追加字符串str

在對于C語言中內(nèi)置類型,我們知道 a+=b,等價于a=a+b

對于string類,要想往后增加字符或字符串是否只能使用上面介紹的兩個接口呢?

那我們是否能將字符串也實現(xiàn)該功能,str1+=str2 ,答案是可以的

image-20221127203542491

4)c_str 功能:返回C格式字符串

image-20221128183146833

image-20221128183240073

5)find+npos 功能:從字符串pos位置開始往后找字符c,返回該字符在字符串中的位置

find即為查找功能,我們?nèi)粝朐谀硞€字符串中查找某個字符用find即可。

image-20221128183739052

有一點需要注意的是,find接口默認(rèn)從字符串首個字符開始查詢,我們也可以對其修改第一次開始查詢的位置。

image-20221128183913464

我們對s1第一次查詢的位置進(jìn)行了修改,在這個位置后面沒有‘y’字符,這個時候編譯器返回了一個隨機值

這個時候我們需要知道,在string類中,存在著npos這樣一個值。

image-20221128184426018

“until the end of the string”

6)rfind 功能:從字符串pos位置開始往前找字符c,返回該字符在字符串中的位置

rfind和find同樣是屬于“逆行”的關(guān)系,rfind就是從字符串末尾開始查詢字符c,與find不同的僅僅就是查詢方向。

image-20221128185134803

7)substr 功能:在str中從pos位置開始,截取n個字符,然后將其返回

image-20221128185506923

注意:

1.在string尾部追加字符時,s.push_back? / s.append(1, c) / s += 'c’三種的實現(xiàn)方式差不多,一般情況下string類的+=操作用的比較多,+=操作不僅可以連接單個字符,還可以連接字符串。

2.對string操作時,如果能夠大概預(yù)估到放多少字符,可以先通過reserve把空間預(yù)留好 。

2.5string類非成員函數(shù)

1)operator+ 功能:將各個字符串連接在一起

這個接口可以將“支離破碎”的多個字符串合在一起

image-20221128191549372

可以是定義好的字符串,也可以是未定義的字符串。

2)getline 功能:獲取一行字符串

在C++中cin常來作為輸入,但我們在輸入字符串時,難免會遇到輸入空格的情況,但cin遇到空格/回車時會自動結(jié)束,將\n存放在緩沖區(qū),所以為了避免這個問題,string類中就有g(shù)etline接口,在輸入時即使碰到空格也不會停止,會將空格存放在字符串中。

PS:上面的幾個接口大家了解一下,下面的OJ題目中會有一些體現(xiàn)他們的使用。string類中還有一些其他的操作,這里不一一列舉,大家在需要用到時不明白了查文檔即可。

string類以及相關(guān)常用接口就結(jié)束到這里。

接下來讓我們嘗試模擬string類的實現(xiàn)。**

3.string類的模擬實現(xiàn)

為了與庫里的某些函數(shù)命名沖突,我們在自己的命名空間里完成模擬實現(xiàn)string類

PS.以下標(biāo)出的函數(shù)需要特別注意 3.1構(gòu)造函數(shù)

image-20221128200706268

需要注意的是這里我們不使用malloc,選擇用new,需要手動將str拷貝到_str中,開辟的空間內(nèi)存也需要多一個用來存放’\0’,string不會自動以’\0’結(jié)束。

3.2重載=

image-20221128203305617

記得先進(jìn)行判斷_str是否還留有空間哦,空間不足,需要開辟新的空間,剩余細(xì)節(jié)與上述構(gòu)造函數(shù)相似。

3.3重載[],reserve,resize

image-20221129104139243

image-20221128204842610

3.4push_back,append

image-20221129104212983

3.5迭代器

image-20221129105607336

image-20221129105635356

范圍for循環(huán)

image-20221129110155584

以前覺得迭代器1好像很神秘,但是實現(xiàn)起來就是這么簡單。

3.6insert

插入字符

image-20221129114812307

插入字符串

image-20221129114825766

3.7find

查找字符

image-20221129124400430

查找字符串

image-20221129124516137

3.8流提取,流輸入

image-20221129125217229

4.string模擬實現(xiàn)代碼

最后給出全部代碼,供大家參考

#pragma once
#include#include
namespace YYz
{class string
	{public:
		typedef char* iterator;
		iterator begin()
		{	return _str;
		}
		iterator end()
		{	return _str + _size;
		}
		string(const char* str="")//構(gòu)造函數(shù)
		{	_size = strlen(str);
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}
		string(const string& s)//拷貝構(gòu)造
		{	_str = new char[s._capacity + 1];
			_size = s._size;
			_capacity = s._capacity;
			strcpy(_str, s._str);
		}

		string& operator=(const string& s)
		{	if (_capacity == _size)
			{		char* tmp = new char[s._capacity + 1];
				strcpy(tmp,s._str);
				delete[]_str;
				_str = tmp;
				_size = s._size;
				_capacity = s._capacity;
			}
			return *this;
		}
		char& operator[](size_t pos)
		{	assert(_size< pos);
			return _str[pos];
		}

		void reserve(size_t n)
		{	if (_capacity< n)
			{		char* tmp = new char[n + 1];
				strcpy(tmp, _str);
				delete[]_str;
				_str = tmp;
				_capacity = n;
			}
		}
		void resize(size_t n,char ch='\0')
		{	if (n >_size)
			{		reserve(n);
				for (size_t i = _size; i< n; ++i)
				{_str[i] = ch;
				}
			}
			else
			{		_size = n;
				_str[n] = '\0';
			}
		}
		void push_back(char ch)
		{	if (_size == _capacity)
			{		size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;
				reserve(newcapacity);
			}
			_str[_size] = ch;
			_size++;
			_str[_size] = '\n';
		}
		void append(const char* str)
		{	size_t len = strlen(str);
			if (_size + len >_capacity)
			{		reserve(_size + len);
			}
			strcpy(_size + _str, str);
			_size += len;
		}
		string& operator+=(char ch)
		{	push_back(ch);
			return *this;
		}
		string& operator+=(const char* ch)
		{	append(ch);
			return *this;
		}
		string& insert(size_t pos, char ch)
		{	assert(pos<= _size);
			if (_size == _capacity)
			{		size_t newcapacity = _capacity == 0 ? 4: 2 * _capacity;
				reserve(newcapacity);
			}
			size_t end = _size+1;
			while (end >pos)
			{		_str[end] = _str[end - 1];
				end--;
			}
			_str[pos] = ch;
			_size++;
			return *this;
		}
		string& insert(size_t pos, const char* str)
		{	int len = strlen(str);
			if (_size + len< _capacity)
			{		reserve(_size + len);
			}
			size_t end = _size + len;
			while (end >pos + len - 1)
			{		_str[end] = _str[end - 1];
				end--;
			}
			strncpy(_str + pos, str, len);
			_size += len;
			return *this;
		}

		const char* c_str()
		{	return _str;
		}
		size_t size() const
		{	return _size;
		}

		size_t capacity() const
		{	return _capacity;
		}
		~string()//析構(gòu)函數(shù)
		{	delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}
		string& erase(size_t pos, size_t len = npos)
		{	assert(pos<= _size);
			if (len == npos || pos + len >= _size)
			{		_str[pos] = '\0';
				_size = pos;
			}
			else
			{		strcpy(_str + pos, _str + pos+len);
				_size -= len;
			}
			return *this;
		}
		size_t find(char ch, size_t pos = 0) const
		{	assert(pos< _size);
			while (pos< _size)
			{		if (_str[pos] == ch)
				{return pos;
				}

				++pos;
			}

			return npos;
		}
		size_t find(const char* str, size_t pos = 0) const
		{	assert(pos< _size);
			const char* ptr = strstr(_str + pos, str);
			if (ptr == nullptr)
			{		return npos;
			}
			else
			{		return ptr - _str;
			}
		}
		void clear()
		{	_size = 0;
			_str[0] = '\0';
		}
	private:
		char* _str;
		size_t _size;
		size_t _capacity;
		const static size_t npos = -1;
	};
}
ostream& operator<<(ostream& out, const string& s)
{for (size_t i = 0; i< s.size(); ++i)
	{out<< s[i];
	}

	return out;
}
istream& operator>>(istream& in, string& s)
{s.clear();
	char buff[128] = {'\0' };
	size_t i = 0;
	char ch = in.get();
	while (ch != ' ' && ch != '\n')
	{if (i == 127)
		{	// 滿了
			s += buff;
			i = 0;
		}

		buff[i++] = ch;

		ch = in.get();
	}

	if (i >0)
	{buff[i] = '\0';
		s += buff;
	}

	return in;
}

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

新聞名稱:【C++】string詳細(xì)介紹及模擬實現(xiàn)string類-創(chuàng)新互聯(lián)
標(biāo)題路徑:http://www.rwnh.cn/article40/dciceo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計域名注冊、網(wǎng)站收錄商城網(wǎng)站、品牌網(wǎng)站設(shè)計品牌網(wǎng)站建設(shè)

廣告

聲明:本網(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)

大荔县| 石楼县| 阳原县| 乾安县| 略阳县| 阿拉善盟| 日照市| 上犹县| 固安县| 泽普县| 托克逊县| 泾阳县| 湘乡市| 沅江市| 温州市| 准格尔旗| 自贡市| 泸溪县| 玉屏| 金乡县| 福清市| 于田县| 红河县| 攀枝花市| 鄢陵县| 石狮市| 祁阳县| 荥阳市| 长子县| 蓝田县| 枝江市| 萨迦县| 锡林郭勒盟| 茌平县| 高邮市| 嘉禾县| 北碚区| 盘锦市| 宜都市| 南雄市| 邓州市|