1. 程式人生 > >C++——標準模板庫

C++——標準模板庫

1、泛型程式設計:將程式儘可能寫的通用,將演算法從特定的資料結構中抽象出來,成為通用的;C++模板為泛型程式設計奠定了關鍵的基礎;STL是泛型程式設計的一個範例:容器container、迭代器iterator、演算法algorithms和函式物件function object。

2、名稱空間namespace:一個名稱空間將不同的識別符號集合在一個命名作用域(named scope)中,是為了解決命名衝突。沒有宣告名稱空間的識別符號都處在無名的名稱空間中。

例如,宣告一個名稱空間NS:
namspace NS {
class File;
void Fun ();
}
則引用識別符號的方式如下,
NS:: File obj;
NS:: Fun ();


可以利用using namespace std;指定在名稱空間std中所有識別符號都可以直接飲用,using NS::file;在當前作用域中就可以直接飲用file。

在新的C++標準程式庫中,所有識別符號都宣告在名稱空間std中,標頭檔案都不使用副檔名。

3、容器:容器類是容納、包含一組元素或元素集合的物件。異類容器類與同類容器類。還可以分為順序容器與關聯容器。七種基本容器:向量(vector)、雙端佇列(deque)、列表(list)、集合(set)、多重集合(multiset)、對映(map)和多重對映(multimap)

容器的介面:外界可以使用的功能。包括方法函式和運算子。

通用運算子:==,!=,>,>=,<,<=,=
迭代方法begin(),end(),rbegin(),rend();訪問方法size(),max_size(),swap(),empty()

順序容器:介面:插入方法 push_front(), push_back(), insert(), 運算子"="。

                 刪除方法 pop(), erase(),clear()

                 迭代訪問方法 使用迭代器

                 其他順序容器訪問方法(不修改的訪問方法) front(),back(),下標運算子[]。

順序容器向量:向量屬於順序容器,用於容納不定長的線性序列,提供對序列的快速隨機訪問,就是直接訪問。向量是動態結構,它的大小不固定,可以在程式執行時增加或者減少。

例子:求反問2~N中的質數,N在程式執行時由鍵盤輸入。

#include <iostream>
#include <iomanip>
#include <vector> //包含向量容器標頭檔案
using namespace std ;
int main()
{   
    vector<int>  A(10); // 用來存放質數的向量,初始狀態有10個元素。
    int n; //質數範圍的上限,執行時輸入
    int primecount = 0, i, j;
    cout << "Enter a value >= 2 as upper limit for prime numbers: ";
    cin >> n;
    A[primecount++] = 2; // 2是一個質數
    for(i = 3; i < n; i++)
    {
        if (primecount == A.size()) // 如果質數表已滿,則再申請10個元素的空間
            A.resize(primecount + 10);
        if (i % 2 == 0) //大於2的偶數不是質數,因此略過本次迴圈的後繼部分
            continue;
        // 檢查3,5,7,...,i/2是否i的因子
        j = 3;
        while (j <= i/2 && i % j != 0)
            j += 2;       

        if (j > i/2) // 若上述引數均不為i的因子,則i為質數
            A[primecount++] = i;
    }
    for (i = 0; i < primecount; i++) //輸出質數
    {
        cout << setw(5) << A[i];
        if ((i+1) % 10 == 0) //每輸出10個數換行一次
            cout << endl;
    }
    cout << endl;
}

4、介面卡:介面卡是一種介面類,為已有的類提供新的介面,目的是簡化、約束,使之安全、隱藏或者改變被修改類提供的服務的集合。主要有三種介面卡型別:容器介面卡(用來擴充套件7中基本容器),迭代器介面卡和函式物件介面卡。

5、迭代器:是面向物件版本的指標,提供了訪問容器、序列中每個元素的方法

輸入迭代器
可以用來從序列中讀取資料
輸出迭代器
允許向序列中寫入資料
前向迭代器
既是輸入迭代器又是輸出迭代器,並且可以對序列進行單向的遍歷
雙向迭代器
與前向迭代器相似,但是在兩個方向上都可以對資料遍歷
隨機訪問迭代器
也是雙向迭代器,但能夠在序列中的任意兩個位置之間進行跳轉。
6、演算法:標準模板庫中包括了70多個演算法,其中包括了查詢演算法、排序演算法、消除演算法、計數演算法、比較演算法、變換演算法、置換演算法和容器管理等等

演算法是一種函式模板,可以分為

不可變序列演算法(non-mutating algorithms),不直接修改所操作的容器內容的演算法
可變序列演算法(mutating algorithms),可以修改它們所操作的容器的元素。
排序相關演算法和數值演算法
例6-1,應用不可變序列演算法對資料序列進行分析
例6-2,以可變序列演算法對資料序列進行復制,生成,刪除,替換,倒序,旋轉等可變性操作。
例6-3,應用排序相關演算法對序列進行各項操作
例6-4,應用數值演算法對資料序列進行操作

//6-1.cpp
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;

int main()
{
 int iarray[]={0,1,2,3,4,5,6,6,6,7,8};
 vector<int> ivector(iarray,iarray+sizeof(iarray)/sizeof(int));
 int iarray1[]={6,6};
 vector<int> ivector1(iarray1,iarray1+sizeof(iarray1)/sizeof(int));  
 int iarray2[]={5,6};
 vector<int> ivector2(iarray2,iarray2+sizeof(iarray2)/sizeof(int));
 int iarray3[]={0,1,2,3,4,5,7,7,7,9,7};
 vector<int> ivector3(iarray3,iarray3+sizeof(iarray3)/sizeof(int));

 //找出ivector之中相鄰元素值相等的第一個元素
 cout<<*adjacent_find(ivector.begin(),ivector.end())<<endl;

 //找出ivector之中元素值為6的元素個數
 cout<<count(ivector.begin(),ivector.end(),6)<<endl;

 //找出ivector之中小於7的元素個數
 cout<<count_if(ivector.begin(),ivector.end(),bind2nd(less<int>(),7))<<endl;

 //找出ivector之中元素值為4的第一個元素所在位置的元素
 cout<<*find(ivector.begin(),ivector.end(),4)<<endl;

 //找出ivector之中大於2的第一個元素所在位置的元素
 cout<<*find_if(ivector.begin(),ivector.end(),bind2nd(greater<int>(),2))
<<endl;
 
 //找出ivector之中子序列ivector1所出現的最後一個位置,再往後3個位置的元素
 cout<<*(find_end(ivector.begin(),ivector.end(),ivector1.begin(),
ivector1.end())+3)<<endl;

 //找出ivector之中子序列ivector1所出現的第一個位置,再往後3個位置的元素
 cout<<*(find_first_of(ivector.begin(),ivector.end(),ivector1.begin(),
ivector1.end())+3)<<endl;
 
 //子序列ivector2在ivector中出現的起點位置元素
 cout<<*search(ivector.begin(),ivector.end(),ivector2.begin(),ivector2.end())
<<endl;

 //查詢連續出現3個6的起點位置元素
 cout<<*search_n(ivector.begin(),ivector.end(),3,6,equal_to<int>())<<endl;

 //判斷兩個區間ivector和ivector3相等否(0為假,1為真)
cout << equal(ivector.begin(), ivector.end(), ivector3.begin()) << endl;

 //查詢區間ivector3在ivector中不匹配點的位置
pair<int*,int*>result=mismatch(ivector.begin(),ivector.end(),ivector3.begin());
cout<< result.first - ivector.begin() << endl;
}
//6-2.cpp
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;

class even_by_two{             //類定義形式的函式物件
public:
 int operator()() const
 {return _x+=2;}
private:
 static int _x;
};
int even_by_two::_x=0;       //靜態資料成員初始化

int main()
{
 int iarray[]={0,1,2,3,4,5,6,6,6,7,8};
 int iarray1[]={0,1,2,3,4,4,5,5,6,6,6,6,6,7,8};
 vector<int> ivector(iarray,iarray+sizeof(iarray)/sizeof(int));
 vector<int> ivector1(iarray+6,iarray+8);  
 vector<int> ivector2(iarray1,iarray1+sizeof(iarray1)/sizeof(int));
 ostream_iterator< int > output( cout, " " );  //定義流迭代器用於輸出資料
 
 //迭代遍歷ivector1區間,對每一個元素進行even_by_two操作
    generate(ivector1.begin(),ivector1.end(),even_by_two());
 copy(ivector1.begin(),ivector1.end(),output);
 cout<<endl;

 //迭代遍歷ivector的指定區間(起點和長度),對每一個元素進行even_by_two操作
    generate_n(ivector.begin(),3,even_by_two());
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;

 //刪除元素6
    remove(ivector.begin(),ivector.end(),6);
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;
 
 //刪除(實際並未從原序列中刪除)元素6,結果置於另一個區間
    vector<int> ivector3(12);
 remove_copy(ivector.begin(),ivector.end(),ivector3.begin(),6);
 copy(ivector3.begin(),ivector3.end(),output);
 cout<<endl;

 //刪除(實際並未從原序列中刪除)小於6的元素
 remove_if(ivector.begin(),ivector.end(),bind2nd(less<int>(),6));
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;
 
 //刪除(實際並未從原序列中刪除)小於7的元素,結果置於另一個區間,
 remove_copy_if(ivector.begin(),ivector.end(),ivector3.begin(),
bind2nd(less<int>(),7));
 copy(ivector3.begin(),ivector3.end(),output);
 cout<<endl;
 
 //將所有的元素值6,改為元素值3
 replace(ivector.begin(),ivector.end(),6,3);
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;
 
 //將所有的元素值3,改為元素值5,結果放置到另一個區間
 replace_copy(ivector.begin(),ivector.end(),ivector3.begin(),3,5);
 copy(ivector3.begin(),ivector3.end(),output);
 cout<<endl;
 
 //將所有小於5的元素值,改為元素值2
 replace_if(ivector.begin(),ivector.end(),bind2nd(less<int>(),5),2);
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;
 
 //將所有的元素值8,改為元素值9,結果放置到另一個區間
 replace_copy_if(ivector.begin(),ivector.end(),ivector3.begin(),
bind2nd(equal_to<int>(),8),9);
 copy(ivector3.begin(),ivector3.end(),output);
 cout<<endl;
 
 //逆向重排每一個元素
 reverse(ivector.begin(),ivector.end());
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;
 
 //逆向重排每一個元素,結果置於另一個區間
 reverse_copy(ivector.begin(),ivector.end(),ivector3.begin());
 copy(ivector3.begin(),ivector3.end(),output);
 cout<<endl;
 
 //旋轉(互換元素)[first,middle), 和[middle,end)
 rotate(ivector.begin(),ivector.begin()+4,ivector.end());
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;
 
 //旋轉(互換元素)[first,middle], 和[middle,end],結果置於另一個區間,
 rotate_copy(ivector.begin(),ivector.begin()+5,ivector.end(),
ivector3.begin());
 copy(ivector3.begin(),ivector3.end(),output);
 cout<<endl;
}

//6-3.cpp
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;

int main()
{
 int iarray[]={26,17,15,22,23,33,32,40};
 vector<int> ivector(iarray,iarray+sizeof(iarray)/sizeof(int));
 
 // 查詢並輸出最大、最小值元素
 cout<<*max_element(ivector.begin(),ivector.end())<<endl;
 cout<<*min_element(ivector.begin(),ivector.end())<<endl;

 //將ivector.begin()+4-ivector.begin()各元素排序,
 //放進[ivector.begin(),ivector.begin()+4]區間。剩餘元素不保證維持原來相對次序
 partial_sort(ivector.begin(),ivector.begin()+3,ivector.end());
 copy(ivector.begin(),ivector.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //區域性排序並複製到別處
 vector<int> ivector1(5);
 partial_sort_copy(ivector.begin(),ivector.end(),ivector1.begin(),
ivector1.end());
 copy(ivector1.begin(),ivector1.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //排序,預設為遞增。
 sort(ivector.begin(),ivector.end());
 copy(ivector.begin(),ivector.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //將指定元素插入到區間內不影響區間原來排序的最低、最高位置
 cout<<*lower_bound(ivector.begin(),ivector.end(),24)<<endl;
 cout<<*upper_bound(ivector.begin(),ivector.end(),24)<<endl;

 //對於有序區間,可以用二分查詢方法尋找某個元素
    cout<<binary_search(ivector.begin(),ivector.end(),33)<<endl;
    cout<<binary_search(ivector.begin(),ivector.end(),34)<<endl;

 //下一個排列組合
 next_permutation(ivector.begin(),ivector.end());
 copy(ivector.begin(),ivector.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //上一個排列組合
 prev_permutation(ivector.begin(),ivector.end());
 copy(ivector.begin(),ivector.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //合併兩個序列ivector和ivector1,並將結果放到ivector2中
 vector<int> ivector2(13);
 merge(ivector.begin(),ivector.end(),ivector1.begin(),ivector1.end(),
ivector2.begin());
 copy(ivector2.begin(),ivector2.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //將小於*(ivector.begin()+5)的元素放置在該元素之左
 //其餘置於該元素之右。不保證維持原有的相對位置
 nth_element(ivector2.begin(),ivector2.begin()+5,ivector2.end());
 copy(ivector2.begin(),ivector2.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //排序,並保持原來相對位置
 stable_sort(ivector2.begin(),ivector2.end());
 copy(ivector2.begin(),ivector2.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //針對一個有序區間,找出其中一個子區間,其中每個元素都與某特定元素值相同
 pair<vector<int>::iterator,vector<int>::iterator> pairIte;
 pairIte=equal_range(ivector2.begin(),ivector2.end(),22);
 cout<<*(pairIte.first)<<endl;
 cout<<*(pairIte.second)<<endl;

 //合併兩個有序序列,然後就地替換
 int iarray3[] = { 1, 3, 5, 7, 2, 4, 6, 8 };
 vector<int> ivector3(iarray3,iarray3+sizeof(iarray3)/sizeof(int));
 inplace_merge(ivector3.begin(), ivector3.begin()+ 4, ivector3.end());
 copy(ivector3.begin(),ivector3.end(), ostream_iterator<int>(cout, " ")); 
 cout<<endl;
 
 //以字典順序比較序列ivector3和ivector4
 int iarray4[] = { 1, 3, 5, 7,1, 5, 9, 3 };
 vector<int> ivector4(iarray4,iarray4+sizeof(iarray4)/sizeof(int));
 cout<< lexicographical_compare(ivector3.begin(),ivector3.end(),
ivector4.begin(),ivector4.end()) << endl;
}
//6-4.cpp
#include <iostream>
#include <numeric>
#include <functional>
#include <vector>
using namespace std;

int main()
{
 int iarray[]={1,2,3,4,5};
 vector<int> ivector(iarray,iarray+sizeof(iarray)/sizeof(int));

 //元素的累計
 cout<<accumulate(ivector.begin(),ivector.end(),0)<<endl;
 //向量的內積
 cout<<inner_product(ivector.begin(),ivector.end(),ivector.begin(),10)<<endl;
 //向量容器中元素區域性求和
 partial_sum(ivector.begin(),ivector.end(),ostream_iterator<int>(cout," "));
 cout<<endl;
 //向量容器中相鄰元素的差值
 adjacent_difference(ivector.begin(),ivector.end(),
ostream_iterator<int>(cout," "));
 cout<<endl;
}
7、函式物件:一個行為類似於函式的物件,它可以沒有引數,也可以帶有若干引數,其功能是獲取一個值,或者改變操作的狀態。任何普通的函式和任何過載了呼叫運算子operate()的類的物件都滿足函式物件的特徵,STL中也定義了一些標準的函式物件,如果以功能劃分,可以分為算術運算、關係運算、邏輯運算三大類。為了呼叫這些標準函式物件,需要包含標頭檔案<functional>。