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

【C++航海王:追尋羅杰的編程之路】string類

這篇具有很好參考價(jià)值的文章主要介紹了【C++航海王:追尋羅杰的編程之路】string類。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

目錄

1 -> 為什么學(xué)習(xí)string類?

1.1 -> C語言中的字符串

2 -> 標(biāo)準(zhǔn)庫中的string類

2.1 -> string類

2.2 -> string類的常用接口

3 -> string類的模擬實(shí)現(xiàn)

3.1 -> 經(jīng)典的string類問題

3.2 -> 淺拷貝?

3.3 -> 深拷貝

3.3.1 -> 傳統(tǒng)寫法的string類

3.3.2 -> 現(xiàn)代寫法的string類

3.4 -> 寫時(shí)拷貝

3.5 -> string類的模擬實(shí)現(xiàn)


【C++航海王:追尋羅杰的編程之路】string類,C++,c++,開發(fā)語言,visualstudio,后端

1 -> 為什么學(xué)習(xí)string類?

1.1 -> C語言中的字符串

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

OOP ->??Object Oriented Programming(面向?qū)ο蟪绦蛟O(shè)計(jì))是一種計(jì)算機(jī)編程架構(gòu)。OOP 的一條基本原則是計(jì)算機(jī)程序是由單個(gè)能夠起到子程序作用的單元或?qū)ο蠼M合而成。

核心思想:封裝、繼承、多態(tài)。

使用OOP的好處:

  • 易維護(hù)
  • 質(zhì)量高
  • 效率高
  • 易擴(kuò)展
并且在OJ中,有關(guān)字符串的題目基本以string類的形式出現(xiàn),而且在常規(guī)工作中,為了簡單、方便、快捷,基本都使用string類,很少有人去使用C庫中的字符串操作函數(shù)。

2 -> 標(biāo)準(zhǔn)庫中的string類

2.1 -> string類

【C++航海王:追尋羅杰的編程之路】string類,C++,c++,開發(fā)語言,visualstudio,后端

  1. 字符串是表示字符序列的類;
  2. 標(biāo)準(zhǔn)的字符串類提供了對此類對象的支持,其接口類似于標(biāo)準(zhǔn)字符容器的接口,但添加了專門用于操作單字節(jié)字符字符串的設(shè)計(jì)特性;
  3. string類是使用char(即作為它的字符類型,使用它的默認(rèn)char_traits和分配器類型);
  4. string類是basic_string模板類的一個(gè)實(shí)例,它使用char來實(shí)例化basic_string模板類,并用char_traits和allocator作為basic_string的默認(rèn)參數(shù);
  5. 注意,這個(gè)類獨(dú)立于所使用的編碼來處理字節(jié):如果用來處理多字節(jié)或變長字符(如UTF-8)的序列,這個(gè)類的所有成員(如長度或大小)以及它的迭代器,將仍然按照字節(jié)(而不是實(shí)際編碼的字符)來操作。

總結(jié):

  1. string是表示字符串的字符串類;
  2. 該類的接口與常規(guī)容器的接口基本相同,再添加了一些專門用來操作string的常規(guī)操作;
  3. string在底層實(shí)際是:basic_string模板類的別名,typedef basic_string<char, char_traits, allocator>string;
  4. 不能操作多字節(jié)或者變長字符的序列。

在使用string類時(shí),必須包括#include頭文件以及using namespace std;

2.2 -> string類的常用接口

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

?

函數(shù)名稱 功能說明
string()
構(gòu)造空的string類對象,即空字符串
string(const char* s)
用C-string來構(gòu)造string類對象
string(size_t n, char c)
string類對象中包含n個(gè)字符c
string(const string& s)
拷貝構(gòu)造函數(shù)
#include <iostream>
using namespace std;

void Teststring()
{
	string s1;				// 構(gòu)造空的string類對象s1
	string s2("hello bit"); // 用C格式字符串構(gòu)造string類對象s2
	string s3(s2);			// 拷貝構(gòu)造s3
}

int main()
{

	return 0;
}

2. string類對象的容量操作

函數(shù)名稱 功能說明
size

返回字符串有效字符長度

length 返回字符串有效字符長度
capacity 返回空間總大小
empty 檢測字符串釋放為空串,是返回true,否則返回false
clear 清空有效字符
reserve 為字符串預(yù)留空間
resize 將有效字符的個(gè)數(shù)改成n個(gè),多出空間用字符c填充
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
using namespace std;


// 測試string容量相關(guān)的接口
// size/clear/resize
void Teststring1()
{
	// 注意:string類對象支持直接用cin和cout進(jìn)行輸入和輸出
	string s("hello, world");

	cout << s.size() << endl;
	cout << s.length() << endl;
	cout << s.capacity() << endl;
	cout << s << endl;

	// 將s中的字符串清空,注意清空時(shí)只是將size清0,不改變底層空間的大小
	s.clear();

	cout << s.size() << endl;
	cout << s.capacity() << endl;

	// 將s中有效字符個(gè)數(shù)增加到10個(gè),多出位置用'a'進(jìn)行填充
	// “aaaaaaaaaa”
	s.resize(10, 'a');

	cout << s.size() << endl;
	cout << s.capacity() << endl;

	// 將s中有效字符個(gè)數(shù)增加到15個(gè),多出位置用缺省值'\0'進(jìn)行填充
	// "aaaaaaaaaa\0\0\0\0\0"
	// 注意此時(shí)s中有效字符個(gè)數(shù)已經(jīng)增加到15個(gè)
	s.resize(15);

	cout << s.size() << endl;
	cout << s.capacity() << endl;
	cout << s << endl;

	// 將s中有效字符個(gè)數(shù)縮小到5個(gè)
	s.resize(5);

	cout << s.size() << endl;
	cout << s.capacity() << endl;
	cout << s << endl;
}

//====================================================================================
void Teststring2()
{
	string s;
	// 測試reserve是否會改變string中有效元素個(gè)數(shù)
	s.reserve(100);

	cout << s.size() << endl;
	cout << s.capacity() << endl;

	// 測試reserve參數(shù)小于string的底層空間大小時(shí),是否會將空間縮小
	s.reserve(50);

	cout << s.size() << endl;
	cout << s.capacity() << endl;
}

// 利用reserve提高插入數(shù)據(jù)的效率,避免增容帶來的開銷
//====================================================================================
void TestPushBack()
{
	string s;
	size_t sz = s.capacity();

	cout << "making s grow:\n";

	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');

		if (sz != s.capacity())
		{
			sz = s.capacity();

			cout << "capacity changed: " << sz << '\n';
		}
	}
}

// 構(gòu)建vector時(shí),如果提前已經(jīng)知道string中大概要放多少個(gè)元素,可以提前將string中空間設(shè)置好
void TestPushBackReserve()
{
	string s;
	s.reserve(100);
	size_t sz = s.capacity();

	cout << "making s grow:\n";

	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');

		if (sz != s.capacity())
		{
			sz = s.capacity();

			cout << "capacity changed: " << sz << '\n';
		}
	}
}

int main()
{
	return 0;
}

注意:

  1. size()與length()方法底層實(shí)現(xiàn)原理完全相同,引入size()的原因是為了與其他容器的接口保持一致,一般情況下基本都是用size();
  2. clear()只是將string中有效字符清空,不改變底層空間大?。?/span>
  3. resize(size_t n)與resize(size_t n, char c)都是將字符串中有效字符個(gè)數(shù)改變到n個(gè),不同的是當(dāng)字符個(gè)數(shù)增多時(shí):resize(n)用0來填充多出的元素空間,resize(size_t n, char c)用字符c來填充多出的元素空間。注意:resize在改變元素個(gè)數(shù)時(shí),如果是將元素個(gè)數(shù)增多,可能會改變底層容量的大小,如果是將元素個(gè)數(shù)減少,底層空間總大小不變;
  4. reserve(size_t res_arg = 0):為string預(yù)留空間,不改變有效元素個(gè)數(shù),當(dāng)reserve的參數(shù)小于string的底層空間總大小時(shí),reserve不會改變?nèi)萘看笮 ?/span>

3. string類對象的訪問及遍歷操作?

?函數(shù)名稱 功能說明
operator[] 返回pos位置的字符,const string類對象調(diào)用
begin + end huoqbegin獲取一個(gè)字符的迭代器 + end獲取最后一個(gè)字符下一個(gè)位置的迭代器
rbegin + rend huoqbegin獲取一個(gè)字符的迭代器 + end獲取最后一個(gè)字符下一個(gè)位置的迭代器
范圍for C++11支持更簡潔的范圍for的新遍歷方式
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
using namespace std;

// string的遍歷
// begin()+end()   for+[]  范圍for
// 注意:string遍歷時(shí)使用最多的還是for+下標(biāo) 或者 范圍for(C++11后才支持)
// begin()+end()大多數(shù)使用在需要使用STL提供的算法操作string時(shí),比如:采用reverse逆置string
void Teststring3()
{
	string s1("hello world");
	const string s2("Hello world");

	cout << s1 << " " << s2 << endl;
	cout << s1[0] << " " << s2[0] << endl;

	s1[0] = 'H';

	cout << s1 << endl;

	// s2[0] = 'h';   代碼編譯失敗,因?yàn)閏onst類型對象不能修改
}

void Teststring4()
{
	string s("hello world");
	// 3種遍歷方式:
	// 需要注意的以下三種方式除了遍歷string對象,還可以遍歷是修改string中的字符,
	// 另外以下三種方式對于string而言,第一種使用最多
	// 1. for+operator[]
	for (size_t i = 0; i < s.size(); ++i)
		cout << s[i] << endl;

	// 2.迭代器
	string::iterator it = s.begin();

	while (it != s.end())
	{
		cout << *it << endl;
		++it;
	}

	// string::reverse_iterator rit = s.rbegin();
	// C++11之后,直接使用auto定義迭代器,讓編譯器推到迭代器的類型
	auto rit = s.rbegin();
	while (rit != s.rend())
		cout << *rit << endl;

	// 3.范圍for
	for (auto ch : s)
		cout << ch << endl;
}

int main()
{
	return 0;
}

4. string類對象的修改操作

函數(shù)名稱 功能說明
push_back 在字符串后尾插字符c
append 在字符串后追加一個(gè)字符串
operator+= 在字符串后追加字符串str
c_str 返回c格式字符串
find + npos 從字符串pos位置開始往后找字符c,返回該字符在字符串中的位置
rfind 從字符串pos位置開始往前找字符c,返回該字符在字符串中的位置
substr 在str中從pos位置開始,截取n個(gè)字符,然后將其返回
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
using namespace std;

// 測試string:
// 1. 插入(拼接)方式:push_back  append  operator+= 
// 2. 正向和反向查找:find() + rfind()
// 3. 截取子串:substr()
// 4. 刪除:erase
void Teststring5()
{
	string str;

	str.push_back(' ');   // 在str后插入空格
	str.append("hello");  // 在str后追加一個(gè)字符"hello"
	str += 'b';           // 在str后追加一個(gè)字符'b'   
	str += "it";          // 在str后追加一個(gè)字符串"it"

	cout << str << endl;
	cout << str.c_str() << endl;   // 以C語言的方式打印字符串

	// 獲取file的后綴
	string file("string.cpp");
	size_t pos = file.rfind('.');
	string suffix(file.substr(pos, file.size() - pos));

	cout << suffix << endl;

	// npos是string里面的一個(gè)靜態(tài)成員變量
	// static const size_t npos = -1;

	// 取出url中的域名
	string url("http://www.cplusplus.com/reference/string/string/find/");


	cout << url << endl;
	size_t start = url.find("://");
	if (start == string::npos)
	{
		cout << "invalid url" << endl;

		return;
	}
	start += 3;
	size_t finish = url.find('/', start);
	string address = url.substr(start, finish - start);

	cout << address << endl;

	// 刪除url的協(xié)議前綴
	pos = url.find("://");
	url.erase(0, pos + 3);

	cout << url << endl;
}

int main()
{
	return 0;
}

注意:

  1. 在string尾部追加字符時(shí),s.push_back(c) / s.append(1, c) / s += 'c'三種的實(shí)現(xiàn)方式差不多,一般情況下string類的+=操作用的比較多,+=操作不僅可以連接單個(gè)字符,還可以連接字符串;
  2. 對sting操作時(shí),如果能夠大概預(yù)估到放多少字符,可以先通過reserve把空間預(yù)留好。

5. string類非成員函數(shù)

函數(shù) 功能說明
operator+ 盡量少用,因?yàn)閭髦捣祷?,?dǎo)致深拷貝效率低
operator>> 輸入運(yùn)算符重載
operator<< 輸出運(yùn)算符重載
getline 獲取一行字符串
relational operators 大小比較

6. vs和g++下string結(jié)構(gòu)的說明

注意:下述結(jié)構(gòu)是在32位平臺下進(jìn)行,32位平臺下指針占4個(gè)字節(jié)。

  • vs下string的結(jié)構(gòu)

string總共占28個(gè)字節(jié),內(nèi)部結(jié)構(gòu)稍微復(fù)雜一點(diǎn),先是有一個(gè)聯(lián)合體,聯(lián)合體用來定義string中字符串的存儲空間:

  • 當(dāng)字符串長度小于16時(shí),使用內(nèi)部固定的字符數(shù)組來存放;
  • 當(dāng)字符串長度大于等于16時(shí),從堆上開辟空間。
union _Bxty
{ // storage for small buffer or pointer to larger one
 value_type _Buf[_BUF_SIZE];
 pointer _Ptr;
 char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;

這種設(shè)計(jì)也是有一定道理的,大多數(shù)情況下字符串的長度都小于16,那string對象創(chuàng)建好后,內(nèi)部已經(jīng)有了16個(gè)字符數(shù)組的固定空間,不需要通過堆創(chuàng)建,效率高。

其次:還有一個(gè)size_t字段保存字符串長度,一個(gè)size_t字段保存從堆上開辟空間總的容量。

最后:還有一個(gè)指針做一些其他事情。

故總共占16 + 4 + 4 + 4 = 28個(gè)字節(jié)。

【C++航海王:追尋羅杰的編程之路】string類,C++,c++,開發(fā)語言,visualstudio,后端

  • g++下string的結(jié)構(gòu)

g++下,string是通過寫時(shí)拷貝實(shí)現(xiàn)的,string對象總共占4個(gè)字節(jié),內(nèi)部只包含了一個(gè)指針,該指針將來指向一塊堆空間,內(nèi)部包含了如下字段:

  • 空間總大小
  • 字符串有效長度
  • 引用計(jì)數(shù)
struct _Rep_base
{
 size_type _M_length;
 size_type _M_capacity;
 _Atomic_word _M_refcount;
};
  • 指向堆空間的指針,用來存儲字符串

3 -> string類的模擬實(shí)現(xiàn)

3.1 -> 經(jīng)典的string類問題

模擬實(shí)現(xiàn)string類,最主要是實(shí)現(xiàn)string類的構(gòu)造、拷貝構(gòu)造、賦值運(yùn)算符重載以及析構(gòu)函數(shù)。

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
#include <cassert>
using namespace std;

class String
{
public:
	String(const char* str = "")
	{
		// 構(gòu)造String類對象時(shí),如果傳遞nullptr指針,可以認(rèn)為程序非
		if (nullptr == str)
		{
			assert(false);

			return;
		}

		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}

	~String()
	{
		if (_str)
		{
			delete[] _str;

			_str = nullptr;
		}
	}

private:
	char* _str;
};

void TestString()
{
	String s1("hello world");

	String s2(s1);
}

【C++航海王:追尋羅杰的編程之路】string類,C++,c++,開發(fā)語言,visualstudio,后端?

說明:上述String類沒有顯式定義其拷貝構(gòu)造函數(shù)與賦值運(yùn)算符重載,此時(shí)編譯器會合成默認(rèn)的,當(dāng)用s1構(gòu)造s2時(shí),編譯器會調(diào)用默認(rèn)的拷貝構(gòu)造。最終導(dǎo)致的問題是,s1、s2共用同一塊內(nèi)存空間,在釋放時(shí)同一塊空間被釋放多次而引起程序崩潰,這種拷貝方式,稱為淺拷貝。

3.2 -> 淺拷貝?

淺拷貝:

也稱位拷貝,編譯器只是將對象中的值拷貝過來。如果對象中管理資源,最后就會導(dǎo)致多個(gè)對象共享同一份資源,當(dāng)一個(gè)對象銷毀時(shí)就會將該資源釋放,而此時(shí)另一些對象不知道該資源已經(jīng)被釋放,以為還有效,所以當(dāng)繼續(xù)對資源進(jìn)項(xiàng)操作時(shí),就會發(fā)生訪問違規(guī)。

可以采用深拷貝解決淺拷貝問題,即:每個(gè)對象都有一份獨(dú)立的資源,不要和其他對象共享。

3.3 -> 深拷貝

如果一個(gè)類中涉及到資源的管理,其拷貝構(gòu)造函數(shù),賦值運(yùn)算符重載以及構(gòu)造函數(shù)必須要顯式給出。一般情況都是按照深拷貝方式提供。

【C++航海王:追尋羅杰的編程之路】string類,C++,c++,開發(fā)語言,visualstudio,后端

3.3.1 -> 傳統(tǒng)寫法的string類

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
#include <cassert>
using namespace std;

class String
{
public:
	String(const char* str = "")
	{
		// 構(gòu)造String類對象時(shí),如果傳遞nullptr指針,可以認(rèn)為程序非
		if (nullptr == str)
		{
			assert(false);

			return;
		}

		_str = new char[strlen(str) + 1];

		strcpy(_str, str);
	}

	String(const String& s)
		: _str(new char[strlen(s._str) + 1])
	{
		strcpy(_str, s._str);
	}

	String& operator=(const String& s)
	{
		if (this != &s)
		{
			char* pStr = new char[strlen(s._str) + 1];

			strcpy(pStr, s._str);

			delete[] _str;
			_str = pStr;
		}

		return *this;
	}

	~String()
	{
		if (_str)
		{
			delete[] _str;

			_str = nullptr;
		}
	}

private:
	char* _str;
};

3.3.2 -> 現(xiàn)代寫法的string類

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
#include <cassert>
using namespace std;

class String
{
public:
	String(const char* str = "")
	{
		if (nullptr == str)
		{
			assert(false);

			return;
		}

		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}

	String(const String& s)
		: _str(nullptr)
	{
		String strTmp(s._str);

		swap(_str, strTmp._str);
	}

	String& operator=(String s)
	{
		swap(_str, s._str);

		return *this;
	}

	~String()
	{
		if (_str)
		{
			delete[] _str;

			_str = nullptr;
		}
	}
private:
	char* _str;
};

3.4 -> 寫時(shí)拷貝

寫時(shí)拷貝就是一種拖延癥,實(shí)在淺拷貝的基礎(chǔ)之上增加了引用計(jì)數(shù)的方式來實(shí)現(xiàn)的。

引用計(jì)數(shù):用來記錄資源使用者的個(gè)數(shù)。在構(gòu)造時(shí),將資源的計(jì)數(shù)給成1,每增加一個(gè)對象使用該資源,就給計(jì)數(shù)增加1,當(dāng)某個(gè)對象被銷毀時(shí),先給該計(jì)數(shù)減1,然后再檢查是否需要釋放資源,如果計(jì)數(shù)為1,說明該對象是資源的最后一個(gè)使用者,將該資源釋放;否則就不能釋放,因?yàn)檫€有其他對象在使用該資源。

3.5 -> string類的模擬實(shí)現(xiàn)

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <assert.h>
using namespace std;

namespace fyd
{
	class string
	{
	public:
		typedef char* iterator;

	public:
		string(const char* str = "")
		{
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}

		string(const string& s)
			: _str(nullptr)
			, _size(0)
			, _capacity(0)
		{
			string tmp(s._str);
			this->swap(tmp);
		}

		string& operator=(string s)
		{
			this->swap(s);
			return *this;
		}

		~string()
		{
			if (_str)
			{
				delete[] _str;
				_str = nullptr;
			}
		}

		iterator begin()
		{
			return _str;
		}

		iterator end()
		{
			return _str + _size;
		}

		void push_back(char c)
		{
			if (_size == _capacity)
				reserve(_capacity * 2);

			_str[_size++] = c;
			_str[_size] = '\0';
		}

		string& operator+=(char c)
		{
			push_back(c);
			return *this;
		}

		void append(const char* str)
		{
			size_t len = strlen(str);
			if ((_size + len) > _capacity)
			{
				reserve(_size + len);
			}

			strcpy(_str + _size, str);
			_size += len;
		}

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

		void clear()
		{
			_size = 0;
			_str[_size] = '\0';
		}

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

		const char* c_str()const
		{
			return _str;
		}

		size_t size()const
		{
			return _size;
		}

		size_t capacity()const
		{
			return _capacity;
		}

		bool empty()const
		{
			return 0 == _size;
		}

		void resize(size_t newSize, char c = '\0')
		{
			if (newSize > _size)
			{
				// 如果newSize大于底層空間大小,則需要重新開辟空間
				if (newSize > _capacity)
				{
					reserve(newSize);
				}

				memset(_str + _size, c, newSize - _size);
			}

			_size = newSize;
			_str[newSize] = '\0';
		}

		void reserve(size_t newCapacity)
		{
			// 如果新容量大于舊容量,則開辟空間
			if (newCapacity > _capacity)
			{
				char* str = new char[newCapacity + 1];

				strcpy(str, _str);

				// 釋放原來舊空間,然后使用新空間
				delete[] _str;
				_str = str;
				_capacity = newCapacity;
			}
		}

		// access
		char& operator[](size_t index)
		{
			assert(index < _size);

			return _str[index];
		}

		const char& operator[](size_t index)const
		{
			assert(index < _size);

			return _str[index];
		}

		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 ((_str < s._str) || (_str == s._str));
		}

		bool operator>(const string& s)
		{
			return !((_str < s._str) || (_str == s._str));
		}

		bool operator>=(const string& s)
		{
			return !(strcmp(_str, s._str) < 0);
		}

		bool operator!=(const string& s)
		{
			return !(strcmp(_str, s._str) == 0);
		}

		// 返回c在string中第一次出現(xiàn)的位置
		size_t find(char c, size_t pos = 0) const
		{
			for (size_t i = pos; i < _size; i++)
			{
				if (_str[i] == c)
					return i;
			}

			return -1;
		}

		// 返回子串s在string中第一次出現(xiàn)的位置
		size_t find(const char* s, size_t pos = 0) const
		{
			const char* ret = strstr(_str + pos, s);

			if (ret)
				return ret - _str;
			return -1;
		}

		// 在pos位置上插入字符c/字符串str,并返回該字符的位置
		string& insert(size_t pos, char c)
		{
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}

			char* end = _str + _size;
			while (end > _str + pos)
			{
				*(end + 1) = *end;
				--end;
			}
			_str[pos] = c;
			_size++;

			return *this;
		}
		string& insert(size_t pos, const char* str)
		{
			size_t len = strlen(str);

			if ((_size + len) > _capacity)
			{
				reserve(_size + len);
			}

			char* end = _str + _size;
			while (end > (_str + pos))
			{
				*(end + len) = *end;
				--end;
			}

			strncpy(_str + pos, str, len);
			_size += len;

			return *this;
		}

		// 刪除pos位置上的元素,并返回該元素的下一個(gè)位置
		string& erase(size_t pos, size_t len)
		{
			size_t leftNum = _size - pos;

			if (len >= leftNum)
			{
				_str[pos] = '\0';
				_size = pos;
			}
			else
			{
				strcpy(_str + pos, _str + pos + len);
				_size -= len;
			}

			return *this;
		}

	private:
		friend ostream& operator<<(ostream& _cout, const fyd::string& s);
		friend istream& operator>>(istream& _cin, fyd::string& s);

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

	ostream& operator<<(ostream& _cout, const fyd::string& s)
	{
		for (size_t i = 0; i < s.size(); ++i)
		{
			_cout << s[i];
		}
		return _cout;
	}

	istream& operator>>(istream& _cin, string& s)
	{
		s.clear();
		char ch;

		ch = _cin.get();
		while (ch != ' ' && ch != '\n')
		{
			s += ch;

			ch = _cin.get();
		}

		return _cin;
	}
}

///對自定義的string類進(jìn)行測試
void TestString()
{
	fyd::string s1("hello");

	s1.push_back(' ');
	s1.push_back('w');
	s1.push_back('o');
	s1.push_back('r');
	s1.push_back('l');

	s1 += 'd';

	cout << s1 << endl;
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;

	// 利用迭代器打印string中的元素
	fyd::string::iterator it = s1.begin();
	while (it != s1.end())
	{
		cout << *it;
		++it;
	}

	cout << endl;

	// 這里可以看到一個(gè)類只要支持的基本的iterator,就支持范圍for
	for (auto ch : s1)
		cout << ch;
	cout << endl;
}

int main()
{

	TestString();

	return 0;
}

感謝大佬們的支持?。?!

互三啦!?。?/strong>文章來源地址http://www.zghlxwxcb.cn/news/detail-831848.html

到了這里,關(guān)于【C++航海王:追尋羅杰的編程之路】string類的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • 【C++航海王:追尋羅杰的編程之路】C++11(上)

    【C++航海王:追尋羅杰的編程之路】C++11(上)

    目錄 1 - C++11簡介 2 - 統(tǒng)一的列表初始化 2.1 - {}初始化 2.2 - std::initializer_list 3 - 聲明 3.1 - auto 3.2 - decltype 3.3 - nullptr 在2003年C++標(biāo)準(zhǔn)委員會曾經(jīng)提交了一份技術(shù)勘誤表(簡稱TC1),使得C++03這個(gè)名字已經(jīng)取代了 C++98稱為C++11之前的最新C++標(biāo)準(zhǔn)名稱。不過由于C++03(TC1)主要是對C++98標(biāo)準(zhǔn)中

    2024年04月23日
    瀏覽(31)
  • 【C++航海王:追尋羅杰的編程之路】關(guān)于模板,你知道哪些?

    【C++航海王:追尋羅杰的編程之路】關(guān)于模板,你知道哪些?

    目錄 1 - 泛型編程 2 - 函數(shù)模板 2.1 - 函數(shù)模板概念 2.2 - 函數(shù)模板格式 2.3 - 函數(shù)模板的原理 2.4 - 函數(shù)模板的實(shí)例化 2.5 - 函數(shù)參數(shù)的匹配原則 3 - 類模板 3.1 - 類模板的定義格式 3.2 - 類模板的實(shí)例化 怎樣實(shí)現(xiàn)一個(gè)通用的交換函數(shù)? 使用函數(shù)重載雖然可以實(shí)現(xiàn),但是有幾個(gè)不好的

    2024年02月20日
    瀏覽(25)
  • 【C++航海王:追尋羅杰的編程之路】關(guān)于模板,你知道哪些?

    【C++航海王:追尋羅杰的編程之路】關(guān)于模板,你知道哪些?

    目錄 1 - 非類型模板參數(shù) 2 - 模板的特化 2.1 - 概念 2.2 - 函數(shù)模板的特化 2.3 - 類模板的特化 2.3.1 - 全特化 2.3.2 - 偏特化 2.3.3 - 類模板特化應(yīng)用實(shí)例 3 - 模板分離編譯 3.1 - 什么是分離編譯 3.2 - 模板的分離編譯 3.3 - 解決方法 4 - 模板總結(jié) 模板參數(shù)分為類型形參與非類型形參。 類型

    2024年04月11日
    瀏覽(23)
  • 【C++航海王:追尋羅杰的編程之路】探尋實(shí)用的調(diào)試技巧

    【C++航海王:追尋羅杰的編程之路】探尋實(shí)用的調(diào)試技巧

    目錄 1 - 什么是bug? 2 - 調(diào)試是什么?有多重要? 2.1 - 調(diào)試是什么? 2.2 - 調(diào)試的基本步驟 2.3 - Debug和Release的介紹 3 - Windows環(huán)境調(diào)試介紹 3.1 - 調(diào)試環(huán)境的準(zhǔn)備 3.2 - 學(xué)會快捷鍵 3.3 - 調(diào)試的時(shí)候查看程序當(dāng)前信息 3.3.1 - 查看臨時(shí)變量的值 3.3.2 - 查看內(nèi)存信息 3.3.3 - 查看調(diào)用堆棧

    2024年04月12日
    瀏覽(21)
  • 【C++航海王:追尋羅杰的編程之路】繼承你學(xué)會了么?

    【C++航海王:追尋羅杰的編程之路】繼承你學(xué)會了么?

    目錄 1 - 繼承的概念及定義 1.1 - 繼承的概念 1.2 - 繼承的定義 1.2.1 - 定義格式 1.2.2 - 繼承關(guān)系和訪問限定符 1.2.3 - 繼承基類成員訪問方式的變化 2 - 基類和派生類對象賦值轉(zhuǎn)換 3 - 繼承中的作用域 4 - 派生類的默認(rèn)成員函數(shù) 5 - 繼承與友元 6 - 繼承與靜態(tài)成員 7 - 復(fù)雜的菱形繼承及

    2024年04月16日
    瀏覽(30)
  • 【C++航海王:追尋羅杰的編程之路】priority_queue(優(yōu)先隊(duì)列) | 容器適配器你知道哪些?

    【C++航海王:追尋羅杰的編程之路】priority_queue(優(yōu)先隊(duì)列) | 容器適配器你知道哪些?

    目錄 1 -?priority_queue的介紹和使用 1.1 -?priority_queue的介紹 1.2 -?priority_queue的使用 1.3 -?priority_queue的模擬實(shí)現(xiàn) 2 - 容器適配器 2.1 - 什么是適配器 2.2 - STL標(biāo)準(zhǔn)庫中stack和queue的底層結(jié)構(gòu) 2.3 - deque的介紹 2.3.1 - deque的原理介紹 2.3.2 - deque的缺陷 2.4 - 為什么選擇deque作為stack和queue的底

    2024年04月10日
    瀏覽(46)
  • 【C++進(jìn)階之路】模擬實(shí)現(xiàn)string類

    【C++進(jìn)階之路】模擬實(shí)現(xiàn)string類

    本文所屬專欄——【C++進(jìn)階之路】 ?上一篇,我們講解了string類接口的基本使用,今天我們就實(shí)戰(zhàn)從底層實(shí)現(xiàn)自己的string類,當(dāng)然實(shí)現(xiàn)所有的接口難度很大,我們今天主要實(shí)現(xiàn)的常用的接口~ 1.為了 不與庫里面的string沖突 ,我們需要 命名空間 對 自己實(shí)現(xiàn)的類進(jìn)行封裝 2.這里

    2024年02月13日
    瀏覽(18)
  • 【C++練級之路】【Lv.6】【STL】string類的模擬實(shí)現(xiàn)

    歡迎各位小伙伴關(guān)注我的專欄,和我一起系統(tǒng)學(xué)習(xí)C語言,共同探討和進(jìn)步哦! 學(xué)習(xí)專欄 : 《進(jìn)擊的C++》 關(guān)于 STL容器 的學(xué)習(xí),我會采用 模擬實(shí)現(xiàn) 的方式,以此來更加清楚地了解其 底層原理和整體架構(gòu) 。而string類更是有100多個(gè)接口函數(shù),所以模擬實(shí)現(xiàn)的時(shí)候只會調(diào)重點(diǎn)和

    2024年01月18日
    瀏覽(30)
  • 【C/C++】C語言開發(fā)者必讀:邁向C++的高效編程之旅

    【C/C++】C語言開發(fā)者必讀:邁向C++的高效編程之旅

    ?? 作者簡介 :阿里巴巴嵌入式技術(shù)專家,深耕嵌入式+人工智能領(lǐng)域,具備多年的嵌入式硬件產(chǎn)品研發(fā)管理經(jīng)驗(yàn)。 ?? 博客介紹 :分享嵌入式開發(fā)領(lǐng)域的相關(guān)知識、經(jīng)驗(yàn)、思考和感悟,歡迎關(guān)注。提供嵌入式方向的學(xué)習(xí)指導(dǎo)、簡歷面試輔導(dǎo)、技術(shù)架構(gòu)設(shè)計(jì)優(yōu)化、開發(fā)外包等

    2024年03月20日
    瀏覽(29)
  • C++提高編程——STL:string容器、vector容器

    C++提高編程——STL:string容器、vector容器

    本專欄記錄C++學(xué)習(xí)過程包括C++基礎(chǔ)以及數(shù)據(jù)結(jié)構(gòu)和算法,其中第一部分計(jì)劃時(shí)間一個(gè)月,主要跟著黑馬視頻教程,學(xué)習(xí)路線如下, 不定時(shí)更新,歡迎關(guān)注 。 當(dāng)前章節(jié)處于: ---------第1階段-C++基礎(chǔ)入門 ---------第2階段實(shí)戰(zhàn)-通訊錄管理系統(tǒng), ---------第3階段-C++核心編程, -----

    2024年01月23日
    瀏覽(22)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包