C++學習筆記(十二)(STL string容器 )

本筆記主要來源於教程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大體分爲六大組件,分別是:容器,算法,迭代器,仿函數,適配器(配接器),空間配置器
 

  1. 容器:各種數據結構,如vector、list、deque、set、map等,用來存放數據
  2. 算法:各種常用的算法,如sort、find、copy、for_each等
  3. 迭代器:扮演了容器和算法之間的膠合劑
  4. 仿函數:行爲類似函數,可作爲算法的某種策略
  5. 適配器:一種用來修飾容器或者仿函數或迭代器接口的東西
  6. 空間配置器:負責空間的配置與管理

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個字符爲字符串str
  • string& 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個字符c
  • string& 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;

}

總結:靈活的運用求子串功能,可以在實際開發中獲取有效的信息

 
最後歡迎大家訪問我的個人博客青蛙聽禪的博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章