程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ Primer_順序容器雜記

C++ Primer_順序容器雜記

編輯:C++入門知識

適配器是根據原始的容器類型所提供的操作,通過
定義新的操作接口,來適應基礎的容器類型。順序容器適配器包括 stack、
queue 和 priority_queue 類型


順序容器    
list  支持快速插入/刪除
deque  雙端隊列
順序容器適配器
stack  後進先出(LIFO)堆棧
queue  先進先出(FIFO)隊列
priority_queue 有優先級管理的隊列


在大多數的程序中,使用默認構造函數能達到最佳
運行時性能,並且使容器更容易使用。


容器構造函數


C<T> c;  創建一個名為 c 的空容器。C 是容器類型名,如 vector,T 是元素
類型,如 int 或 string 適用於所有容器。
C c(c2);  創建容器 c2 的副本 c;c 和 c2 必須具有相同的容器類型,並存放
相同類型的元素。適用於所有容器。
C c(b,e);
創建 c,其元素是迭代器 b 和 e 標示的范圍內元素的副本。適用於
所有容器。
C c(n,t);
用 n 個值為 t 的元素創建容器 c,其中值 t 必須是容器類型 C 的
元素類型的值,或者是可轉換為該類型的值。
只適用於順序容器
C c(n);  創建有 n 個值初始化(第 3.3.1 節)(value-initialized)元素
的容器 c。
只適用於順序容器


將一個容器復制給另一個容器時,類型必須匹配:容器類型和
元素類型都必須相同。


盡管不能直接將一種容器內的元素復制給另一種容器,但系統允許通過傳遞
一對迭代器(第 3.4 節)間接實現該實現該功能。使用迭代器時,不要求容器
類型相同。容器內的元素類型也可以不相同,只要它們相互兼容,能夠將要復制
的元素轉換為所構建的新容器的元素類型,即可實現復制。


C++ 語言中,大多數類型都可用作容器的元素類型。容器元素類型必須滿足
以下兩個約束:
1.   元素類型必須支持賦值運算。
2.   元素類型的對象必須可以復制。


IO 庫類型不支持復制或賦值。因此,不能創建存放 IO 類型對象的容器。


容器的容器


// note spacing: use ">>" not ">>" when specifying a container element type
 vector< vector<string> > lines; // vector of vectors
注意,在指定容器元素為容器類型時,必須如下使用空格:
     vector< vector<string> > lines; // ok: space required between close >
     vector< vector<string>> lines; // error: >> treated as shift operator
 
C++ 語言使用一對迭代器標記迭代器范圍(iterator range),這兩個迭代
器分別指向同一個容器中的兩個元素或超出末端的下一位置,通常將它們命名為
first 和 last,或 beg 和 end,用於標記容器中的一段元素范圍。
盡管 last 和 end 這兩個名字很常見,但是它們卻容易引起誤解。其實第
二個迭代器從來都不是指向元素范圍的最後一個元素,而是指向最後一個元素的
下一位置。該范圍內的元素包括迭代器 first 指向的元素,以及從 first 開始
一直到迭代器 last 指向的位置之前的所有元素。如果兩個迭代器相等,則迭代
器范圍為空。
此類元素范圍稱為左閉合區間(left-inclusive interval) ,其標准表示
方式為:
     // to be read as: includes first and each element up to but not
including last
     [ first, last )
 
表示范圍從 first 開始,到 last 結束,但不包括 last。迭代器 last 可
以等於 first,或者指向 first 標記的元素後面的某個元素,但絕對不能指向
first 標記的元素前面的元素。


使迭代器失效的容器操作


一些容器操作會修改容器的內在狀態或移動容
器內的元素。這樣的操作使所有指向被移動的元素的迭代器失效,也可能同時使
其他迭代器失效。使用無效迭代器是沒有定義的,可能會導致與懸垂指針相同的
問題。
例如,每種容器都定義了一個或多個 erase 函數。這些函數提供了刪除容
器元素的功能。任何指向已刪除元素的迭代器都具有無效值,畢竟,該迭代器指
向了容器中不再存在的元素。
 
使用迭代器編寫程序時,必須留意哪些操作會使迭代器失效。
使用無效迭代器將會導致嚴重的運行時錯誤。


c.rbegin()  返回一個逆序迭代器,它指向容器 c 的最後一個元素
c.rend()  返回一個逆序迭代器,它指向容器 c 的第一個元素前面的位置
 
所有順序容器都支持 push_back 操作


容器元素都是副本


在容器中添加元素時,系統是將元素值復制到容器裡。類似地,使用一
段元素初始化新容器時,新容器存放的是原始元素的副本。被復制的原
始值與新容器中的元素各不相關,此後,容器內元素值發生變化時,被
復制的原值不會受到影響,反之亦然。
 
添加元素可能會使迭代器失效


任何 insert 或 push 操作都可能導致迭代器失效。當編寫循
環將元素插入到 vector 或 deque 容器中時,程序必須確保迭
代器在每次循環後都得到更新。


避免存儲  end   操作返回的迭代器


在 vector 或 deque 容器中添加元素時,可能會導致某些或全部迭代器失
效。假設所有迭代器失效是最安全的做法。這個建議特別適用於由 end 操作返
回的迭代器。在容器的任何位置插入任何元素都會使該迭代器失效。


不要存儲 end 操作返回的迭代器。添加或刪除 deque 或
vector 容器內的元素都會導致存儲的迭代器失效。


Exercise
9.18:
編寫程序將 int 型的 list 容器的所有元素復制到兩個
deque 容器中。list 容器的元素如果為偶數,則復制到
一個 deque 容器中;如果為奇數,則復制到另一個 deque
容器裡。


view plain
#include<iostream> 
#include<list> 
#include<vector> 
#include<deque> 
using namespace std; 
 
void print(list<int>::iterator beg,list<int>::iterator end) 

     while(beg!=end) 
     { 
             cout<<*beg<<" "; 
             beg++;                
     }      
     cout<<endl; 

 
void print(deque<int>::iterator beg,deque<int>::iterator end) 

     while(beg!=end) 
     { 
             cout<<*beg<<" "; 
             beg++;                
     }      
     cout<<endl; 

 
int main() 

    list<int>lst;  
    deque<int>odd,even; 
    int range=20; 
    for(int i=0;i<range;i++) 
            lst.push_back(i); 
    print(lst.begin(),lst.end()); 
    list<int>::iterator itl=lst.begin(); 
    while(itl!=lst.end()) 
    { 
         if(*itl%2==0) 
                 even.push_back(*itl); 
         else 
                 odd.push_back(*itl);        
         itl++;                      
    } 
    print(odd.begin(),odd.end()); 
    print(even.begin(),even.end()); 
    system("pause"); 
    return 0; 

關系操作符


string 類型的關系運算


1.   如果兩個容器具有相同的長度而且所有元素都相等,那麼這兩個容器就相
等;否則,它們就不相等。
2.   如果兩個容器的長度不相同,但較短的容器中所有元素都等於較長容器中
對應的元素,則稱較短的容器小於另一個容器。
3.   如果兩個容器都不是對文的初始子序列,則它們的比較結果取決於所比較
的第一個不相等的元素。
 
所有容器都通過比較其元素對來實現關系運算


使用越界的下標,或調用空容器的 front 或 back 函數,都會
導致程序出現嚴重的錯誤。


使用下標運算的另一個可選方案是 at 成員函數 .這個函數的行
為和下標運算相似,但是如果給出的下標無效,at 函數將會拋出 out_of_range
異常


刪除順序容器內元素的操作


c.erase(p)  刪除迭代器 p 所指向的元素
            返回一個迭代器,它指向被刪除元素後面的元素。如果 p 指向
            容器內的最後一個元素,則返回的迭代器指向容器的超出末端
            的下一位置。如果 p 本身就是指向超出末端的下一位置的迭代
            器,則該函數未定義
c.erase(b,e)  刪除迭代器 b 和 e 所標記的范圍內所有的元素
            返回一個迭代器,它指向被刪除元素段後面的元素。如果 e 本
            身就是指向超出末端的下一位置的迭代器,則返回的迭代器也
            指向容器的超出末端的下一位置
c.clear()  刪除容器 c 內的所有元素。返回 void
c.pop_back()  刪除容器 c 的最後一個元素。返回 void。如果 c 為空容器,
            則該函數未定義
c.pop_front()  刪除容器 c 的第一個元素。返回 void。如果 c 為空容器,則
            該函數未定義
            只適用於 list 或 deque 容器


刪除第一個或最後一個元素


pop_front 和 pop_back 函數用於刪除容器內的第一個和最後一個元素。但
vector 容器類型不支持 pop_front 操作。這些操作刪除指定的元素並返回
void。


find 函數需要一對標記查找范圍的迭代器以
及一個在該范圍內查找的值作參數。查找完成後,該函數返回一個迭代器,它指
向具有指定值的第一個元素,或超出末端的下一位置。

 


Exercise
9.26:
假設有如下 ia 的定義,將 ia 復制到一個 vector 容器
和一個 list 容器中。使用單個迭代器參數版本的 erase
函數將 list 容器中的奇數值元素刪除掉,然後將
vector 容器中的偶數值元素刪除掉。
    int ia[] = { 0, 1, 1, 2, 3,  5, 8, 13, 21, 55,
89 };
 

view plain
#include<iostream> 
#include<list> 
#include<vector> 
#include<deque> 
using namespace std; 
 
void print(list<int>::iterator beg,list<int>::iterator end) 

     while(beg!=end) 
     { 
             cout<<*beg<<" "; 
             beg++;                
     }      
     cout<<endl; 

 
void print(vector<int>::iterator beg,vector<int>::iterator end) 

     while(beg!=end) 
     { 
             cout<<*beg<<" "; 
             beg++;                
     }      
     cout<<endl; 

 
void deleteelem(list<int>&lst,int flag)  

     int base=(flag%2==0?0:1); 
     list<int>::iterator head=lst.begin(),tail=lst.end(); 
     while(head!=tail) 
     //這裡不用更新指向容器尾端的迭代器 
     //因為list容器刪除元素後沒有出現元素的移動  
     { 
               if(*head%2==base) 
                      head=lst.erase(head); 
               //巧妙利用函數返回值                  
               else 
                      head++; 
     } 

 
void deleteelem(vector<int>&vec,int flag)  

     int base=(flag%2==0?0:1); 
     vector<int>::iterator head=vec.begin(),tail=vec.end(); 
     while(head!=(tail=vec.end())) 
     //這裡要更新一下指向容器尾端的迭代器 
     //因為vector容器刪除元素後元素要順序前移是迭代器失效  
     { 
               if(*head%2==base) 
                      head=vec.erase(head);                  
               else 
                      head++; 
     } 

 
int main() 

    int ia[10]={0,1,2,3,4,5,6,7,8,9}; 
    list<int>odd(ia,ia+10);  
    vector<int>even(ia,ia+10); 
    print(odd.begin(),odd.end()); 
    print(even.begin(),even.end()); 
    deleteelem(odd,2); 
    print(odd.begin(),odd.end()); 
    deleteelem(even,1); 
    print(even.begin(),even.end()); 
    system("pause"); 
    return 0; 


Exercise
9.27:
    編寫程序處理一個 string 類型的 list 容器。在該容器
    中尋找一個特殊值,如果找到,則將它刪除掉。用 deque
    容器重寫上述程序。


view plain
#include<iostream> 
#include<list> 
#include<string> 
#include<deque> 
using namespace std; 
 
void Print(list<string>::iterator beg,list<string>::iterator end) 

        while(beg!=end) 
            cout<<*beg++<<" ";                
        cout<<endl;       

 
void Print(deque<string>::iterator beg,deque<string>::iterator end) 

        while(beg!=end) 
            cout<<*beg++<<" ";                
        cout<<endl;       

 
void Delete(list<string>&lst,string str) 

     list<string>::iterator beg=lst.begin(); 
     while(beg!=lst.end()) 
     { 
             if(*beg==str) 
                   beg=lst.erase(beg); 
             else 
                   beg++;                        
     } 

 
void Delete(deque<string>&dq,string str) 

     deque<string>::iterator beg=dq.begin(); 
     while(beg!=dq.end()) 
     { 
             if(*beg==str) 
                   beg=dq.erase(beg); 
             else 
                   beg++;                        
     } 

 
int main() 

        string str[10]={"you","will","when","pray","believe","many","we","pray","with","no"}; 
        list<string>lst(str,str+10); 
        deque<string>dq(str,str+10); 
        Print(lst.begin(),lst.end()); 
        Print(dq.begin(),dq.end()); 
        string delstr="pray"; 
        Delete(lst,delstr); 
        Print(lst.begin(),lst.end()); 
        Delete(dq,delstr); 
        Print(dq.begin(),dq.end()); 
        system("pause");         


賦值與  swap


賦值操作符首先 erases 其左操作
數容器中的所有元素,然後將右操作數容器的所有元素 inserts 到左邊容器中


賦值和 assign 操作使左操作數容器的所有迭代器失效。swap
操作則不會使迭代器失效。完成 swap 操作後,盡管被交換的
元素已經存放在另一容器中,但迭代器仍然指向相同的元素。


assign 操作首先刪除容器中所有的元素,然後將其參數所指定的新元素插
入到該容器中。與復制容器元素的構造函數一樣,如果兩個容器類型相同,其元
素類型也相同,就可以使用賦值操作符(=)將一個容器賦值給另一個容器。如
果在不同(或相同)類型的容器內,元素類型不相同但是相互兼容,則其賦值運
算必須使用 assign 函數。例如,可通過 assign 操作實現將 vector 容器中一
段 char* 類型的元素賦給 string 類型 list 容器。


由於 assign 操作首先刪除容器中原來存儲的所有元素,因此,
傳遞給 assign 函數的迭代器不能指向調用該函數的容器內的
元素。


使用  swap  操作以節省刪除元素的成本


swap 操作實現交換兩個容器內所有元素的功能。要交換的容器的類型必須
匹配:操作數必須是相同類型的容器,而且所存儲的元素類型也必須相同。調用
了 swap 函數後,右操作數原來存儲的元素被存放在左操作數中,反之亦然。
     vector<string> svec1(10); // vector with 10 elements
     vector<string> svec2(24); // vector with 24 elements
     svec1.swap(svec2);
 
關於 swap 的一個重要問題在於:該操作不會刪除或插入任何
元素,而且保證在常量時間內實現交換。由於容器內沒有移動
任何元素,因此迭代器不會失效。
 
執行 swap 後,容器 svec1 中存儲 24 個 string 類型的元素,而 svec2 則存
儲 10 個元素。


沒有移動元素這個事實意味著迭代器不會失效。它們指向同一元素,就像沒
作 swap 運算之前一樣。雖然,在 swap 運算後,這些元素已經被存儲在不同的
容器之中了。例如,在做 swap 運算之前,有一個迭代器 iter 指向 svec1[3] 字
符串;實現 swap 運算後,該迭代器則指向 svec2[3] 字符串(這是同一個字符
串,只是存儲在不同的容器之中而已)。


Exercise
9.28:
    編寫程序將一個 list 容器的所有元素賦值給一個
    vector 容器,其中 list 容器中存儲的是指向 C 風格字
    符串的 char* 指針,而 vector 容器的元素則是 string
    類型。

view plain
#include<iostream> 
#include<list> 
#include<vector> 
#include<string> 
using namespace std; 
 
void print(list<string>::iterator beg,list<string>::iterator end) 

     cout<<"Print List String Called"<<endl; 
     while(beg!=end) 
     { 
             cout<<*beg<<" "; 
             beg++;                
     }      
     cout<<endl; 

 
void print(vector<const char *>::iterator beg,vector<const char *>::iterator end) 

     cout<<"Print Vector Const Char * Called"<<endl; 
     while(beg!=end) 
     { 
             cout<<*beg<<" "; 
             beg++;                
     }      
     cout<<endl; 

 
int main() 

    string str1[2]={"Hello","Ubuntu!"}; 
    const char* str2[3]={"I","Love","C++"}; 
    list<string>lst1(str1,str1+2),lst2(str2,str2+3); 
    vector<const char *>vec(str2,str2+3); 
    print(lst1.begin(),lst1.end()); 
    print(lst2.begin(),lst2.end()); 
    print(vec.begin(),vec.end()); 
    //assign test 
    cout<<"assign test"<<endl; 
    lst1.assign(vec.begin(),vec.end()); 
    print(lst1.begin(),lst1.end()); 
    print(vec.begin(),vec.end()); 
    //swap test 
    cout<<"swap test"<<endl; 
    lst1.swap(lst2); 
    print(lst1.begin(),lst1.end()); 
    print(lst2.begin(),lst2.end()); 
    system("pause"); 
    return 0; 


vector 容器的自增長
 
vector 容器的元素以連續的方式存放——每一個元素都緊挨著前一個元素存儲。


在 list 容器中添加一個元素,標准庫只需創建一個新元素,然後將該新元素
連接在已存在的鏈表中,不需要重新分配存儲空間,也不必復制任何已存在的元素。


由此可以推論:一般而言,使用 list 容器優於 vector 容器。但是,通常
出現的反而是以下情況:對於大部分應用,使用 vector 容器是最好的。原因在
於,標准庫的實現者使用這樣內存分配策略:以最小的代價連續存儲元素。由此
而帶來的訪問元素的便利彌補了其存儲代價。


為了使 vector 容器實現快速的內存分配,其實際分配的容量要比當前所需
的空間多一些。vector 容器預留了這些額外的存儲區,用於存放新添加的元素。
於是,不必為每個新元素重新分配容器。所分配的額外內存容量的確切數目因庫
的實現不同而不同。比起每添加一個新元素就必須重新分配一次容器,這個分配
策略帶來顯著的效率。事實上,其性能非常好,因此在實際應用中,比起 list 和
deque 容器,vector 的增長效率通常會更高。


capacity  和  reserve   成員


vector 類提供了兩個成員函數:capacity 和
reserve 使程序員可與 vector 容器內存分配的實現部分交互工作。capacity
操作獲取在容器需要分配更多的存儲空間之前能夠存儲的元素總數,而 reserve
操作則告訴 vector 容器應該預留多少個元素的存儲空間。


弄清楚容器的 capacity(容量)與 size(長度)的區別非常
重要。size 指容器當前擁有的元素個數;而 capacity 則指容
器在必須分配新存儲空間之前可以存儲的元素總數。


編寫程序研究vector容器的內存分配策略:


view plain
#include<iostream> 
#include<vector> 
using namespace std; 
 
void print(vector<int>::iterator beg,vector<int>::iterator end) 

     if(beg==end) 
        cout<<"Nothing to display !"<<endl; 
     else 
     { 
         while(beg!=end) 
            cout<<*beg++<<" "; 
         cout<<endl; 
     }       

 
int main() 

    vector<int>v; 
    print(v.begin(),v.end()); 
    cout<<"size :"<<v.size()<<"   "<<"capicity :"<<v.capacity()<<endl; 
    for(int i=1;i<=11;i++) 
    { 
            v.push_back(i); 
            print(v.begin(),v.end()); 
            cout<<"size :"<<v.size()<<"   "<<"capicity :"<<v.capacity()<<endl;    
    } 
    v.reserve(20); 
    cout<<"size :"<<20<<"   "<<"capicity :"<<v.capacity()<<endl; 
    v.reserve(50); 
    cout<<"size :"<<50<<"   "<<"capicity :"<<v.capacity()<<endl; 
    v.reserve(100); 
    cout<<"size :"<<100<<"   "<<"capicity :"<<v.capacity()<<endl; 
    system("pause"); 


容器的選用


元素是否連續存儲還會顯著地影響:
1.   在容器的中間位置添加或刪除元素的代價。
2.   執行容器元素的隨機訪問的代價。


程序使用這些操作的程序將決定應該選擇哪種類型的容器。vector 和 deque
容器提供了對元素的快速隨機訪問,但付出的代價是,在容器的任意位置插入或
刪除元素,比在容器尾部插入和刪除的開銷更大。list 類型在任何位置都能快
速插入和刪除,但付出的代價是元素的隨機訪問開銷較大。


插入操作如何影響容器的選擇


list 容器不支持隨機訪問,訪問某個元素要求遍歷涉及的其他元素。


deque 容器擁有更加復雜的數據結構。從 deque 隊列的兩端插入和刪除元素
都非常快。在容器中間插入或刪除付出的代價將更高。


通常來說,除非找到選擇使用其他容器的更好理由,否則
vector 容器都是最佳選擇。


如果無法確定某種應用應該采用哪種容器,則編寫代碼時嘗試
只使用 vector 和 lists 容器都提供的操作:使用迭代器,而
不是下標,並且避免隨機訪問元素。這樣編寫,在必要時,可
很方便地將程序從使用 vector 容器修改為使用 list 的容
器。


string類型不支持以棧方式操縱容器:在 string 類型中不能使用 front、back 和 pop_back 操作


 Exercise
9.34: 
使用迭代器將 string 對象中的字符都改為大寫字母。
Exercise
9.35: 
使用迭代器尋找和刪除 string 對象中所有的大寫字
符。
Exercise
9.36: 
編寫程序用 vector<char> 容器初始化 string 對象。

view plain
#include<iostream> 
#include<vector> 
#include<string> 
#include<cctype> 
using namespace std; 
 
int main() 

        //使用迭代器將 string 對象中的字符都改為大寫字母 
        string str("Hello Ubuntu !"); 
        cout<<str<<endl; 
        string::iterator it=str.begin(); 
        while(it!=str.end()) 
        { 
               if(islower(*it))  
                   *it=toupper(*it); 
               it++;                   
        } 
        cout<<str<<endl; 
        //使用迭代器尋找和刪除 string 對象中所有的大寫字 
        str="Hello Ubuntu !"; 
        cout<<str<<endl; 
       it=str.begin(); 
        while(it!=str.end()) 
        { 
               if(isupper(*it))  
                   it=str.erase(it); 
               else  
                   it++;                 
        } 
        cout<<str<<endl; 
        //編寫程序用 vector<char> 容器初始化 string 對象。 
        string str1("Hello Ubuntu !"); 
        vector<char>vec(str1.begin(),str1.end()); 
        string str2(vec.begin(),vec.end()); 
        cout<<str2<<endl; 
        system("pause"); 

Exercise
9.38: 
    已知有如下 string 對象:
         "ab2c3d7R4E6"
    
    編寫程序尋找該字符串中所有的數字字符,然後再尋找
    所有的字母字符。以兩種版本編寫該程序:第一個版本
    使用 find_first_of 函數,而第二個版本則使用
    find_first_not_of 函數。

view plain
#include<iostream> 
#include<string> 
using namespace std; 
int main() 

    string str("ab2c3d7R4E6"); 
    string numerics("1234567890"); 
    string alpha("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); 
    //find_first_of 
    //number 
    string::size_type pos=0;    
    while((pos=str.find_first_of(numerics,pos))!=string::npos) 
    { 
                cout<<str[pos]; 
                pos++;                                         
    }  
    cout<<endl; 
    //letter 
    pos=0; 
    while((pos=str.find_first_of(alpha,pos))!=string::npos) 
    { 
                cout<<str[pos]; 
                pos++;                                         
    }  
    cout<<endl; 
    //find_first_not_of 
    //number 
    pos=0;    
    while((pos=str.find_first_not_of(numerics,pos))!=string::npos) 
    { 
                cout<<str[pos]; 
                pos++;                                         
    }  
    cout<<endl; 
    //letter 
    pos=0; 
    while((pos=str.find_first_not_of(alpha,pos))!=string::npos) 
    { 
                cout<<str[pos]; 
                pos++;                                         
    }  
    cout<<endl; 
    system("pause"); 

 Exercise
9.39: 
    已知有如下 string 對象:
         string line1 = "We were her pride of 10 she
    named us:";
         string line2 = "Benjamin, Phoenix, the
    Prodigal"
         string line3 = "and perspicacious pacific
    Suzanne";
    
         string sentence = line1 + ' ' + line2 + ' ' +
    line3;
    
    編寫程序計算 sentence 中有多少個單詞,並指出其中
    最長和最短的單詞。如果有多個最長或最短的單詞,則
    將它們全部輸出。

view plain
#include<iostream> 
#include<string> 
#include<vector> 
using namespace std; 
 
int main() 

    string line1 = "We were her pride of 10 she named us:";  
    string line2 = "Benjamin, Phoenix, the Prodigal" ; 
    string line3 = "and perspicacious pacific Suzanne";  
    string sentence = line1 + ' ' + line2 + ' ' + line3;   
    string separators(" \t\v\r\f,:"); 
    cout<<sentence<<endl; 
    sentence+=" ";//添加結束標志  
    string::size_type word(0),slen(sentence.size()),llen(0),pos(0),end; 
    vector<string>lstr,sstr;//容器  
    //從頭到尾遍歷  
    for(end=sentence.find_first_of(separators,pos) ; pos!=string::npos ; pos=sentence.find_first_not_of(separators,end),end=sentence.find_first_of(separators,pos)) 
    { 
                word++; 
                if(end-pos>llen)//發現更長的  
                { 
                       llen=end-pos; 
                       lstr.clear();//清空原容器  
                }    
                if(end-pos<slen) 
                { 
                       slen=end-pos; 
                       sstr.clear(); 
                } 
                if(end-pos==llen)//長度符合  
                { 
                       lstr.push_back(string(sentence.begin()+pos,sentence.begin()+end));//進入容器  
                }    
                if(end-pos==slen) 
                { 
                       sstr.push_back(string(sentence.begin()+pos,sentence.begin()+end)); 
                }                                                                                          
    } 
    cout<<"There are "<<word<<" words in this sentense."<<endl; 
    vector<string>::iterator it=lstr.begin(); 
    cout<<"There are "<<lstr.size()<<" longest words which the length is "<<llen<<endl; 
    while(it!=lstr.end()) 
        cout<<*it++<<" "; 
    cout<<endl; 
    it=sstr.begin(); 
    cout<<"There are "<<sstr.size()<<" longest words which the length is "<<slen<<endl; 
    while(it!=sstr.end()) 
        cout<<*it++<<" "; 
    cout<<endl; 
    cin.get();   

 

9.40用
     string q1("when lilacs last in the dooryard bloom 'd'");
     string q2("The child is the father of the man");
     創建
     string sentence("The child is in the dooryard"); 

view plain
#include<iostream> 
#include<string> 
using namespace std; 
 
int main() 

     string q1("when lilacs last in the dooryard bloom 'd'"); 
     string q2("The child is the father of the man"); 
     string sentence; 
     sentence.assign(q2,q2.find("The child is "),string("The child is ").size()); 
    // sentence.append(string("").assign(q1,q1.find("in the dooryard"),string("in the dooryard").size())); 
     sentence.append(q1.substr(q1.find("in the dooryard"),string("in the dooryard").size())); 
     cout<<sentence<<endl; 
     cin.get();   


 容器適配器


除了順序容器,標准庫還提供了三種順序容器適配器:queue、
priority_queue 和 stack。適配器(adaptor)是標准庫中通用的概念,包括容
器適配器、迭代器適配器和函數適配器。本質上,適配器是使一事物的行為類似
於另一事物的行為的一種機制。容器適配器讓一種已存在的容器類型采用另一種
不同的抽象類型的工作方式實現。例如,stack(棧)適配器可使任何一種順序
容器以棧的方式工作。表 9.22 列出了所有容器適配器通用的操作和類型。


size_type               一種類型,足以存儲此適配器類型最大對象的長度
value_type              元素類型
container_type          基礎容器的類型,適配器在此容器類型上實現
A a;                    創建一個新空適配器,命名為 a
A a(c);                 創建一個名為 a 的新適配器,初始化為容器 c 的副本
關系操作符              所有適配器都支持全部關系操作符:==、 !=、 <、 <=、 >、>=
 
覆蓋基礎容器類型


     默認的 stack 和 queue 都基於 deque 容器實現,而 priority_queue 則
在 vector 容器上實現。在創建適配器時,通過將一個順序容器指定為適配器的
第二個類型實參,可覆蓋其關聯的基礎容器類型:

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