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

【C++】一篇文章帶你深入了解string

這篇具有很好參考價(jià)值的文章主要介紹了【C++】一篇文章帶你深入了解string。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言

一. 為什么學(xué)習(xí)string?

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


二、 標(biāo)準(zhǔn)庫(kù)中的string

2.1 string介紹

string的文檔介紹

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

總結(jié):

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

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


2.2 string的常用接口說(shuō)明

2.2.1 string對(duì)象的常見(jiàn)構(gòu)造

2.2.1.1 string() ---- 無(wú)參構(gòu)造函數(shù)
構(gòu)造空的string對(duì)象,即空字符串
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s;
	cout << s <<endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.1.2 string(const char* s) ---- 有參構(gòu)造函數(shù)
用C-string來(lái)構(gòu)造string對(duì)象
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");
	cout << s << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.1.3 string(size_t n, char c) ---- 有參構(gòu)造函數(shù)
string對(duì)象中包含n個(gè)字符c
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s(10,'z');
	cout << s << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.1.4 string(const string&s) ---- 拷貝構(gòu)造函數(shù)
拷貝構(gòu)造函數(shù)
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");
	string ss(s);
	cout << s << endl;
	cout << ss << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.2 string對(duì)象的容量操作

2.2.2.1 size 函數(shù)
返回字符串有效字符長(zhǎng)度
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");

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

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.2.2 length 函數(shù)
返回字符串有效字符長(zhǎng)度
size() 與 length() 方法底層實(shí)現(xiàn)原理完全相同,
引入 size() 的原因是為了與其他容器的接口保持一致,
一般情況下基本都是用 size()。
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");

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

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.2.3 capacity 函數(shù)
返回空間總大小
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");

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

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.2.4 empty 函數(shù)
檢測(cè)字符串釋放為空串,是返回true,否則返回false

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言

#include <iostream>
#include <string>

using namespace std;
int main()
{
	string s;
	string ss("chineseprson");

	cout << s.empty() << endl;
	cout << ss.empty() << endl;

	return 0;
}

2.2.2.5 clear 函數(shù)
清空有效字符
clear()只是將string中有效字符清空,不改變底層空間大小。
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");
	cout << s << endl;

	s.clear();
	cout << s << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.2.6 reserve 函數(shù)
為字符串預(yù)留空間
reserve(size_t res_arg=0):
為string預(yù)留空間,不改變有效元素個(gè)數(shù),
當(dāng)reserve的參數(shù)小于string的底層空間總大小時(shí),
reserver不會(huì)改變?nèi)萘啃 ?
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");

	s.reserve(30);
	cout << s << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.2.7 resize 函數(shù)
resize(size_t n) 與 resize(size_t n, char c)都是將字符串中有效字符個(gè)數(shù)改變到n個(gè),
不同的是當(dāng)字符個(gè)數(shù)增多時(shí):resize(n)用 '\0' 來(lái)填充多出的元素空間,
resize(size_t n, char c)用字符c來(lái)填充多出的元素空間。
注意:resize在改變?cè)貍€(gè)數(shù)時(shí),如果是將元素個(gè)數(shù)增多,
可能會(huì)改變底層容量的大小,如果是將元素個(gè)數(shù)減少,底層空間總大小不變。
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");
	cout << s << endl;

	s.resize(30,'6');
	cout << s << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.3 string對(duì)象的訪(fǎng)問(wèn)及遍歷操作

2.2.3.1 operator[]
返回pos位置的字符,const string對(duì)象調(diào)用
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");
	for (int i = 0; i < s.size(); i++)
	{
		printf("[%d] : %c\n", i, s[i]);
	}
	cout << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.3.2 迭代器 begin 、end
begin 獲取第一個(gè)字符的迭代器 
end 獲取最后一個(gè)字符下一個(gè)位置的迭代器
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");
	
	string::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << ' ';
		it++;
	}

	cout << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.3.3 迭代器 rbegin 、rend
rbegin 獲取最后一個(gè)字符的迭代器 
rend 獲取第一個(gè)字符前一個(gè)位置的迭代器
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");

	string::reverse_iterator it = s.rbegin();
	while (it != s.rend())
	{
		cout << *it << ' ';
		it++;
	}

	cout << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.3.4 范圍for

范圍for作為C++新出的遍歷方法,相對(duì)于以前的遍歷方式它能夠更加簡(jiǎn)潔的遍歷數(shù)組、容器等數(shù)據(jù)結(jié)構(gòu)中的元素。

#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");

	for (auto ch : s)
	{
		cout << ch << ' ';
	}

	cout << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.4. string對(duì)象的增刪查改

2.2.4.1 push_back 函數(shù)
在字符串后面加一個(gè)字符
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");

	s.push_back('6');
	cout << s << endl;

	s.push_back('6');
	cout << s << endl;

	s.push_back('6');
	cout << s << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.4.2 operator+=
string& operator+= (const string& str);
operator+= 能夠在字符串最后追加一個(gè)string對(duì)象內(nèi)的字符串

string& operator+= (const char* s);
string& operator+= (char c);
operator+= 能夠在字符串后面加一個(gè)字符或者字符串
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");

	s += '6';
	cout << s << endl;

	s += "666666";
	cout << s << endl;

	string ss("牛牛牛");

	s += ss;
	cout << s << endl;
	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.4.3 append 函數(shù)
string& append (const string& str);
append 函數(shù)能夠在字符串最后追加一個(gè)string對(duì)象內(nèi)的字符串

string& append (const string& str, size_t subpos, size_t sublen);
append 函數(shù)能夠在字符串最后追加一個(gè)string對(duì)象內(nèi)的字符串的一段字符串

string& append (const char* s);
append 函數(shù)能夠在字符串最后追加一個(gè)string對(duì)象內(nèi)的字符串

string& append (const char* s, size_t n);
append 函數(shù)還能夠在字符串后面追加字符串的前 n 個(gè)

string& append (size_t n, char c);
append 函數(shù)能夠在字符串后面追加 n 個(gè)字符

注意append 函數(shù)與 operator+= 作用有部分相同
若是單純?cè)谧址竺孀芳右粋€(gè)字符或者字符串,更習(xí)慣使用 operator+=

#include <iostream>
#include <string>

using namespace std;
int main()
{
	string s("chineseprson");

	// 追加n個(gè)字符
	s.append(1,'6');
	cout << s << endl;

	// 追加一個(gè)字符串
	s.append("666666");
	cout << s << endl;

	// 追加一個(gè)字符串的前n個(gè)
	s.append("888888888", 3);

	cout << s << endl;
	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.4.4 insert 函數(shù)
string& insert (size_t pos, const string& str);
insert函數(shù)能夠在字符串任意位置插入一個(gè)string容器內(nèi)的字符串

string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);
insert函數(shù)能夠在字符串任意位置插入一個(gè)string對(duì)象內(nèi)的字符串的一段字符串

string& insert (size_t pos, const char* s);
insert函數(shù)能夠在字符串一段字符串

string& insert (size_t pos, const char* s, size_t n);
insert 函數(shù)還能夠在字符串任意位置插入字符串的前 n 個(gè)

string& insert (size_t pos, size_t n, char c);
insert 函數(shù)還能夠在字符串任意位置插入n個(gè)字符
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("student");
	string ss("test");


	// 在第三個(gè)位置插入string
	s.insert(1, ss);
	cout << s << endl;

	// 在最后插入string的一部分
	s.insert(s.size(), ss , 0 , 2);
	cout << s << endl;

	// 在第一個(gè)位置插入string
	s.insert(0,"666");
	cout << s << endl;

	// 其他插入方法一樣,這里省略
	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.4.5 erase 函數(shù)
string& erase (size_t pos = 0, size_t len = npos);
erase 函數(shù)能夠刪除第 n 個(gè)位置后面長(zhǎng)度為 len 的字符串

如果沒(méi)有傳 len 或是 第 n 個(gè)位置后面的字符數(shù)小于 len ,則n后面的字符全部刪除
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("student");
	
	s.erase(4, 2);
	cout << s << endl;

	s.erase(1);
	cout << s << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.4.6 npos
npos的值通常是一個(gè)很大的正數(shù),等于-1(當(dāng)作為無(wú)符號(hào)數(shù)解釋時(shí))
或等于string::size_type的最大可能值。

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.4.7 c_str 函數(shù)
返回C格式字符串

在C++中,printf 是一個(gè)C語(yǔ)言函數(shù),它不支持直接打印std::string類(lèi)型的內(nèi)容。這是因?yàn)?printf 是一個(gè)可變參數(shù)函數(shù),而 std::string 不是基本數(shù)據(jù)類(lèi)型,因此需要轉(zhuǎn)換為C風(fēng)格字符串才能由 printf 輸出。

#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("chineseprson");

	printf("%s\n", s);
	printf("%s\n", s.c_str());

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.4.8 find 函數(shù)
size_t find (const string& str, size_t pos = 0) const;
find 函數(shù)能夠從第 pos 個(gè)位置開(kāi)始從前往后查找包含 string 對(duì)象 str 的字符串的位置

size_t find (const char* s, size_t pos = 0) const;
find 函數(shù)能夠從第 pos 個(gè)位置開(kāi)始從前往后查找包含字符串 s 的位置

size_t find (char c, size_t pos = 0) const;
find 函數(shù)能夠從第 pos 個(gè)位置開(kāi)始從前往后查找包含字符 c 的位置

find 函數(shù)若是能找到則返回包含需要查找內(nèi)容第一個(gè)字符位置,否則返回 npos。
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("student test");
	string str("student");

	// 查找 str --> 找得到
	int pos = s.find(str, 0);
	cout << "str pos : " << pos << endl;

	// 查找字符串 --> 找得到
	pos = s.find("test" , 0);
	cout << "test pos : " << pos << endl;

	// 查找字符串 --> 找不到
	pos = s.find("Test", 0);
	cout << "Test pos : " << pos << endl;

	// 查找字符 --> 找得到
	pos = s.find('s', 0);
	cout << "s pos : " << pos << endl;

	// 查找字符 --> 找不到
	pos = s.find('a', 0);
	cout << "a pos : " << pos << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.4.9 rfind 函數(shù)
size_t rfind (const string& str, size_t pos = npos) const;
find 函數(shù)能夠從第 pos 個(gè)位置開(kāi)始從后往前查找包含 string 對(duì)象 str 的字符串的位置

size_t rfind (const char* s, size_t pos = npos) const;
find 函數(shù)能夠從第 pos 個(gè)位置開(kāi)始從前往后查找包含字符串 s 的位置

size_t rfind (char c, size_t pos = npos) const;
find 函數(shù)能夠從第 pos 個(gè)位置開(kāi)始從前往后查找包含字符 c 的位置
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("student test");
	string str("student");

	// 查找 str --> 找得到
	int pos = s.rfind(str, s.size()-1);
	cout << "str pos : " << pos << endl;

	// 查找字符串 --> 找得到
	pos = s.rfind("test", s.size() - 1);
	cout << "test pos : " << pos << endl;

	// 查找字符串 --> 找不到
	pos = s.rfind("test", s.size() - 5);
	cout << "test pos : " << pos << endl;

	// 查找字符串 --> 找不到
	pos = s.rfind("Test", s.size() - 1);
	cout << "Test pos : " << pos << endl;

	// 查找字符 --> 找得到
	pos = s.rfind('s', s.size() - 1);
	cout << "s pos : " << pos << endl;

	// 查找字符 --> 找不到
	pos = s.rfind('a', s.size() - 1);
	cout << "a pos : " << pos << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


2.2.4.10 substr 函數(shù)
string substr (size_t pos = 0, size_t len = npos) const;
在字符串中從第pos個(gè)位置開(kāi)始截取len個(gè)字符返回
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("student test");
	// 在s中從第0個(gè)位置開(kāi)始截取所有字符返回
	string ss = s.substr(0);
	cout << ss << endl;

	// 在s中從第3個(gè)位置開(kāi)始截取3字符返回
	ss = s.substr(3,3);
	cout << ss << endl;

	return 0;
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


三、string拷貝問(wèn)題

3.1 經(jīng)典的string問(wèn)題

上面已經(jīng)對(duì)string進(jìn)行了簡(jiǎn)單的介紹,大家只要能夠正常使用即可。在面試中,面試官總喜歡讓學(xué)生自己來(lái)模擬實(shí)現(xiàn)string,最主要是實(shí)現(xiàn)string的構(gòu)造、拷貝構(gòu)造、賦值運(yùn)算符重載以及析構(gòu)函數(shù)。大家看下以下string的實(shí)現(xiàn)是否有問(wèn)題?

// 為了和標(biāo)準(zhǔn)庫(kù)區(qū)分,此處使用String
class String
{
public:
    /*String()
:_str(new char[1])
{*_str = '\0';}
*/
//String(const char* str = "\0") 錯(cuò)誤示范
//String(const char* str = nullptr) 錯(cuò)誤示范
    String(const char* str = "")
    {
        // 構(gòu)造String對(duì)象時(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;
};
// 測(cè)試
void TestString()
{
    String s1("hello C++!!!");
    String s2(s1);
}

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言
說(shuō)明:上述String沒(méi)有顯式定義其拷貝構(gòu)造函數(shù)與賦值運(yùn)算符重載,此時(shí)編譯器會(huì)合成默認(rèn)的,當(dāng)用s1構(gòu)造s2時(shí),編譯器會(huì)調(diào)用默認(rèn)的拷貝構(gòu)造。最終導(dǎo)致的問(wèn)題是,s1、s2共用同一塊內(nèi)存空間,在釋放時(shí)同一塊空間被釋放多次而引起程序崩潰,這種拷貝方式,稱(chēng)為淺拷貝


3.2 淺拷貝

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

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


3.3 深拷貝

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

【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言


3.4 寫(xiě)時(shí)拷貝

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

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


四、string的模擬實(shí)現(xiàn)

4.1 string默認(rèn)成員函數(shù)的實(shí)現(xiàn)

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

namespace aj
{
    class string
    {
    public:
        // 這里缺省值給""的原因是空字符串本身就帶一個(gè)'\0'
        // 而不是初始化的時(shí)候_str為nullptr
        // 初始化列表的順序應(yīng)該與聲明相同
        string(const char* str = "")
            :_capacity(strlen(str))
            , _size(_capacity)
        {
            // 多開(kāi)一個(gè)空間用來(lái)存放'\0'
            _str = new char[_capacity + 1];
            strcpy(_str, str);
        }
		
		// 拷貝構(gòu)造函數(shù)傳統(tǒng)寫(xiě)法:
        /*string(const string& s)
        {
            _capacity = s._capacity;
            _str = new char[_capacity + 1];
            _size = s._size;
            strcpy(_str, s._str);
        }*/

		// swap函數(shù)
		void swap(string& s)
        {
            std::swap(_str, s._str);
            std::swap(_capacity, s._capacity);
            std::swap(_size, s._size);
        }

        // 拷貝構(gòu)造函數(shù)現(xiàn)代寫(xiě)法:
        // 構(gòu)造一個(gè)使用s構(gòu)造string對(duì)象tmp
        // tmp中的內(nèi)容是this指向的對(duì)象所需要的
        // 將兩個(gè)對(duì)象的指針交換
        // 即可達(dá)到我們的目的
        string(const string& s)
            : _str(nullptr)
            , _capacity(0)
            , _size(0)
        {
            string tmp(s._str);
            swap(tmp);
        }
		
		// 賦值重載的傳統(tǒng)寫(xiě)法:
		// 這里的傳統(tǒng)寫(xiě)法與上面的拷貝構(gòu)造的內(nèi)容幾乎相同
		// 而下面的現(xiàn)代寫(xiě)法復(fù)用了拷貝構(gòu)造
		// 使得成員函數(shù)看起來(lái)更加簡(jiǎn)潔
		
        // 賦值重載 傳統(tǒng)寫(xiě)法
        /*string& operator=(const string& s)
        {
            if (this != &s)
            {
                reserve(s._capacity);
                strcpy(_str, s._str);
                _capacity = s._capacity;
                _size = s._size;
            }

            return *this;
        }*/
		
		// 賦值重載的現(xiàn)代寫(xiě)法:
		// 首先判斷是否是自己給自己賦值
		// 若是直接返回自己,否則進(jìn)行下面的操作
		// 利用拷貝構(gòu)造得來(lái)tmp
		// tmp中的數(shù)據(jù)是我們需要的數(shù)據(jù)
		// 而this指向的數(shù)據(jù)是我們需要改變的
		// tmp是臨時(shí)變量,出了作用域會(huì)自動(dòng)銷(xiāo)毀
		// 我們將tmp的內(nèi)容和this指向的內(nèi)容交換
		// 實(shí)質(zhì)上是兩個(gè)指針的指向變化
		// 交換后this指向的內(nèi)容就是我們需要的,返回
		// 而tmp中的內(nèi)容是不需要的,出了作用域自動(dòng)銷(xiāo)毀

        // 賦值重載 現(xiàn)代寫(xiě)法
        /*string& operator=(const string& s)
        {
            if (this != &s)
            {
                string tmp(s);
                swap(tmp);
            }

            return *this;
        }*/
		
		// 拷貝構(gòu)造函數(shù)的現(xiàn)代寫(xiě)法:
		// 這個(gè)現(xiàn)代寫(xiě)法與上面的本質(zhì)相同
		// 這個(gè)是不判斷是否是自己給自己賦值
		// 而是傳值傳參時(shí)利用拷貝構(gòu)造直接得來(lái)tmp
		// 其他步驟相同
		
		// 賦值重載 現(xiàn)代寫(xiě)法
        string& operator=(string tmp)
        {
            swap(tmp);

            return *this;
        }
		
		// 析構(gòu)函數(shù)
        ~string()
        {
            delete[] _str;
            _str = nullptr;
            _size = _capacity = 0;
        }

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

        const static size_t npos;
    };

    const size_t string::npos = -1;
};

4.2 string 中 c_str 、size 、capacity 和 empty 的實(shí)現(xiàn)

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

#include <string>

namespace aj
{
    class string
    {
    public:
        void clear()
        {
            _str[0] = '\0';
            _size = 0;
        }

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

        size_t size()const
        {
            return _size;
        }

        size_t capacity() const
        {
            return _capacity;
        }

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

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

        const static size_t npos;
    };
    const size_t string::npos = -1;
};


4.3 string 中 resize 和 reverse 的實(shí)現(xiàn)

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

namespace aj
{
    class string
    {
    public:
        // 分三種情況 (n為新字符串的長(zhǎng)度)
        //  (1) n <= _size
        //  (2) n > _size && n <= _capacity
        //  (3) n > _capacity
        // 第一種情況為縮短,第二三種情況為增長(zhǎng),
        // 但第二種情況不需要擴(kuò)容,第三種情況不需要
        // 由于resize內(nèi)部當(dāng)傳入的參數(shù)小于_capacity 時(shí)不會(huì)擴(kuò)容
        // 所以將第二三種情況放在一起

        void resize(size_t n, char c = '\0')
        {
            if (n <= _size)
            {
                _str[n] = '\0';
                _size = n;
            }
            else
            {
                reserve(n);
                _capacity = n;
                while (_size < n)
                {
                    _str[_size] = c;
                    _size++;
                }
                // 到這里 _size = n
                _str[_size] = '\0';
            }
        }

        void reserve(size_t n)
        {
            if (n > _capacity)
            {
                // _capacity 記錄的是需要存儲(chǔ)有效數(shù)據(jù)的個(gè)數(shù)
                // 所以我們這里要多開(kāi)一個(gè)空間用來(lái)記錄'\0'
                char* tmp = new char[n + 1];
                strcpy(tmp, _str);
                delete[] _str;
                _str = tmp;

                _capacity = n;
            }

        }

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

        const static size_t npos;
    };

    const size_t string::npos = -1;
};


4.4 string 中 push_back 、append 和 operator+= 的實(shí)現(xiàn)

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

namespace aj
{
    class string
    {
    public:
        void push_back(char c)
        {
            if (_size + 1 > _capacity)
            {
                // 這里不能盲目的開(kāi)二倍,因?yàn)閟tring可能是空字符串,
                // _capacity = 0 , 那么這里的二倍就沒(méi)有意義,繼續(xù)下面的操作會(huì)報(bào)錯(cuò)
                reserve(_capacity == 0 ? 4 : 2 * _capacity);
            }

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

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

            strcpy(_str + _size, str);
            _size += len;
        }
        
		string& operator+=(char c)
        {
            push_back(c);
            return *this;
        }

        void reserve(size_t n)
        {
            if (n > _capacity)
            {
                // _capacity 記錄的是需要存儲(chǔ)有效數(shù)據(jù)的個(gè)數(shù)
                // 所以我們這里要多開(kāi)一個(gè)空間用來(lái)記錄'\0'
                char* tmp = new char[n + 1];
                strcpy(tmp, _str);
                delete[] _str;
                _str = tmp;

                _capacity = n;
            }

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

        const static size_t npos;
    };

    const size_t string::npos = -1;
};


4.5 string 中 operator[] 的實(shí)現(xiàn)

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

namespace aj
{
    class string
    {
    public:
        char& operator[](size_t index)
        {
            return _str[index];
        }

        const char& operator[](size_t index)const
        {
            return _str[index];
        }

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

        const static size_t npos;
    };

    const size_t string::npos = -1;
};

4.6 string 中 迭代器 的實(shí)現(xiàn)

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

namespace aj
{
    class string
    {

    public:
        typedef char* iterator;
        typedef const char* const_iterator;

    public:
        iterator begin()
        {
            return _str;
        }

        iterator end()
        {
            return _str + _size;
        }

        const_iterator begin() const
        {
            return _str;
        }

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

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

        const static size_t npos;
    };

    const size_t string::npos = -1;
};


4.7 string 中 operator<< 和 operator>> 的實(shí)現(xiàn)

并不是所有的流插入、流提取都需要定義成友元函數(shù),定義成友元函數(shù)的目的是為了訪(fǎng)問(wèn)成員的私有,這里不需要訪(fǎng)問(wèn)私有,則不需要定義成友元函數(shù)。

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

namespace aj
{
    class string
    {
    private:
        char* _str;
        size_t _capacity;
        size_t _size;

        const static size_t npos;
    };

    const size_t string::npos = -1;

    ostream& operator<<(ostream& _cout, const string& s)
    {
        for (auto ch : s)
        {
            cout << ch;
        }

        return _cout;
    }
	
	// 這個(gè)版本不好在,沒(méi)有提前開(kāi)空間
	// 即使開(kāi)空間了,也不知道開(kāi)多少
	// 大了浪費(fèi),小了又需要很多次擴(kuò)容
    //istream& operator>>(istream& _cin, string& s)
    //{
    //    // 流插入時(shí)需要將string中字符串清除
    //    s.clear();
    //    char ch = 0;
    //    ch = _cin.get();
    //    while (ch != ' ' && ch != '\n')
    //    {
    //        s += ch;
    //        ch = _cin.get();
    //    }
    //    return _cin;
    //}

    istream& operator>>(istream& _cin, string& s)
    {
        // 流插入時(shí)需要將string中字符串清除
        s.clear();
        // 定義一個(gè)buff數(shù)組,作為緩沖
        char buff[129] = { 0 };
        char ch = 0;
        ch = _cin.get();
        int i = 0;
        while (ch != ' ' && ch != '\n')
        {
            buff[i] = ch;
            ch = _cin.get();
            if (i == 128)
            {
                s += buff;
                i = 0;
            }
            i++;
        }

        if (i != 0)
        {
            s += buff;
        }
        return _cin;
    }
};


4.8 string 中 比較函數(shù) 的實(shí)現(xiàn)

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

namespace aj
{
    class string
    {
    public:
        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);
        }

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

        const static size_t npos;
    };

    const size_t string::npos = -1;
};


4.9 string 中 find 的實(shí)現(xiàn)

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

namespace aj
{
    class string
    {
    public:
        // 返回c在string中第一次出現(xiàn)的位置

        size_t find(char c, size_t pos = 0) const
        {
            assert(pos < _size);
            for (size_t i = pos; i < _size; i++)
            {
                if (_str[i] == c)
                {
                    return i;
                }
            }

            return npos;
        }

        // 返回子串s在string中第一次出現(xiàn)的位置

        size_t find(const char* s, size_t pos = 0) const
        {
            assert(pos < _size);
            char* ret = strstr(_str, s);
            if (ret == nullptr)
            {
                return npos;
            }
            return ret - _str;
        }

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

        const static size_t npos;
    };

    const size_t string::npos = -1;
};


4.10 string 中 insert 和 erase 的實(shí)現(xiàn)

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

namespace aj
{
    class string
    {
    public:
        string& insert(size_t pos, char c)
        {
            assert(pos <= _size);

            if (_size + 1 > _capacity)
            {
                reserve(_capacity == 0 ? 4 : 2 * _capacity);
            }

            // 注意:無(wú)符號(hào)整形比較是用補(bǔ)碼進(jìn)行比較
            // 當(dāng)pos = 0,且 i = -1 時(shí) , 0并不比-1大
            // 記得將_size位置上的'\0'也向后移動(dòng)

            // 版本一 存在問(wèn)題
            /*for (size_t i = _size; pos <= i; i--)
            {
                _str[i + 1] = _str[i];
            }*/

            // 版本二 將pos轉(zhuǎn)換為有符號(hào)整形進(jìn)行比較
            /*for (int i = _size; (int)pos <= i; i--)
            {
                _str[i + 1] = _str[i];
            }*/

            // 版本三 將 i 置為_(kāi)size 的后面從后往前移動(dòng),防止了0與-1的比較
            for (size_t i = _size + 1; pos < i; i--)
            {
                _str[i] = _str[i - 1];
            }

            _str[pos] = c;
            _size++;

            return *this;
        }

        string& insert(size_t pos, const char* str)
        {
            assert(pos <= _size);

            int len = strlen(str);

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

            for (size_t i = _size + len; pos < i; i--)
            {
                _str[i] = _str[i - len];
            }

            strncpy(_str + pos, str, len);

            _size += len;

            return *this;
        }


        string& erase(size_t pos, size_t len = npos)
        {
            assert(pos < _size);

            if (len + pos > _capacity || len == npos)
            {
                _str[pos] = '\0';
                _size = pos;
            }
            else
            {
                size_t begin = len + pos;
                while (begin <= _size)
                {
                    _str[pos] = _str[begin];
                    pos++;
                    begin++;
                }
                _size -= len;
            }
            return *this;
        }

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

        const static size_t npos;
    };

    const size_t string::npos = -1;
};


4.11 string 中 substr 的實(shí)現(xiàn)

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

namespace aj
{
    class string
    {
    public:
        string substr(size_t pos = 0, size_t len = npos) const
        {
            assert(pos < _size);
            string tmp;
            int end = pos + len;
            if (pos + len > _size || len == npos)
            {
                len = _size - pos;
                end = _size;
            }
            
            // 提前開(kāi)空間防止擴(kuò)容
            tmp.reserve(len);

            for (int i = pos; i < end; i++)
            {
                tmp += _str[i];
            }

            return tmp;
        }

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

        const static size_t npos;
    };

    const size_t string::npos = -1;
};


4.12 string 實(shí)現(xiàn)匯總及函數(shù)測(cè)試

#pragma once

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

#include <string>

namespace aj
{
    class string
    {
        // friend ostream& operator<<(ostream& _cout, const aj::string& s);
        // friend istream& operator>>(istream& _cin, aj::string& s);

    public:
        typedef char* iterator;
        typedef const char* const_iterator;

    public:
        // 這里缺省值給""的原因是空字符串本身就帶一個(gè)'\0'
        // 而不是初始化的時(shí)候_str為nullptr
        // 初始化列表的順序應(yīng)該與聲明相同
        string(const char* str = "")
            :_capacity(strlen(str))
            , _size(_capacity)
        {
            // 多開(kāi)一個(gè)空間用來(lái)存放'\0'
            _str = new char[_capacity + 1];
            strcpy(_str, str);
        }
		
		// 拷貝構(gòu)造函數(shù)傳統(tǒng)寫(xiě)法:
        /*string(const string& s)
        {
            _capacity = s._capacity;
            _str = new char[_capacity + 1];
            _size = s._size;
            strcpy(_str, s._str);
        }*/

		// swap函數(shù)
		void swap(string& s)
        {
            std::swap(_str, s._str);
            std::swap(_capacity, s._capacity);
            std::swap(_size, s._size);
        }

        // 拷貝構(gòu)造函數(shù)現(xiàn)代寫(xiě)法:
        string(const string& s)
            : _str(nullptr)
            , _capacity(0)
            , _size(0)
        {
            string tmp(s._str);
            swap(tmp);
        }
		
        // 賦值重載 傳統(tǒng)寫(xiě)法
        /*string& operator=(const string& s)
        {
            if (this != &s)
            {
                reserve(s._capacity);
                strcpy(_str, s._str);
                _capacity = s._capacity;
                _size = s._size;
            }

            return *this;
        }*/
		
        // 賦值重載 現(xiàn)代寫(xiě)法
        /*string& operator=(const string& s)
        {
            if (this != &s)
            {
                string tmp(s);
                swap(tmp);
            }

            return *this;
        }*/
		
		// 賦值重載 現(xiàn)代寫(xiě)法
        string& operator=(string tmp)
        {
            swap(tmp);

            return *this;
        }
		
		// 析構(gòu)函數(shù)
        ~string()
        {
            delete[] _str;
            _str = nullptr;
            _size = _capacity = 0;
        }

        //

        // iterator

        iterator begin()
        {
            return _str;
        }

        iterator end()
        {
            return _str + _size;
        }

        const_iterator begin() const
        {
            return _str;
        }

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



        /

        // modify

        void push_back(char c)
        {
            if (_size + 1 > _capacity)
            {
                // 這里不能盲目的開(kāi)二倍,因?yàn)閟tring可能是空字符串,
                // _capacity = 0 , 那么這里的二倍就沒(méi)有意義,繼續(xù)下面的操作會(huì)報(bào)錯(cuò)
                reserve(_capacity == 0 ? 4 : 2 * _capacity);
            }

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

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


        // 分為兩種情況
        // (1) 追加后的字符串沒(méi)有超過(guò)_capacity
        // (2) 追加后的字符串超過(guò)_capacity需要擴(kuò)容

        void append(const char* str)
        {
            int 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()
        {
            _str[0] = '\0';
            _size = 0;
        }

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

        }

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



        /

        // capacity

        size_t size()const
        {
            return _size;
        }

        size_t capacity() const
        {
            return _capacity;
        }

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

        // 分三種情況 (n為新字符串的長(zhǎng)度)
        // (1)n <= _size
        //  (2) n > _size && n <= _capacity
        //  (3) n > _capacity
        // 第一種情況為縮短,第二三種情況為增長(zhǎng),
        // 但第二種情況不需要擴(kuò)容,第三種情況不需要
        // 由于reserve內(nèi)部當(dāng)傳入的參數(shù)小于_capacity 時(shí)不會(huì)擴(kuò)容
        // 所以將第二三種情況放在一起

        void resize(size_t n, char c = '\0')
        {
            if (n <= _size)
            {
                _str[n] = '\0';
                _size = n;
            }
            else
            {
                reserve(n);
                _capacity = n;
                while (_size < n)
                {
                    _str[_size] = c;
                    _size++;
                }
                // 到這里 _size = n
                _str[_size] = '\0';
            }
        }

        void reserve(size_t n)
        {
            if (n > _capacity)
            {
                // _capacity 記錄的是需要存儲(chǔ)有效數(shù)據(jù)的個(gè)數(shù)
                // 所以我們這里要多開(kāi)一個(gè)空間用來(lái)記錄'\0'
                char* tmp = new char[n + 1];
                strcpy(tmp, _str);
                delete[] _str;
                _str = tmp;

                _capacity = n;
            }

        }



        /

        // access

        char& operator[](size_t index)
        {
            return _str[index];
        }

        const char& operator[](size_t index)const
        {
            return _str[index];
        }



        /

        //relational operators

        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
        {
            assert(pos < _size);
            for (size_t i = pos; i < _size; i++)
            {
                if (_str[i] == c)
                {
                    return i;
                }
            }

            return npos;
        }

        // 返回子串s在string中第一次出現(xiàn)的位置

        size_t find(const char* s, size_t pos = 0) const
        {
            assert(pos < _size);
            char* ret = strstr(_str, s);
            if (ret == nullptr)
            {
                return npos;
            }
            return ret - _str;
        }

        string substr(size_t pos = 0, size_t len = npos) const
        {
            assert(pos < _size);
            string tmp;
            int end = pos + len;
            if (pos + len > _size || len == npos)
            {
                len = _size - pos;
                end = _size;
            }
            
            // 提前開(kāi)空間防止擴(kuò)容
            tmp.reserve(len);

            for (int i = pos; i < end; i++)
            {
                tmp += _str[i];
            }

            return tmp;
        }

        

        string& insert(size_t pos, char c)
        {
            assert(pos <= _size);

            if (_size + 1 > _capacity)
            {
                reserve(_capacity == 0 ? 4 : 2 * _capacity);
            }

            // 注意:無(wú)符號(hào)整形比較是用補(bǔ)碼進(jìn)行比較
            // 當(dāng)pos = 0,且 i = -1 時(shí) , 0并不比-1大
            // 記得將_size位置上的'\0'也向后移動(dòng)

            // 版本一 存在問(wèn)題
            /*for (size_t i = _size; pos <= i; i--)
            {
                _str[i + 1] = _str[i];
            }*/

            // 版本二 將pos轉(zhuǎn)換為有符號(hào)整形進(jìn)行比較
            /*for (int i = _size; (int)pos <= i; i--)
            {
                _str[i + 1] = _str[i];
            }*/

            // 版本三 將 i 置為_(kāi)size 的后面從后往前移動(dòng),防止了0與-1的比較
            for (size_t i = _size + 1; pos < i; i--)
            {
                _str[i] = _str[i - 1];
            }

            _str[pos] = c;
            _size++;

            return *this;
        }

        string& insert(size_t pos, const char* str)
        {
            assert(pos <= _size);

            int len = strlen(str);

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

            for (size_t i = _size + len; pos < i; i--)
            {
                _str[i] = _str[i - len];
            }

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

            return *this;
        }


        string& erase(size_t pos, size_t len = npos)
        {
            assert(pos < _size);

            if (len + pos > _capacity || len == npos)
            {
                _str[pos] = '\0';
                _size = pos;
            }
            else
            {
                size_t begin = len + pos;
                while (begin <= _size)
                {
                    _str[pos] = _str[begin];
                    pos++;
                    begin++;
                }
                _size -= len;
            }
            return *this;
        }

        

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

        const static size_t npos;
    };

    const size_t string::npos = -1;


    ostream& operator<<(ostream& _cout, const string& s)
    {
        for (auto ch : s)
        {
            cout << ch;
        }

        return _cout;
    }

    //istream& operator>>(istream& _cin, string& s)
    //{
    //    // 流插入時(shí)需要將string中字符串清除
    //    s.clear();
    //    char ch = 0;
    //    ch = _cin.get();
    //    while (ch != ' ' && ch != '\n')
    //    {
    //        s += ch;
    //        ch = _cin.get();
    //    }
    //    return _cin;
    //}

    istream& operator>>(istream& _cin, string& s)
    {
        // 流插入時(shí)需要將string中字符串清除
        s.clear();
        char buff[129] = { 0 };
        char ch = 0;
        ch = _cin.get();
        int i = 0;
        while (ch != ' ' && ch != '\n')
        {
            buff[i] = ch;
            ch = _cin.get();
            if (i == 128)
            {
                s += buff;
                i = 0;
            }
            i++;
        }

        if (i != 0)
        {
            s += buff;
        }
        return _cin;
    }

    // 測(cè)試c_str size capacity resize empty
    void test_string1()
    {
        string s("chineseperson");
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << s.empty() << endl;
        cout << endl;

        s.resize(20, 'c');
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << endl;

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

        string s1;
        cout << s1.c_str() << endl;
        cout << s1.size() << endl;
        cout << s1.capacity() << endl;
        cout << s1.empty() << endl;
        cout << endl;
    }

    // 測(cè)試 push_back append
    void test_string2()
    {
        string s("chineseperson");
        s.push_back('6');
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout <<  endl;

        s.append(" hellolllllllllll");
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << endl;

        string s1;
        s1.push_back('6');

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

    // 測(cè)試 +=  operator[]
    void test_string3()
    {
        string s("chineseperson");
        s += '6';
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << endl;

        s += " hellolllllllllll";
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << endl;

        string s1;
        s1 += '6';

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

        s1[0]++;
        cout << s1.c_str() << endl;
        cout << s1.size() << endl;
        cout << s1.capacity() << endl;
        cout << endl;
    }

    // 測(cè)試 迭代器 和 范圍for
    void test_string4()
    {
        string s("chineseperson");
        string::iterator it = s.begin();
        while (it != s.end())
        {
            cout << *it << ' ';
            it++;
        }
        cout << endl;

        for (auto ch : s)
        {
            cout <<ch << ' ';
        }
    }

    // 測(cè)試流插入流提取
    void test_string5()
    {
        string s;
        cin >> s;
        cout << s << endl;
    }

    // 測(cè)試拷貝構(gòu)造 , 賦值
    void test_string6()
    {
        string s("chineseperson");
        string s1(s);
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << endl;


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

        string s2("hello");
        cout << s2.c_str() << endl;
        cout << s2.size() << endl;
        cout << s2.capacity() << endl;
        cout << endl;

        s2 = s;
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << endl;
    }

    // 測(cè)試string比較
    void test_string7()
    {
        string s("chineseperson");
        string s1(s);
        s1[0]++;
        cout << (s < s1) << endl;
        cout << (s <= s1) << endl;
        cout << (s > s1) << endl;
        cout << (s >= s1) << endl;
        cout << (s != s1) << endl;
        cout << (s == s1) << endl;

    }

    // 測(cè)試 find
    void test_string8()
    {
        string s("chineseperson");
        cout << s.find('n') << endl;
        cout << s.find('n', 10) << endl;
        cout << s.find('a') << endl;

        cout << endl;
        cout << s.find("esepe") << endl;

    }

    // 測(cè)試insert erase
    void test_string9()
    {
        string s("chineseperson");
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << endl;

        s.insert(0, '6');
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << endl;

        s.insert(s.size(), '6');
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << endl;

        string s1(s);
        s.insert(0, "hello ");
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << endl;

        s.insert(s.size(), " Yeah Yeah Yeah !!");
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << endl;

        string s2(s);
        cout << s2.c_str() << endl;
        cout << s2.size() << endl;
        cout << s2.capacity() << endl;
        cout << endl;

        s2.erase(0, 2);
        cout << s2.c_str() << endl;
        cout << s2.size() << endl;
        cout << s2.capacity() << endl;
        cout << endl;

        s2.erase(15);
        cout << s2.c_str() << endl;
        cout << s2.size() << endl;
        cout << s2.capacity() << endl;
        cout << endl;

        s2.erase(5);
        cout << s2.c_str() << endl;
        cout << s2.size() << endl;
        cout << s2.capacity() << endl;
        cout << endl;
    }
    // 測(cè)試 substr
    void test_string10()
    {
        string s("chineseperson");
        cout << s.c_str() << endl;
        cout << s.size() << endl;
        cout << s.capacity() << endl;
        cout << endl;

        string s1 = s.substr(2, 5);
        cout << s1.c_str() << endl;
        cout << s1.size() << endl;
        cout << s1.capacity() << endl;
        cout << endl;

        string s2 = s.substr(2);
        cout << s2.c_str() << endl;
        cout << s2.size() << endl;
        cout << s2.capacity() << endl;
        cout << endl;
        

        string tmp("https://legacy.cplusplus.com/reference/string/string/substr/");
        int i1 = tmp.find(':', 0);
        string ret1 = tmp.substr(0, i1);
        cout << ret1.c_str() << endl;

        int i2 = tmp.find('/', i1 + 3);
        string ret2 = tmp.substr(i1 + 3, i2);
        cout << ret2.c_str() << endl;

        string ret3 = tmp.substr(i2);
        cout << ret3.c_str() << endl;
    }

};


結(jié)尾

如果有什么建議和疑問(wèn),或是有什么錯(cuò)誤,大家可以在評(píng)論區(qū)中提出。
希望大家以后也能和我一起進(jìn)步??!????
如果這篇文章對(duì)你有用的話(huà),希望大家給一個(gè)三連支持一下!!????
【C++】一篇文章帶你深入了解string,c++,開(kāi)發(fā)語(yǔ)言文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-844539.html

到了這里,關(guān)于【C++】一篇文章帶你深入了解string的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • 一篇文章帶你了解什么是圖靈完備

    圖靈完備(Turing-complete)是一個(gè)計(jì)算機(jī)科學(xué)中的概念,它指的是一種計(jì)算模型能夠模擬任何其他計(jì)算模型的能力。這意味著,只要一種計(jì)算模型是圖靈完備的,那么它就能夠完成任何可計(jì)算的任務(wù)。 圖靈完備是指一種計(jì)算機(jī)語(yǔ)言或計(jì)算模型具有足夠的能力來(lái)模擬圖靈機(jī)的所有

    2024年02月15日
    瀏覽(32)
  • 一篇文章帶你了解什么是JDK

    JDK(Java Development Kit)是Java開(kāi)發(fā)工具包,它提供了開(kāi)發(fā)和運(yùn)行Java應(yīng)用程序所需的工具、庫(kù)和資源。下面是JDK的一些重點(diǎn)介紹: Java編譯器(javac):JDK包含了Java編譯器,可以將Java源代碼編譯為Java字節(jié)碼。通過(guò)編譯器,開(kāi)發(fā)人員可以將Java源代碼轉(zhuǎn)換為可在JVM上運(yùn)行的字節(jié)碼文

    2024年03月19日
    瀏覽(32)
  • 一篇文章帶你了解-selenium工作原理詳解

    一篇文章帶你了解-selenium工作原理詳解

    前言 Selenium是一個(gè)用于Web應(yīng)用程序自動(dòng)化測(cè)試工具。Selenium測(cè)試直接運(yùn)行在瀏覽器中,就像真正的用戶(hù)在操作一樣。支持的瀏覽器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。 主要功能包括:測(cè)試與瀏覽器的兼容性——測(cè)試你的應(yīng)用程序看是否能夠很好得

    2024年02月10日
    瀏覽(26)
  • 一篇文章帶你詳細(xì)了解axios的封裝

    一篇文章帶你詳細(xì)了解axios的封裝

    對(duì)請(qǐng)求的封裝在實(shí)際項(xiàng)目中是十分必要的,它可以讓我們統(tǒng)一處理 http 請(qǐng)求。比如做一些攔截,處理一些錯(cuò)誤等。本篇文章將詳細(xì)介紹如何封裝 axios 請(qǐng)求,具體實(shí)現(xiàn)的功能如下 基本配置 配置默認(rèn)請(qǐng)求地址,超時(shí)等 請(qǐng)求攔截 攔截 request 請(qǐng)求,處理一些發(fā)送請(qǐng)求之前做的處理,譬如給

    2024年02月07日
    瀏覽(30)
  • 一篇文章帶你了解 什么是u(ustd)帶你了解他的前世今生

    一篇文章帶你了解 什么是u(ustd)帶你了解他的前世今生

    在數(shù)字貨幣的繁榮世界中,USDT無(wú)疑是其中一位重要的角色。它的前世今生,是一個(gè)從無(wú)到有,從小到大,經(jīng)歷了種種波折和爭(zhēng)議的故事。 2014年11月下旬,一個(gè)名為Realcoin的注冊(cè)地為馬恩島和香港的公司決定改變自己的名字,取名為T(mén)ether。這個(gè)決定預(yù)示著一種新的數(shù)字貨幣即將

    2024年01月23日
    瀏覽(23)
  • WAF是什么?一篇文章帶你全面了解WAF

    Web應(yīng)用程序防火墻(Web Application Firewall,WAF)是一種用于保護(hù)Web應(yīng)用程序的安全設(shè)備。Web應(yīng)用程序是指通過(guò)Web瀏覽器或其他Web客戶(hù)端訪(fǎng)問(wèn)的應(yīng)用程序。WAF的目的是保護(hù)Web應(yīng)用程序免受黑客、網(wǎng)絡(luò)攻擊和數(shù)據(jù)泄漏等安全威脅的攻擊。 在這篇文章中,我們將深入探討WAF的工作原理

    2024年02月10日
    瀏覽(23)
  • 【網(wǎng)絡(luò)安全】一篇文章帶你了解CTF那些事兒

    【網(wǎng)絡(luò)安全】一篇文章帶你了解CTF那些事兒

    CTF(Capture The Flag)中文一般譯作奪旗賽,在網(wǎng)絡(luò)安全領(lǐng)域中指的是網(wǎng)絡(luò)安全技術(shù)人員之間進(jìn)行技術(shù)競(jìng)技的一種比賽形式。CTF起源于1996年DEFCON全球黑客大會(huì),以代替之前黑客們通過(guò)互相發(fā)起真實(shí)攻擊進(jìn)行技術(shù)比拼的方式。已經(jīng)成為全球范圍網(wǎng)絡(luò)安全圈流行的競(jìng)賽形式,2013年全

    2024年02月08日
    瀏覽(24)
  • 一篇文章帶你了解抖音來(lái)客功能的使用方法和注意事項(xiàng)

    一篇文章帶你了解抖音來(lái)客功能的使用方法和注意事項(xiàng)

    抖音是近年來(lái)備受歡迎的社交媒體平臺(tái)之一,其中的“來(lái)客”功能更是讓許多人喜愛(ài)。那么什么是抖音來(lái)客呢?抖音來(lái)客是指在直播過(guò)程中,可以邀請(qǐng)其他抖音用戶(hù)進(jìn)行互動(dòng)和參與,從而增加直播的熱度和粉絲數(shù)量。下面不若與眾科技就來(lái)介紹一下抖音來(lái)客的具體使用方法和

    2024年02月08日
    瀏覽(24)
  • 【云原生】什么是云原生?如何學(xué)習(xí)云原生?一篇文章帶你了解云原生

    【云原生】什么是云原生?如何學(xué)習(xí)云原生?一篇文章帶你了解云原生

    云原生,相信這個(gè)名詞大家并不陌生;云原生在近期可謂是爆火,伴隨云計(jì)算的滾滾浪潮,云原生(CloudNative)的概念應(yīng)運(yùn)而生,云原生很火,火得一塌糊涂??墒乾F(xiàn)在很多人還是不知道什么是云原生,所以今天我們就來(lái)聊一聊近期很火的這個(gè)名詞:云原生吧 。 大家平時(shí)經(jīng)常提

    2024年02月02日
    瀏覽(31)
  • 一篇文章帶你了解什么是云計(jì)算,SaaS PaaS IaaS的區(qū)別

    一篇文章帶你了解什么是云計(jì)算,SaaS PaaS IaaS的區(qū)別

    目錄 一、本地部署 vs 云計(jì)算 彈性 運(yùn)維成本 數(shù)據(jù)安全 二、SaaS PaaS IaaS的區(qū)別 在了解云計(jì)算之前,我們先要了解什么是“計(jì)算”,支撐計(jì)算我們需要硬件基礎(chǔ)設(shè)施和軟件環(huán)境。 硬件包括服務(wù)器、存儲(chǔ)、網(wǎng)絡(luò)等...? 軟件環(huán)境包括數(shù)據(jù)庫(kù)、中間件、操作系統(tǒng)等... 云就是個(gè)地理概

    2024年04月27日
    瀏覽(31)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包