本筆記主要來源於教程https://www.bilibili.com/video/av41559729?p=1
2 STL初識
2.1 STL的誕生
- 長久以來,軟件界一直希望建立一種可重複利用的東西
- C++的面向對象和泛型編程思想,目的就是複用性的提升
- 大多數情況下,數據結構和算法都未能有一套標準,導致被迫從事大量重複工作
- 爲了建立數據結構和算法的一套標準,誕生類STL
2.2 STL基本概念
- STL(Standard Template Library,標準模板庫)
- STL從廣義上分爲:容器(container) 算法(algorithm) 迭代器(iterator)
- 容器和算法之間通過迭代器進行無縫連接。
- STL幾乎所有的代碼都採用了模板類或模板函數。
2.3 STL六大組件
STL大體分爲六大組件,分別是:容器,算法,迭代器,仿函數,適配器(配接器),空間配置器
- 容器:各種數據結構,如vector、list、deque、set、map等,用來存放數據
- 算法:各種常用的算法,如sort、find、copy、for_each等
- 迭代器:扮演了容器和算法之間的膠合劑
- 仿函數:行爲類似函數,可作爲算法的某種策略
- 適配器:一種用來修飾容器或者仿函數或迭代器接口的東西
- 空間配置器:負責空間的配置與管理
2.4 STL中容器,算法,迭代器
容器:置物之所也
STL容器就是將運用最廣泛的一些數據結構實現出來
常用的數據結構:數組,鏈表,樹,棧,隊列,集合,映射表等
這些容器分爲序列式容器和關聯式容器兩種:
序列式容器:強調值的排序,序列式容器中的每個元素均有固定的位置
關聯式容器:二叉樹結構,各元素之間沒有嚴格的物理上的順序關係
算法:問題之解法也
有限的步驟,解決邏輯或數學上的問題,這一門學科我們叫做算法(Algorithms)
算法分爲:質變算法和非質變算法
質變算法:是指運算過程中會更改區間內的元素的內容的算法,例如拷貝,替換,刪除等等
非質變算法:是指運算過程中不會更改區間內的元素內容的算法,例如查找,計數,遍歷,尋找極值等等
迭代器:容器和算法之間粘合劑 算法要通過迭代器才能訪問容器中的元素
提供一種方法,使之能夠依序尋訪某個容器所含的各個元素,而又無需暴露該容器的內部表示方式。
每個容器都有自己專屬的迭代器。
迭代器使用非常類似於指針,初學階段我們可以先理解迭代器爲指針。
種類 | 功能 | 支持運算 |
---|---|---|
輸入迭代器 | 對數據的只讀訪問 | 只讀,支持++,==,!= |
輸出迭代器 | 對數據的只寫訪問 | 只寫,支持++ |
前向迭代器 | 讀寫操作,並能向前推進迭代器 | 讀寫,支持++,==,!= |
雙向迭代器 | 讀寫操作,並能向前和向後操作 | 讀寫,支持++,– |
隨機訪問迭代器 | 讀寫操作,可以以跳躍的方式訪問任意數據,功能最強的迭代器 | 讀寫,支持++,–,[n],-n,<,<=,>,>= |
常用的容器中迭代器的種類爲雙向迭代器,和隨機訪問迭代器。
##2.5 容器算法迭代器初識
瞭解STL中容器、算法、迭代器概念之後,我們利用代碼感受STL的魅力
STL中最常見的容器爲Vector,可以理解爲數組,下面我們將學習如何向這個容器中插入數據,並遍歷這個容器
2.5.1 vector存放內置數據類型
容器:vector
算法:for_each
迭代器:vector<int>::iterator
#include
using namespace std;
#include
#include//標準算法頭文件
//vector容器存放內置數據類型
void myPrint(int val)
{
cout << val << endl;
}
void test01()
{
//創建了一個vector容器,數組
vector < int>v;
//向容器中插入數據
v.push_back(10);//尾插法
v.push_back(20);
v.push_back(30);
v.push_back(40);
//通過迭代器訪問容器中的數據
vector< int>::iterator itBegin = v.begin();//起始迭代器,指向容器中第一個元素
vector< int>::iterator itEnd = v.end();//結束迭代器,指向容器中最後一個元素的下一個位置
//第一種遍歷方式
while (itBegin != itEnd)
{
cout << *itBegin << endl;
itBegin++;
}
//第二種遍歷方式
for (vector< int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it<< endl;//*it就是<>中內容
}
//第三種遍歷方式 利用STL中提供的遍歷算法
for_each(v.begin(), v.end(), myPrint);
}
int main()
{
test01();
system("pause");
return 0;
}
2.5.2 Vector存放自定義數據類型
學習目標:vector中存放自定義數據類型,並輸出
#include
using namespace std;
#include< string>
#include< vector>
#include< algorithm>//標準算法頭文件
//vector容器中存放自定義的數據類型
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void test01()
{
vector< Person>v;
Person p1("aa", 10);
Person p2("asa", 120);
Person p3("ada", 120);
Person p4("faa", 110);
Person p5("aqa", 170);
//向容器中添加數據
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
//遍歷容器中的數據
for (vector< Person>::iterator it = v.begin(); it != v.end(); it++)
{
cout << "姓名: " << (*it).m_Name << " 年齡爲: " << (*it).m_Age << endl;
cout << "姓名: " << it->m_Name<< " 年齡爲: " << it->m_Age<< endl;
}
}
//存放自定義數據類型 指針
void test02()
{
vector< Person*>v;
Person p1("aa", 10);
Person p2("asa", 120);
Person p3("ada", 120);
Person p4("faa", 110);
Person p5("aqa", 170);
//向容器中添加數據
v.push_back(&p1);
v.push_back(&p2);
v.push_back(&p3);
v.push_back(&p4);
v.push_back(&p5);
//遍歷容器
for (vector< Person*>::iterator it = v.begin(); it != v.end(); it++)
{
cout << "::姓名: " << (*it)->m_Name << " 年齡爲: " << (*it)->m_Age << endl;
}
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
2.5.3 Vector容器嵌套容器
學習目標: 容器中嵌套容器,我們將所有數據進行遍歷輸出
//容器嵌套容器
void test01()
{
vector
(*it),<>中是什麼類型,它就是什麼類型
3.1 string容器
3.1.1 string容器基本概念
本質:
- string是C++風格的字符串,而string本質上是一個類
string和char*區別: - char*是一個指針
- string是一個類,類內部封裝了char*,管理這個字符串,是一個char*型的容器
特點:
string內部封裝了很多成員方法
例如:查找find,拷貝copy,刪除delete,替換replace,插入insert
string管理char*所分配的內存,不用擔心複製越界和取值越界等,由類內部進行負責
3.1.2 string構造函數
構造函數原型:
string();
//創建一個空的字符串,例如:string str;
string(const char *s);
//使用字符串s初始化string(const string& str);
//使用一個string對象初始化另一個string對象string(int n,char c);
//使用n個字符c初始化
#include
using namespace std;
#include
/*
string(); //創建一個空的字符串,例如:string str;
string(const char *s); //使用字符串s初始化
string(const string& str); //使用一個string對象初始化另一個string對象
string(int n,char c); //使用n個字符c初始化
*/
//string的構造函數
void test01()
{
string s1;//默認構造
const char *str = "helloworld";
string s2(str);
cout << "s2= " << s2 << endl;
string s3(s2);
cout << "s3= " << s3 << endl;
string s4(10, 'a');
cout << "s4= " << s4 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
總結:string的多種構造方式沒有可比性,靈活使用即可
3.1.3 string賦值操作
功能描述:
- 給string字符串進行賦值
賦值的函數原型: string& operator=(const char *s)
//char*類型字符串 賦值給當前的字符串string& operator=(const string &s);
//把字符串s賦給當前的字符串string& operator=(char c);
//字符賦值給當前的字符串string& assign(const char *s);
//把字符串s賦給當前的字符串string& assign(const char*s,int n);
//把字符串s的前n個字符賦給當前的字符串string& assign(const string *s);
//把字符串s賦給當前字符串string& assign(int n,char c);
//把n個字符串c賦給當前字符串
#include
using namespace std;
#include
//string 的賦值操作
/*
string& operator=(const char *s) //char*類型字符串 賦值給當前的字符串
string& operator=(const string &s); //把字符串s賦給當前的字符串
string& operator=(char c); //字符賦值給當前的字符串
string& assign(const char *s); //把字符串s賦給當前的字符串
string& assign(const char*s,int n); //把字符串s的前n個字符賦給當前的字符串
string& assign(const string *s); //把字符串s賦給當前字符串
string& assign(int n,char c); //把n個字符串c賦給當前字符串
*/
void test01()
{
string str1;
str1 = "hello world";
cout << "str1= " << str1 << endl;
string str2;
str2 = str1;
cout << "str2= " << str2 << endl;
string str3;
str3 ='a';
cout << "str3= " << str3 << endl;
string str4;
str4.assign("hello C++");
cout << "str4= " << str4 << endl;
string str5;
str5.assign("hello C++", 7);
cout << "str5= " << str5 << endl;
string str6;
str6.assign(str5);
cout << "str6= " << str6 << endl;
string str7;
str7.assign(10, 'w');
cout << "str7= " << str7 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
總結:
- string的賦值方式很多,
operator=
這種方式是比較實用的。
3.1.4 string字符串拼接
功能描述:
- 實現在字符串末尾拼接字符串
函數原型: string& operator+=(const char* str);
//重載+=操作符string& operator+=(const char c);
//重載+=操作符string& operator+=(const string& str);
//重載+=操作符string& append(const char* s);
//把字符串s連接到當前字符串結尾string& append(const char* s,int n);
//把字符串s的前n個字符連接到當前字符串結尾string& append(const string &s);
//同operator+=(const string& str)string& append(const string &s,int pos,int n);
//字符串s中從pos開始的n個字符連接到字符串結尾
#include
using namespace std;
#include
//string字符串拼接
/*
string& operator+=(const char* str); //重載+=操作符
string& operator+=(const char c); //重載+=操作符
string& operator+=(const string& str); //重載+=操作符
string& append(const char* s); //把字符串s連接到當前字符串結尾
string& append(const char* s,int n); //把字符串s的前n個字符連接到當前字符串結尾
string& append(const string &s); //同operator+=(const string& str)
string& append(const string &s,int pos,int n);//字符串s中從pos開始的n個字符連接到字符串結尾
*/
void test01()
{
string str1 = "我";
str1 += "愛玩遊戲";
cout << "str1= " << str1 << endl;
str1 += ':';
cout << "str1= " << str1 << endl;
string str2 = "LOL,DNF";
str1 += str2;
cout << "str1= " << str1 << endl;
string str3 = "I";
str3.append(" love");
cout << "str3= " << str3 << endl;
str3.append(" game abcde", 4);
cout << "str3= " << str3 << endl;
str3.append(str2);
cout << "str3= " << str3 << endl;
//只截取三個 參數2是從哪個位置開始截取,參數3是截取個數
str3.append(str2, 0, 3);
cout << "str3= " << str3 << endl;
str3.append(str2, 4, 3);
cout << "str3= " << str3 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
總結:字符串拼接的重載版本很多,初學階段記住幾種即可。
3.1.5 string查找和替換
功能描述:
- 查找:查找指定字符是否存在
- 替換:在指定的位置替換字符串
函數原型: int find(const string& str,int pos=0)const;
//查找str第一次出現位置,從pos開始查找int find(const char* s,int pos=0)const;
//查找s第一次出現位置,從pos開始查找int find(const char* s,int pos,int n)const;
//從pos位置查找s的前n個字符第一次位置int find(const char c,int pos=0)const;
//查找字符c第一次出現位置int rfind(const string&str,int pos=npos)const;
//查找str最後一次位置,從pos開始查找int rfind(const char* s,int pos=npos)const;
//查找s最後一次出現位置,從pos開始查找int rfind(const char*s,int pos,int n)const;
從pos查找s的前n個字符最後一次位置int rfind(const char c,int pos=0)const;
//查找字符c最後一次出現位置string& replace(int pos,int n,const string& str);
//替換從pos開始n個字符爲字符串strstring& replace(int pos,int n,const char* s);
//替換從pos開始的n個字符爲字符串s
示例:
//字符串查找和替換
//1、查找
void test01()
{
string str1 = "abcdefgde";
int pos=str1.find("de");//0,1,2,3
int pos2 = str1.find("df");//沒有返回-1
if (pos == -1)
{
cout << "未找到字符串" << endl;
}
else
{
cout << "找到字符串.pos= " << pos << endl;
}
//rfind 和find區別是rfind從右往左查找(但是都是從左往右數),而find從左往右查找
pos = str1.rfind("de");
cout << "找到字符串.pos= " << pos << endl;
}
//2、替換
void test02()
{
string str1 = "abcdefg";
//從一號位置起,三個字符,替換爲“1111”
str1.replace(1, 3, "1111");
cout << "str1= " << str1 << endl;//結果:str1= a1111efg
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
總結:
- find查找是從左往右,rfind查找是從右往左(但是都是從左往右數)
- find找到字符後返回查找的第一個字符位置,找不到返回-1(0,1,2,3)
- replace在替換時,要指定從哪個位置起,多少個字符,替換成什麼樣的字符串
3.1.6 string字符串比較
功能描述:
- 字符串之間的比較
比較方式: - 字符串比較是按字符串的ASCII碼進行對比
等於 返回 0
大於 返回 1
小於 返回 -1
函數原型:int compare(const string& s)const
//與字符串s比較int compare(const char* s)const
//與字符串s比較
//字符串比較
void test01()
{
string str1 = "xello";
string str2 = "zello";
if (str1.compare(str2) == 0)//一般都用來比較是否相等,比如中文比較大小毫無意義
{
cout << "str1 等於 str2" << endl;
}
else if (str1.compare(str2) > 0)
{
cout << "str1 大於 str2" << endl;
}
else if (str1.compare(str2) < 0)
{
cout << "str1 小於 str2" << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
總結:字符串對比主要是用於比較兩個字符串是否相等,判斷誰大誰小的意義並不是很大。
3.1.7 string字符存取
string中單個字符存儲方式有兩種:
char& operator[](int n);
//通過[]方式取字符char& at(int n);
//通過at方式獲取字符
//string字符存取
void test01()
{
string str = "hello";
cout << "str= "<
總結:string字符串中單個字符存取有兩種方式,利用[]或at。
3.1.8 string插入和刪除
功能描述:
- 對string字符串進行插入和刪除字符操作
函數原型: string& insert(int pos,const char* s);
//插入字符串string& insert(int pos,const string& str);
//插入字符串string& insert(int pos,int n,char c);
//在指定位置插入n個字符cstring& erase(int pos,int n=npos);
//刪除從Pos開始的n個字符
示例:
//字符串 插入和刪除
void test01()
{
string str = "hello";
//插入
str.insert(1, "111");
cout << "str= " << str << endl;//結果str= h111ello
//刪除
str.erase(1, 3);
cout << "str= " << str << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
總結:插入和刪除下標都是從0開始
3.1.9 string子串
功能描述:
- 從字符串中獲取想要的子串
函數原型:
string substr(int pos = 0, int n = npos) const;
//返回由pos開始的n個字符組成的字符串
示例:
//string求子串
void test01()
{
string str = "abcdef";
string Substr = str.substr(1, 3);
cout << "subStr = " << Substr << endl;//結果subStr = bcd
}
//實用操作
void test02()
{
string email = "[email protected]";
//從郵件地址中 獲取 用戶名信息
int pos=email.find("@");
cout << pos << endl;
string usrName = email.substr(0, pos);
cout << usrName << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
總結:靈活的運用求子串功能,可以在實際開發中獲取有效的信息
最後歡迎大家訪問我的個人博客青蛙聽禪的博客