<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
STL(standard template libaray-標準模板庫):是C++標準庫的重要組成部分,不僅是一個可複用的元件庫,而且是一個包羅資料結構與演演算法的軟體框架。
可以理解為就是一個類似stdio.h的庫,包含了這個庫,裡面的語法或者函數可以直接使用。
最原始的版本是由Alexander Stepanov和Meng Lee開發的,並且他們要求對其進行開源處理。之後又經歷了PJ.版本,RW版本,SGI版本等,目前SGI版本最應用最廣泛的版本,我們後面學習STL要閱讀部分原始碼,主要參考這一版本。
總結一下目前開源與閉源的作業系統或者軟體:
開源:STL,linux,git,Vue
閉源:IOS,Windows
第一境界:熟練使用STL。
第二境界:瞭解STL的原始碼,即瞭解底層。
第三境界:會自己擴充STL庫。
廢話不多說,正式進入主題:
STL有六大組成部分,我們會來逐一學習:
首先我們來學習容器中的string類。
string類,顧名思義是進行字串操作的一個類,操作方式即使用其中的成員函數來進行操作。
#include<string> using namespace std;
string也是在類域std中的,我們在練習時也可以將類域std開啟。
通過查閱文獻,我們發現string類原來是typedef出來的,是對basic_string這一模板傳入char型別時起的別名。這一模板的定義方式大概是這樣的:
template<class T> class basic_string { private: T* _str; //.... }
有人會問為什麼要使用模板呢?字串型別除了char還有別的嘛?
其實字元型別除了char之外還有別的型別,比如wchar_t就佔兩個位元組。我們儲存漢字一般會使用兩個位元組來進行儲存。所以對於兩位元組儲存的字元再使用basic_string傳入wchar_t起別名的話就方便的多了。
注意:string類中傳入的是char,上面只作瞭解即可。
建構函式即用於初始化。
1.string()
:構造空的string類物件str,即空字串。
2.string (const char* s)
:向物件中傳入字串來構造string物件。
3.string(size_t n,char c)
:string類物件中包含n個字元c。
4.string(const string&s)
:拷貝建構函式。
string s1;//空字串s1。 string s2("hello world");//向s2中傳入hello world。 string s3(s2, 2, 6);//向s3中傳入s2中從第二個開始(不包括第二個)後六個字元。當最後不加數值時(即不加6),則會取後面的全部字元。 string s4(s2);//用s2對s4進行初始化。 cout << s1 << endl;//過載運運算元,可以直接列印s1物件的字串內容。 cout << s2 << endl; cout << s3 << endl; cout << s4 << endl;
自動呼叫,不用管。
1.size
:返回有效字元長度。
2.length
:返回字串的有效字元長度。是一個歷史殘留問題。
3.capacity
:返回空間總大小。
4.empty
:檢測字串是否為空,是返回true,不是返回false
5.clear
:清空有效字元。
6.reserve
:為字串預留空間。
7.resize
:將有效字元改成n個,多出的用字元C填充。
string s1("hello world"); cout << s1.size() << endl;//輸出字串大小,不包括' ' cout << s1.length() << endl;//輸出字串大小,不包括' ' cout << s1.capacity() << endl;//輸出空間總大小 s1.clear();//清空有效字串 cout << s1 << endl;
擴容一般使用兩種函數,reserve與resize。reserve主要為開空間,而resize在開空間的同時還會進行初始化。
string s1("hello world"); cout << s1.capacity() << endl; s1.reserve(100); cout << s1.capacity() << endl;
列印的結果是:
通過列印我們發現,reserve擴充套件的空間是在原有字串大小基礎上擴充套件的,而不是在原有容量的基礎上。
string s1("hello world"); s1.resize(100,'x');
我們可以通過偵錯來觀察這段程式碼的效果:
我們發現hello world並沒有被覆蓋,最大空間變成了111和reserve一樣。但是,x只有89個,一共增加了100-11個x,但是在hello world後面增加了100個空間。
如果我們開闢的空間小於字串本身呢?s1.resize(5)表示的是隻保留前五個字元大小。
我們可以使用s1[i]來進行字元的讀或者寫的操作。
string s1("hello world"); for (size_t i = 0; i < s1.size(); i++) { cout << s1[i] << " ";//s1[i]進行讀操作 s1[i] += 1; } cout << endl; for (size_t i = 0; i < s1.size(); i++) { cout << s1[i] << " ";//s1[i]進行寫操作 }
char& operator[](size_t pos) { return _str[pos];//返回pos位置所在的字元 }
注意,這裡使用參照返回不是為了減少拷貝,這裡是為了修改返回物件。
at也是和operator[]一樣,但是檢測越界的方法不同,operator[]使用斷言,at直接拋異常。
在剛開始使用迭代器時,我們可以把它想象成一個指標型別。
string s1("hello world"); string::iterator it = s1.begin(); while (it != s1.end()) { cout << *it << " "; ++it; } cout << endl;
其中it就是一個迭代器型別的變數,由於函數iterator在類內,因此在使用時需要首先指明類域。
我們仍然使用解除參照操作符來進行類似解除參照的操作。我們同樣也可以通過*來對字串的內容進行修改,對這段程式碼列印的結果是:
反向迭代器使用函數reverse_iterator
string s1("hello world"); string::reverse_iterator rit = s1.rbegin(); while (rit != s1.rend()) { cout << *rit; ++rit; }
列印的結果是剛好反過來的:
注意:我們定義反向迭代器rit之後,在進行遍歷時雖然是從後向前遍歷,但是仍需要對rit進行++操作。
迭代的意義主要體現在和[]進行對比,有人可能認為既然可以用下標直接參照,為什麼還要使用迭代器呢?
這是因為對於string來說,下標和[]就足夠好用,可以不使用迭代器,但是對於其他容器,比如list map/set等不支援下標加[]遍歷,比如對於連結串列來說,由於實體記憶體不連續所以不能使用下標來進行遍歷。
除了普通迭代器之外,還有const修飾的迭代器等等。後面會詳細說明的。
除了使用迭代器遍歷之外,我們還可以使用語法糖來進行遍歷操作:
string s1("hello world"); for (auto& e : s1) { cout << e << " "; }
範圍for會把s1中的每一個字元取出來賦值給e(使用參照則為它本身),自動往後迭代,自動判斷結束。
push back
:在字串後尾插字元c
append
:在字串後追加一個字串
operator+=
:在字串後追加字串str
c str
:返回C格式字串
find+nops
:從字串pos位置開始往後找字元c,返回該字元再字串中的位置。
rfind
:從字串中pos位置開始往前找字元c,返回該字元再字串中的位置。
substr
:在str中從pos位置開始,擷取n個字元,然後將其返回。
string s1("hello world"); s1.push_back('a');//在末尾插入字元a cout << s1 << endl; s1.append("bcd");//在末尾插入字串bcd cout << s1 << endl; s1 += 'e';//在末尾插入字元e cout << s1 << endl; s1 += "hello linux";//在末尾插入字串hello linux cout << s1 << endl;
注意:推薦直接使用操作符過載進行增刪操作。
下面是一段字串擷取的程式碼,擷取字尾.txt:
string file("test.txt"); size_t pos = file.find('.');//返回第一次匹配'.'的位置 if (pos != string::npos) { string suffix = file.substr(pos, file.size() - pos);//將.之後的內容賦值給suffix cout << suffix << endl; }
find會返回第一次出現匹配的位置,如果匹配失敗會返回nops(無符號-1,表示一個極大的數)。
substr是字串擷取函數,意思是擷取pos位置與file.size()-pos位置的字串。
同上,我們也可以使用rfind進行倒著查詢。
這裡再舉一個擷取網址的例子:
我們都知道網址分為三部分:協定,域名與網路路徑。下面使用find與substr來進行擷取操作。
string url("http://www.cplusplus.com/reference/string/string/find/"); size_t pos1 = url.find(':'); string protocol = url.substr(0, pos1 - 0); cout << protocol << endl; size_t pos2 = url.find('/', pos1 + 3);//從pos+3的位置開始找 string domain = url.substr(pos1 + 3, pos2 - (pos1 + 3)); cout << domain << endl; string uri = url.substr(pos2 + 1);//沒指定結尾位置,預設為整個後面內容 cout << uri << endl;
列印的結果為:
使用insert與erase兩函數進行操作:
string s("hello world"); s.insert(0, 1, 'x');//在0位置插入一個1 s.insert(s.begin(), 'y');//在頭處插入一個y s.insert(0, "test");//在頭處插入test s.insert(4, "&&");//在第四個位置插入特殊符號 s.erase(0, 1);//刪除頭處第一個字元 s.erase(s.size() - 1, 1);//尾刪一個字元 cout << s << endl;
列印的結果為:
在使用erase時,如果不給值的話,會繼續刪完。
儘量少使用頭部和中間的刪除,因為要挪動資料,效率較低。
和C語言中strcmp一樣,string類也有對字串的比較,不過是通過運運算元過載。
string s1("hello world"); string s2("string"); cout << (s1 < s2) << endl; cout << ("hhh" > s2) << endl;
注意我們可以使用兩種方式來說進行字串比較,一種是s1<s2,另一種是直接進行比較。
與strcmp原理一樣,會從兩個字串起始位置開始比較,如果為真則返回1,如果為假返回0。
我們使用stoi(string to int)來將字串轉為整型,使用to_string來將其他型別轉換為字串。
int val = stoi("1234"); string str = to_string(3.14);
我們可以通過偵錯來觀察轉換是否成功:
可見,轉換很成功。
string類是表示字串的字串類,在使用string類時必須包含標頭檔案,並開放std空間,在OJ中有關字串的題目基本以string類的形式出現,而且在常規工作中,為了簡單、方便、快捷,基本都會使用string類,很少有人去使用C庫中的字串操作函數。
本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45