程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ STL原來可以這麼強大

C++ STL原來可以這麼強大

編輯:C++入門知識

今天在做C++ Primer第14章習題14.37的時候用到了一些STL的函數,徹底顛覆了我對C++的看法。以前總覺得C++很麻煩,實現一個功能總要寫一堆的代碼,很繁瑣,那是菜鳥時候的想法。雖然現在也還是菜鳥,但級別比原來提高了一點,從今天使用了STL的算法之後才知道,原來C++也可以這麼簡潔。

        從習題一步步擴展開來講吧,習題如下:

習題14.37    使用標准庫函數對象和函數適配器,定義一個對象用於:

        (a)查找大於1024的所有值

        (b)查找不大於pooth的所有字符串

        (c)將所有值乘以2

        做這題之前先簡單介紹一下C++的函數對象和標准庫提供的函數適配器。

        C++中函數對象是為實現某種操作而重載調用操作符的類,即重載其operator()操作符函數,必須聲明為成員函數。函數對象經常用作通用算法的實參。標准庫定義了很多函數對象供程序員使用,在functional頭文件裡面定義,包含算數函數對象類型、關系函數對象類型和邏輯函數對象類型,這些函數對象有的是一元函數對象,有的是二元函數對象,一元函數對象接受一個實參,二元函數對象接受兩個實參。

        STL中提供了很多標准庫算法,一般的標准庫算法都使用內置的操作,比如<、==等,如果要使用自定義的操作,可以傳函數指針,但對函數指針的形參個數有限制,用起來不是很方便。這時候函數對象就可以發揮作用了,可以把多余的參數作為函數對象的內部成員,通過初始化的時候把值傳遞給函數對象,通過調用函數對象的調用操作符實現比較的目的。

        C++提供了函數適配器來擴展函數對象的使用。因為二元函數對象要傳遞兩個值,如果其中有一個值是已知或者默認的,這時候可以把他初始化,這個功能由綁定器來提供,bind1st用來綁定二元函數對象的第一個實參,bind2nd用於綁定二元函數對象的第二個實參。另外一個適配器是求反器,用於對謂詞函數對象的真值求反,not1對一元函數對象求反,not2對二元函數求反。

        簡單介紹完基礎之後再回來解這習題,來看看STL是怎麼讓程序變得簡潔的。

        對於(a)可以用bind2nd函數適配器和greater<int>函數對象來實現,如下所示:


[cpp]
// Find the value greater than 1024 with standard function objects and function adaptor 
int nVal[] = {43, 53, 536, 4976, 5307, 32, 536, 957}; 
size_t size = sizeof(nVal) / sizeof(int); 
 
cout << "The original value: " << endl; 
for (size_t i = 0; i != size; ++i) 
    cout << nVal[i] << " "; 
cout << endl; 
     
int *nFind = nVal; 
int toCompare = 1024; 
 
cout << "The value that greater than " << toCompare << " : " << endl; 
while ((nFind = find_if(nFind, nVal + size, bind2nd(greater<int>(), toCompare))) != nVal + size) 

    cout << *nFind << " "; 
    ++nFind; 

cout << endl << endl; 
        對於(b)可以用bind2nd函數適配器和not_equal_to<string>函數對象來實現,如下所示:

[cpp]
// Find string not equal with "pooth" 
const int ARYSIZE = 5; 
string sAry[ARYSIZE] = {"abc", "adu", "butterfly", "pooth", "nancy"}; 
vector<string> sVec(sAry, sAry + ARYSIZE); 
 
vector<string>::iterator sIter = sVec.begin(); 
cout << "The original string: " << endl; 
while (sIter != sVec.end()) 

    cout << *sIter << " "; 
    ++sIter; 

cout << endl; 
 
cout << "The string that not euqal with \"pooth\" : " << endl; 
sIter = sVec.begin(); 
string sToCompare = "pooth"; 
while ((sIter = find_if(sIter, sVec.end(), bind2nd(not_equal_to<string>(), sToCompare))) != sVec.end()) 

    cout << *sIter << " "; 
    ++sIter; 

cout << endl << endl; 
        對於(c)可以用bind2nd函數適配器、transform和multiplies<int>來實現,如下所示:

[cpp]
class PrintVal 

public: 
        PrintVal() { } 
        void operator()(int &val) const { cout << val << " "; } 
}; 
 
// Multiply all the value by 2 
vector<int> nVec(nVal, nVal + size); 
cout << "The original val: " << endl; 
for_each(nVec.begin(), nVec.end(), PrintVal()); 
cout << endl; 
transform(nVec.begin(), nVec.end(), nVec.begin(), bind2nd(multiplies<int>(), 2)); 
cout << "After multiply by 2: " << endl; 
for_each(nVec.begin(), nVec.end(), PrintVal()); 
cout << endl; 
        從上面是不是可以看到,從(a)(b)到(c)是不是代碼簡潔了很多,通過引入PrintVal函數對象和for_each的使用,大大減少了代碼量,使程序看起來簡潔易懂。

         整個習題的代碼如下所示:


[cpp]
#include <iostream> 
#include <functional> 
#include <algorithm> 
#include <vector> 
#include <string> 
using namespace std; 
 
class PrintVal 

public: 
    PrintVal() { } 
    void operator()(int &val) const { cout << val << " "; } 
}; 
 
int main() 

    // Find the value greater than 1024 with standard function objects and function adaptor 
    int nVal[] = {43, 53, 536, 4976, 5307, 32, 536, 957}; 
    size_t size = sizeof(nVal) / sizeof(int); 
     
    cout << "The original value: " << endl; 
    for (size_t i = 0; i != size; ++i) 
        cout << nVal[i] << " "; 
    cout << endl; 
         
    int *nFind = nVal; 
    int toCompare = 1024; 
 
    cout << "The value that greater than " << toCompare << " : " << endl; 
    while ((nFind = find_if(nFind, nVal + size, bind2nd(greater<int>(), toCompare))) != nVal + size) 
    { 
        cout << *nFind << " "; 
        ++nFind; 
    } 
    cout << endl << endl; 
 
 
    // Find string not equal with "pooth" 
    const int ARYSIZE = 5; 
    string sAry[ARYSIZE] = {"abc", "adu", "butterfly", "pooth", "nancy"}; 
    vector<string> sVec(sAry, sAry + ARYSIZE); 
 
    vector<string>::iterator sIter = sVec.begin(); 
    cout << "The original string: " << endl; 
    while (sIter != sVec.end()) 
    { 
        cout << *sIter << " "; 
        ++sIter; 
    } 
    cout << endl; 
 
    cout << "The string that not euqal with \"pooth\" : " << endl; 
    sIter = sVec.begin(); 
    string sToCompare = "pooth"; 
    while ((sIter = find_if(sIter, sVec.end(), bind2nd(not_equal_to<string>(), sToCompare))) != sVec.end()) 
    { 
        cout << *sIter << " "; 
        ++sIter; 
    } 
    cout << endl << endl; 
 
 
    // Multiply all the value by 2 
    vector<int> nVec(nVal, nVal + size); 
    cout << "The original val: " << endl; 
    for_each(nVec.begin(), nVec.end(), PrintVal()); 
    cout << endl; 
    transform(nVec.begin(), nVec.end(), nVec.begin(), bind2nd(multiplies<int>(), 2)); 
    cout << "After multiply by 2: " << endl; 
    for_each(nVec.begin(), nVec.end(), PrintVal()); 
    cout << endl; 
    return 0; 
}   


摘自  huagong_adu 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved