C++ Primer_顺序容器杂记

适配器是根据原始的容器类型所提供的操作,通过
定义新的操作接口,来适应基础的容器类型。顺序容器适配器包括 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 

容器里。



#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 }; 
 


#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 
    容器重写上述程序。 



#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 
    类型。 


#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容器的内存分配策略: 



#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 对象。


#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 函数。 


#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 中有多少个单词,并指出其中
    最长和最短的单词。如果有多个最长或最短的单词,则
    将它们全部输出。 


#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");  


#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 容器上实现。在创建适配器时,通过将一个顺序容器指定为适配器的
第二个类型实参,可覆盖其关联的基础容器类型: 


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值