?1. 什么是STL
STL(standard template libaray-標準模板庫):是C++標準庫的重要組成部分,不僅是一個可復用的組件庫,而且 是一個包羅數據結構與算法的軟件框架。
2. STL的版本
原始版本
Alexander Stepanov、Meng Lee 在惠普實驗室完成的原始版本,本著開源精神,他們聲明允許任何人任意 運用、拷貝、修改、傳播、商業使用這些代碼,無需付費。唯一的條件就是也需要向原始版本一樣做開源使 用。 HP 版本--所有STL實現版本的始祖。
P. J. 版本
由P. J. Plauger開發,繼承自HP版本,被Windows Visual C++采用,不能公開或修改,缺陷:可讀性比較低, 符號命名比較怪異。
RW版本
由Rouge Wage公司開發,繼承自HP版本,被C+ + Builder 采用,不能公開或修改,可讀性一般。
SGI版本
由Silicon Graphics Computer Systems,Inc公司開發,繼承自HP版 本。被GCC(Linux)采用,可移植性好, 可公開、修改甚至販賣,從命名風格和編程 風格上看,閱讀性非常高。我們后面學習STL要閱讀部分源代碼, 主要參考的就是這個版本。
3. STL的六大組件
今天我們主要要講到string和reverse(逆置)
1. 為什么學習string類?
1.1 C語言中的字符串
C語言中,字符串是以'\0'結尾的一些字符的集合,為了操作方便,C標準庫中提供了一些str系列的庫函數, 但是這些庫函數與字符串是分離開的,不太符合OOP的思想,而且底層空間需要用戶自己管理,稍不留神可 能還會越界訪問。
2. 標準庫中的string類
2.1 string類(了解)
string類的文檔介紹
- 字符串是表示字符序列的類
- 標準的字符串類提供了對此類對象的支持,其接口類似于標準字符容器的接口,但添加了專門用于操作 單字節字符字符串的設計特性。
- ?string類是使用char(即作為它的字符類型,使用它的默認char_traits和分配器類型(關于模板的更多信 息,請參閱basic_string)。
- string類是basic_string模板類的一個實例,它使用char來實例化basic_string模板類,并用char_traits 和allocator作為basic_string的默認參數(根于更多的模板信息請參考basic_string)。
- 注意,這個類獨立于所使用的編碼來處理字節:如果用來處理多字節或變長字符(如UTF-8)的序列,這個 類的所有成員(如長度或大小)以及它的迭代器,將仍然按照字節(而不是實際編碼的字符)來操作。
總結:
- string是表示字符串的字符串類
- ?該類的接口與常規容器的接口基本相同,再添加了一些專門用來操作string的常規操作。
- ?string在底層實際是:basic_string模板類的別名,typedef basic_string string;
- 不能操作多字節或者變長字符的序列。
在使用string類時,必須包含#include頭文件以及using namespace std;
2.2 string類的常用接口說明
(注意下面只講解最常用的接口)
1. string類對象的常見構造
看一下string的一些實現
上面使用到了 傳地址(開辟新空間接收)和?直接傳字符串(會發現,其實是傳的引用):
2. string類對象的容量操作
可以測試發現:
注意:clear清理的是size,capacity不變
reserve
通過查閱可以了解其性能?
【注意】
- ?size()與length()方法底層實現原理完全相同,引入size()的原因是為了與其他容器的接口保持一 致,一般情況下基本都是用size()。
- ?clear()只是將string中有效字符清空,不改變底層空間大小。
- ?resize(size_t n) 與 resize(size_t n, char c)都是將字符串中有效字符個數改變到n個,不同的是當字 符個數增多時:resize(n)用0來填充多出的元素空間,resize(size_t n, char c)用字符c來填充多出的 元素空間。注意:resize在改變元素個數時,如果是將元素個數增多,可能會改變底層容量的大小,如果是將元素個數減少,底層空間總大小不變。
- reserve(size_t res_arg=0):為string預留空間,不改變有效元素個數,當reserve的參數小于 string的底層空間總大小時,reserver不會改變容量大小。
?3. string類對象的訪問及遍歷操作
那么我們現在遍歷字符串就有三種方法了:
?1. for+operator[]
for (size_t i = 0; i < s.size(); ++i)cout << s[i] << endl;
2.迭代器 iterator?
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;
4. string類對象的修改操作
一些實現和應用
void Teststring5()
{string str;str.push_back(' '); // 在str后插入空格str.append("hello"); // 在str后追加一個字符"hello"str += 'b'; // 在str后追加一個字符'b' str += "it"; // 在str后追加一個字符串"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里面的一個靜態成員變量// 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的協議前綴pos = url.find("://");url.erase(0, pos + 3);cout << url << endl;
}
【注意】:
1. 在string尾部追加字符時,s.push_back(c) / s.append(1, c) / s += 'c'三種的實現方式差不多,一般 情況下string類的+=操作用的比較多,+=操作不僅可以連接單個字符,還可以連接字符串。
2. 對string操作時,如果能夠大概預估到放多少字符,可以先通過reserve把空間預留好。
5. string類非成員函數
上面的幾個接口大家可以了解一下,下面的OJ題目中會有一些體現他們的使用。string類中還有一些其他的 操作,這里不一一列舉,大家在需要用到時不明白了查文檔即可~