《STL》— STL详解

xiaoxiao2021-02-28  159

 

STL学习系列——标准模板库STL介绍

 

       库是一系列程序组件的集合,他们可以在不同的程序中重复使用。C++语言按照传统的习惯,提供了由各种各样的函数组成的库,用于完成诸如输入/输出、数学计算等功能。

1. STL介绍

标准模板库STL是当今每个从事C++编程的人需要掌握的技术,所有很有必要总结下

本文将介绍STL并探讨它的三个主要概念:容器、迭代器、算法。

STL的最大特点就是:

数据结构和算法的分离,非面向对象本质。访问对象是通过象指针一样的迭代器实现的;

容器是象链表,矢量之类的数据结构,并按模板方式提供;

算法是函数模板,用于操作容器中的数据。由于STL以模板为基础,所以能用于任何数据类型和结构。

容器可以分为三种主要类型:序列容器、关联容器、容器适配器。

每种STL容器都具有相关联的成员函数,这些成员函数的一个子集在所有的STL容器中都定义了。

STL迭代器的属性和指针类似,程序可以利用迭代器操作STL容器中的元素

STL算法是用于执行常见数据操作的函数,这些操作包括搜索、排序和比较元素,STL提供了大约70种算法,其中大多数算法都使用迭代器来访问容器元素。

1.1   容器简介

 容器可以分为三种:序列容器、关联容器、容器适配器。

序列容器:vector deque list

Vector:可从后端执行快速的插入和删除,直接访问任何元素

Deque:从前面或后面执行快速的插入和删除,直接访问任何元素

List:双链表,能在任何地方执行快速的插入和删除

关联容器:set multiset map multimap

Set:执行快速搜索,元素不允许重复

Multiset:执行快速搜索,元素允许重复

Map:一对一映射,元素不允许重复,快速的基于键的搜索

Multimap:一对多映射,元素允许重复,快速的基于键的搜索

容器适配器:stack queue priority_queue

Stack:后进先出

Queue:先进先出

priority_queue:优先级最高的元素总是最先出队

序列容器表示线性数据结构,例如向量和链表;

关联容器是非线性容器,通常能够快速找出保存在容器中的元素。这类容器能够保存值的集合或键/值对;序列容器和关联容器统称为第一类容器。

STL将堆栈和队列实现为容器适配器,使程序以一种受约束的方式看待序列容器。

STL通常可通过模板实现泛型编程,以避免继承和虚函数,获得更好的执行时性能。

1.2   迭代器简介

迭代器在许多方面和指针相同,用于指向第一类容器的元素。

迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器不仅仅是指针,因此你不能认为他们一定具有地址值。例如,一个数组索引,也可以认为是一种迭代器。

迭代器有各种不同的创建方法。程序可能把迭代器作为一个变量创建。一个STL容器类可能为了使用一个特定类型的数据而创建一个迭代器。作为指针,必须能够使用*操作符类获取数据。你还可以使用其他数学操作符如++。典型的,++操作符用来递增迭代器,以访问容器中的下一个对象。如果迭代器到达了容器中的最后一个元素的后面,则迭代器变成past-the-end值。使用一个past-the-end值得指针来访问对象是非法的,就好像使用NULL或为初始化的指针一样。

废话不多说,直接上demo

[cpp] view plaincopy

//利用istream_iterator进行输入,利用ostream_iterator进行输出  //下面程序演示了使用istream_iterator从标准输入进行输入,以及使用ostream_iterator输出到标准输出  #include "stdafx.h"  #include <iostream>  using namespace std;    #include <iterator>    int _tmain(int argc, _TCHAR* argv[])  {   cout<<"输入2个整数:"<<endl;   //下行创建了一个istream_iterator,它能够以一种类型安全的方式从标准输入对象cin提取int值   std::istream_iterator<int> inputInt(cin);     //下行对迭代器inputInt解除引用,并从cin中读出一个整数,然后将它赋予number1   int number1=*inputInt;   ++inputInt;                    //将迭代器inputInt定位到输出流中的下一个值   int number2=*inputInt;         //从inputInt输入下一个整数,并将它赋予number2     //下行创建了一个ostream_iterator,它能够在标准输出对象cout中出入int值   std::ostream_iterator<int> outputInt(cout);   cout<<"和是:"<<endl;   *outputInt=number1+number2; //将number1和number2的和赋予*outputInt   cout<<endl;   system("pause");   return 0;  }  

1.3   算法简介

STL算法能用于各种容器。STL提供的许多算法,大量用于操作容器,插入、删除、搜索、排序以及其他算法,都适合于部分或者所有的STL容器。

STL的实现非常简单。到目前为止,类的设计者都将算法作为容器的成员函数,使算法和容器相关联。STL采用不同的方法,STL的算法和容器是分离的,它只是间接地通过迭代器操作容器的元素。

STL算法能够用于STL容器以及基于指针的、C风格的数组。

STL:STL各种容器的使用时机详解

 

C++标准程序库提供了各具特长的不同容器。现在的问题是:该如何选择最佳的容器类别?下表给出了概述。

但是其中有些描述可能不一定实际。例如:如果你需呀处理的元素数量很少,可以虎落复杂度,因为线性算法通常对元素本身的处理过程比较快,这种情况下,“显性复杂度搭配快速的元素处理”要比“对数复杂度搭配慢的元素处理”来得划算。

    作为对上表的补充,使用时:

    1.缺省情况下应该使用vector。vector的内部结构最简单,并允许随机存取,所以数据的存取十分方便灵活,数据的处理也够快。

    2.如果经常要在序列头部和尾部安插和移除元素,应该采用deque。如果你希望元素被移除时,容器能够自动缩减内存,那么你也应该采用deque。此外,由于vector通常才有用一个内存区块来存放元素,而deque采用多个区块,所以后者可内含更多元素。

   3.如果需要经常在容器的中段执行元素的安插、移除和移动,可考虑使用list。list提供特殊的成员函数,可以在常数时间内将元素从A容器转移到B容器。但由于list不支持随机存取,所以如果只要知道list的头部却要造访list中的元素,性能会大打折扣。

     和所有“以节点为基础”的容器相似,只要元素还是容器的已不复,list就不会令指向那些元素的迭代器失效。vector则不然,一旦超过其容量,它的所有iterators,pointers.references都会失效;执行安插或移除操作时,也会令一部分iterators、pointers、references失效。至于deque,当它的大小改变,所有iterators,pointers,references都会失效。

    4.如果你要的容器是这种性质:每次操作若不成功,便无效用,那么你应该选用list,或是采用关联式容器。

    5.如果你经常需要根据某个准则来搜寻元素,那么应当使用“以该排序准则对元素进行排序”的set或multiset。记住,理论上,面对1000个元素的排序,对数复杂度比线性复杂度好10倍。就搜寻速度而言,hash table通常比二叉树还要快5-10倍。但是hash table的元素并未排序,所以如果元素必须排序,它就用不上了。

    6.如果想处理key/value pair,请采用map或multimap。

    7.如果需要关联式数组,应采用map。

    8.如果需要字典结构,应采用multimap。 

                                     二、STL:map/multimap用法详解

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

          使用map/multimap之前要加入头文件#include<map>,map和multimap将key/value当作元素,进行管理。它们可根据key的排序准则自动将元素排序。multimap允许重复元素,map不允许重复元素。

          map和multimap内部的数据结构也是平衡二叉树。

          map和multimap根据元素的key自动对元素进行排序,要修改元素的key必须先删除拥有该key的元素,然后插入拥有新的key/value的元素。

常用函数

1.构造函数和析构函数    

map m:创建空映射,不包含任何元素

map m(op):以op为排序准则,产生一个空的map

map m1(m2):复制c2中的元素到c1中

map m(const value_type *first, const value_type* last):复制[first, last)之间元素构成新映射

map m(const value_type *first, const value_type* last,op):以op为排序准则,复制[first, last)之间元素构成新映射。

m.~set()销毁所有元素,释放内存

 

multimap mm:创建空映射,不包含任何元素

multimap mm(op):以op为排序准则,产生一个空的multimap

multimap m1(m2):复制m2中的元素到m1中

multimap m(const value_type *first, const value_type* last):复制[first, last)之间元素构成新映射

multimap m(const value_type *first, const value_type* last,op):以op为排序准则,复制[first, last)之间元素构成新映射

m.~multimap()销毁所有元素,释放内存

 

[cpp] view plaincopy

#include "stdafx.h"  #include <iostream>  #include <map>    using namespace std;    bool fncomp (char lhs, char rhs) {return lhs<rhs;}    struct classcomp {      bool operator() (const char& lhs, const char& rhs) const      {return lhs<rhs;}  };    int main ()  {      map<char,int> first;        first['a']=10;      first['b']=30;      first['c']=50;      first['d']=70;        map<char,int> second (first.begin(),first.end());        map<char,int> third (second);        map<char,int,classcomp> fourth;                 // class as Compare        bool(*fn_pt)(char,char) = fncomp;      map<char,int,bool(*)(char,char)> fifth (fn_pt); // function pointer as Compare        return 0;  }  

 

2.大小、判断空函数

    int size() const:返回容器元素个数     bool empty() const:判断容器是否空,若返回true,表明容器已空。

3.增加删除函数

    iterator insert(const value_type& x):插入元素x

    iterator insert(iterator it,const value_type& x):在迭代指针it处插入元素x     void insert(const value_type *first,const value_type* last):插入[first, last)之间元素

    iterator erase(iterator it):删除迭代指针it处元素

    iterator erase(iterator first,iterator last):删除[first, last)之间元素

    size_type erase(const Key& key):删除键值等于key的元素

 

[cpp] view plaincopy

#include "stdafx.h"  #include <iostream>  #include <map>    using namespace std;      int main ()  {      map<char,int> mymap;        mymap.insert(pair<char,int>('a',10));      mymap.insert(pair<char,int>('z',200));        pair<map<char,int>::iterator,bool> ret;      ret = mymap.insert(pair<char,int>('z',500));      if (ret.second == false)      {          cout<<"element 'z' already existed";          cout<<"with a value of "<<ret.first->second<<'\n';      }        map<char,int>::iterator it = mymap.begin();      mymap.insert(it,pair<char,int>('b',300));      mymap.insert(it,pair<char,int>('c',400));        map<char,int> anothermap;      anothermap.insert(mymap.begin(),mymap.find('c'));        cout<<"mymap contains :\n";      for (it = mymap.begin();it!= mymap.end();it++)      {          cout<<it->first<<"=>"<<it->second<<'\n';      }        cout<<"anothermap contains :\n";      for (it = anothermap.begin();it!= anothermap.end();it++)      {          cout<<it->first<<"=>"<<it->second<<'\n';      }      return 0;  }  

上述代码运行结果为

 

 

[cpp] view plaincopy

#include "stdafx.h"  #include <iostream>  #include <map>    using namespace std;      int main ()  {      map<char,int> mymap;      map<char,int>::iterator it;            mymap['a'] = 10;      mymap['b'] = 20;      mymap['c'] = 30;      mymap['d'] = 40;      mymap['e'] = 50;      mymap.insert(pair<char,int>('f',60));        cout<<"initial mymap contains :\n";      for (it = mymap.begin();it!= mymap.end();it++)      {          cout<<it->first<<"=>"<<it->second<<'\n';      }        it = mymap.find('b');      mymap.erase(it);        mymap.erase('c');        it = mymap.find('e');      mymap.erase(it,mymap.end());        cout<<"now mymap contains :\n";      for (it = mymap.begin();it!= mymap.end();it++)      {          cout<<it->first<<"=>"<<it->second<<'\n';      }        return 0;  }  

上述代码运行结果为:

 

如果想往map/multimap中修改一个映射的值,应先插入一个新映射,再把与修改的映射删除。

4.遍历函数    

    iterator begin():返回首元素的迭代器指针

    iterator end():返回尾元素的迭代器指针

    reverse_iterator rbegin():返回尾元素的逆向迭代器指针

    reverse_iterator rend():返回首元素前一个位置的迭代器指针

5.操作函数   

    const_iterator lower_bound(const Key& key):返回键值大于等于key的迭代器指针     const_iterator upper_bound(const Key& key):返回键值大于key的迭代器指针     int count(const Key& key) const:返回键值等于key的元素的个数     pair<const_iterator,const_iterator> equal_range(const Key& key) const:返回容器中键值等于key的迭代指针[first, last)     const_iterator find(const Key& key) const:查找功能,返回键值等于key的迭代器指针     void swap(set& s):交换但映射元素     void swap(multiset& s):交换多映射元素  

6.特殊函数

    reference operator[](const Key& k):仅在但映射map类中,可以以数组的形式给映射添加键-值对,并可返回值的引用。

                               三、STL:set/multiset用法详解

 

        使用set或multiset之前,必须加入头文件<set>

Set、multiset都是集合类,差别在与set中不允许有重复元素,multiset中允许有重复元素。

sets和multiset内部以平衡二叉树实现

 

1.   常用函数

1)        构造函数和析构函数

set c:创建空集合,不包含任何元素

set c(op):以op为排序准则,产生一个空的set

set c1(c2):复制c2中的元素到c1中

set c(const value_type *first, const value_type* last):复制[first, last)之间元素构成新集合

set c(const value_type *first, const value_type* last,op):以op为排序准则,复制[first, last)之间元素构成新集合。

c.~set()销毁所有元素,释放内存

 

multiset mc:创建空集合,不包含任何元素

multiset mc(op):以op为排序准则,产生一个空的set

multiset c1(c2):复制c2中的元素到c1中

multiset c(const value_type *first, const value_type* last):复制[first, last)之间元素构成新集合

multiset c(const value_type *first, const value_type* last,op):以op为排序准则,复制[first, last)之间元素构成新集合。

c.~set()销毁所有元素,释放内存

 

[cpp] view plaincopy

// constructing sets  #include <iostream>  #include <set>    bool fncomp (int lhs, int rhs) {return lhs<rhs;}    struct classcomp {    bool operator() (const int& lhs, const int& rhs) const    {return lhs<rhs;}  };    int main ()  {    std::set<int> first;                           // empty set of ints      int myints[]= {10,20,30,40,50};    std::set<int> second (myints,myints+5);        // range      std::set<int> third (second);                  // a copy of second      std::set<int> fourth (second.begin(), second.end());  // iterator ctor.      std::set<int,classcomp> fifth;                 // class as Compare      bool(*fn_pt)(int,int) = fncomp;    std::set<int,bool(*)(int,int)> sixth (fn_pt);  // function pointer as Compare      return 0;  }  

 

 

2)        大小、判断空函数

    int size() const:返回容器元素个数     bool empty() const:判断容器是否为空,若返回true,表明容器已空

3)        增加、删除函数

      pair<iterator,bool> insert( x):插入元素x

    iterator insert(iterator it,x):在迭代器it处插入元素x

    void insert(const value_type *first,const value_type *last):插入[first, last)之间元素

    iterator erase(iterator it):删除迭代器指针it处元素

    iterator erase(iterator first,iterator last):删除[first, last)之间元素

    size_type erase(const Key& key):删除元素值等于key的元素

 

[cpp] view plaincopy

#include <iostream>  #include <set>    int main ()  {    std::set<int> myset;    std::set<int>::iterator it;    std::pair<std::set<int>::iterator,bool> ret;      // set some initial values:    for (int i=1; i<=5; ++i) myset.insert(i*10);    // set: 10 20 30 40 50      ret = myset.insert(20);               // no new element inserted      if (ret.second==false) it=ret.first;  // "it" now points to element 20      myset.insert (it,25);                 // max efficiency inserting    myset.insert (it,24);                 // max efficiency inserting    myset.insert (it,26);                 // no max efficiency inserting      int myints[]= {5,10,15};              // 10 already in set, not inserted    myset.insert (myints,myints+3);      std::cout << "myset contains:";    for (it=myset.begin(); it!=myset.end(); ++it)      std::cout << ' ' << *it;    std::cout << '\n';      return 0;  }  

[cpp] view plaincopy

#include <iostream>  #include <set>    int main ()  {    std::set<int> myset;    std::set<int>::iterator it;      // insert some values:    for (int i=1; i<10; i++) myset.insert(i*10);  // 10 20 30 40 50 60 70 80 90      it = myset.begin();    ++it;                                         // "it" points now to 20      myset.erase (it);      myset.erase (40);      it = myset.find (60);    myset.erase (it, myset.end());      std::cout << "myset contains:";    for (it=myset.begin(); it!=myset.end(); ++it)      std::cout << ' ' << *it;    std::cout << '\n';      return 0;  }  

 

4)        遍历函数

     iterator begin():返回首元素的迭代器指针

    iterator end():返回尾元素的迭代器指针     reverse_iterator rbegin():返回尾元素的逆向迭代器指针     reverse_iterator rend():返回首元素前一个位置的迭代器指针

[cpp] view plaincopy

#include <iostream>  #include <set>    int main ()  {    int myints[] = {75,23,65,42,13};    std::set<int> myset (myints,myints+5);      std::cout << "myset contains:";    for (std::set<int>::iterator it=myset.begin(); it!=myset.end(); ++it)      std::cout << ' ' << *it;      std::cout << '\n';      return 0;  }  

 

5)        操作函数

       const_iterator lower_bound(const Key& key):返回容器中大于等于key的迭代器指针

    const_iterator upper_bound(const Key& key):返回容器中大于key的迭代器指针

    int count(const Key& key) const:返回容器中元素等于key的元素的个数     pair<const_iterator,const_iterator> equal_range(const Key& key) const:返回容器中元素值等于key的迭代指针[first, last)     const_iterator find(const Key& key) const:查找功能,返回元素值等于key的迭代器指针     void swap(set& s):交换集合元素     void swap(multiset& s):交换多集合元素  

 

[cpp] view plaincopy

#include <iostream>  #include <set>    int main ()  {    std::set<int> myset;    std::set<int>::iterator itlow,itup;      for (int i=1; i<10; i++) myset.insert(i*10); // 10 20 30 40 50 60 70 80 90      itlow=myset.lower_bound (30);                //       ^    itup=myset.upper_bound (60);                 //                   ^      myset.erase(itlow,itup);                     // 10 20 70 80 90      std::cout << "myset contains:";    for (std::set<int>::iterator it=myset.begin(); it!=myset.end(); ++it)      std::cout << ' ' << *it;    std::cout << '\n';      return 0;  }  

[cpp] view plaincopy

#include "stdafx.h"  #include <iostream>  #include <set>    using namespace std;    int main ()  {      set<int> myset;        for (int i=1; i<=5; i++) myset.insert(i*10);   // myset: 10 20 30 40 50        pair<set<int>::const_iterator,set<int>::const_iterator> ret;      ret = myset.equal_range(30);        cout << "the lower bound points to: " << *ret.first << '\n';      cout << "the upper bound points to: " << *ret.second << '\n';        return 0;  }  

[cpp] view plaincopy

#include "stdafx.h"  #include <iostream>  #include <set>    using namespace std;    int main ()  {      int myints[]={12,75,10,32,20,25};      set<int> first (myints,myints+3);     // 10,12,75      set<int> second (myints+3,myints+6);  // 20,25,32        first.swap(second);        cout << "first contains:";      for (set<int>::iterator it=first.begin(); it!=first.end(); ++it)          cout << ' ' << *it;      cout << '\n';        cout << "second contains:";      for (set<int>::iterator it=second.begin(); it!=second.end(); ++it)          cout << ' ' << *it;      cout << '\n';        return 0;  

 

 

 

 

 

 

 

                                             四、

STL:list用法详解

list容器介绍

相对于vector容器的连续线性空间,list是一个双向链表,它有一个重要性质:插入操作和删除操作都不会造成原有的list迭代器失效,每次插入或删除一个元素就配置或释放一个元素空间。也就是说,对于任何位置的元素插入或删除,list永远是常数时间。

常用函数

(1)    构造函数

list<Elem> c:创建一个空的list

list<Elem> c1(c2):复制另一个同类型元素的list

list<Elem>c(n):创建n个元素的list,每个元素值由默认构造函数确定

list<Elem>c(n,elem):创建n个元素的list,每个元素的值为elem

list<Elem>c(begin,end):由迭代器创建list,迭代区间为[begin,end)

(2)    大小、判断函数

Int size() const:返回容器元素个数

bool empty() const:判断容器是否为空,若为空则返回true

(3)    增加、删除函数

void push_back(const T& x):list元素尾部增加一个元素x

void push_front(const T& x):list元素首元素钱添加一个元素X

void pop_back():删除容器尾元素,当且仅当容器不为空

void pop_front():删除容器首元素,当且仅当容器不为空

void remove(const T& x):删除容器中所有元素值等于x的元素

void clear():删除容器中的所有元素

iterator insert(iterator it, const T& x ):在迭代器指针it前插入元素x,返回x迭代器指针

void insert(iterator it,size_type n,const T& x):迭代器指针it前插入n个相同元素x

void insert(iterator it,const_iterator first,const_iteratorlast):把[first,last)间的元素插入迭代器指针it前

iterator erase(iterator it):删除迭代器指针it对应的元素

iterator erase(iterator first,iterator last):删除迭代器指针[first,last)间的元素

(4)    遍历函数

iterator begin():返回首元素的迭代器指针

iterator end():返回尾元素之后位置的迭代器指针

reverse_iterator rbegin():返回尾元素的逆向迭代器指针,用于逆向遍历容器

reverse_iterator rend():返回首元素前一个位置的迭代器指针

reference front():返回首元素的引用

reference back():返回尾元素的引用 

(5)    操作函数

void sort():容器内所有元素排序,默认是升序

template<class Pred>void sort(Pred pr):容器内所有元素根据预断定函数pr排序

void swap(list& str):两list容器交换功能

void unique():容器内相邻元素若有重复的,则仅保留一个

void splice(iterator it,list& li):队列合并函数,队列li所有函数插入迭代指针it前,x变成空队列

void splice(iterator it,list& li,iterator first):队列li中移走[first,end)间元素插入迭代指针it前

void splice(iterator it,list& li,iterator first,iterator last):x中移走[first,last)间元素插入迭代器指针it前

void reverse():反转容器中元素顺序

基本操作示例:

[cpp] view plain copy  print?

#include "stdafx.h"  #include<iostream>  #include<string>  #include<list>  using namespace std;  typedef list<string> LISTSTR;      int _tmain(int argc, _TCHAR* argv[])  {  LISTSTR test;  test.push_back("back");  test.push_back("middle");  test.push_back("front");      cout<<test.front()<<endl;  cout<<*test.begin()<<endl;      cout<<test.back()<<endl;  cout<<*(test.rbegin())<<endl;      test.pop_front();  test.pop_back();      cout<<test.front()<<endl;  return 0;  }  

程序运行结果如下:

从上述代码可以看出list首尾元素的增加和删除都是非常容易的,test.front()相当于string& s=test.front(),返回了首元素的引用;test.begin()相当于list<string>::iterator it=test.begin(),返回了首元素的迭代器指针,因此test.front()于*test.begin()的结果是一致的。

[cpp] view plaincopy

#include "stdafx.h"  #include<iostream>  #include<string>  #include<list>  using namespace std;  typedef list<int> LISTINT;    int _tmain(int argc, _TCHAR* argv[])  {      LISTINT test;      for(int i=0;i<5;i++)      {          test.push_back(i+1);      }        LISTINT::iterator it = test.begin();      for(;it!=test.end();it++)      {          cout<<*it<<"\t";      }      cout<<endl;        //reverse show      LISTINT::reverse_iterator rit = test.rbegin();      for(;rit!=test.rend();rit++)      {          cout<<*rit<<"\t";      }      cout<<endl;      return 0;  }  

程序运行结果如下:

正向迭代器与逆向迭代器表示形式是不一样的,前者是iterator,后者是reverse_iterator。逆向显示并不会改变元素在容器中的位置,只是逆向显示。

[cpp] view plaincopy

#include "stdafx.h"  #include<iostream>  #include<string>  #include<list>  using namespace std;  typedef list<int> LISTINT;    int _tmain(int argc, _TCHAR* argv[])  {      LISTINT test;      test.push_back(1);      test.push_back(5);      test.push_back(3);      test.push_back(10);        LISTINT test2;      test2.push_back(2);      test2.push_back(8);      test2.push_back(6);      test2.push_back(9);        test.sort();      test2.sort();        test.merge(test2);        for(LISTINT::iterator it = test.begin();it!=test.end();it++)      {          cout<<*it<<"\t";      }      cout<<endl;      cout<<test.size()<<"\t"<<test2.size()<<endl;      return 0;  }  

上面的代码展示了sort merge和splice的使用,程序运行结果如下:

从允许结果可以看出,两个链表merge合并前,一般都已经俺升序排好序,合并后的链表仍然是升序排列。merge操作是数据移动操作,不是复制操作,因此t1.merge(t2)表示把test2中所有元素依次移动并插入到源链表test的适当位置,test增加了多少个元素,test2就减少了多少个元素。若用test.splice(test.begin(),test2)代替程序中的test.merge(test2),其余不变,就能看出splice的特点。splice()完成的是拼接功能,也是数据移动操作,不慎复制操作。test.splice(test.begin(),test2)表明把test2中所有元素整体地移动到原始链表test的首元素前,test增加了多少个元素,test2就减少了多少个元素。如上述代码所述,test,test2排序后,test={1,3,5,10},test2={2,6,8,9}. test.splice(test.begin(),test2)后,test={2,6,8,9,1,3,5,10},test2={};test.merge(test2)后,test={1,2,3,5,6,8,9,10},test2={}

                                                  五、

STL:deque用法详解

deque函数:

deque容器为一个给定类型的元素进行线性处理,像向量一样,它能够快速地随机访问任一个元素,并且能够高效地插入和删除容器的尾部元素。但它又与vector不同,deque支持高效插入和删除容器的头部元素,因此也叫做双端队列。deque类常用的函数如下。

(1)    构造函数

deque():创建一个空deque

deque(int nSize):创建一个deque,元素个数为nSize

deque(int nSize,const T& t):创建一个deque,元素个数为nSize,且值均为t

deque(const deque &):复制构造函数

(2)    增加函数

void push_front(const T& x):双端队列头部增加一个元素X

void push_back(const T& x):双端队列尾部增加一个元素x

iterator insert(iterator it,const T& x):双端队列中某一元素前增加一个元素x

void insert(iterator it,int n,const T& x):双端队列中某一元素前增加n个相同的元素x

void insert(iterator it,const_iterator first,const_iteratorlast):双端队列中某一元素前插入另一个相同类型向量的[forst,last)间的数据

(3)    删除函数

Iterator erase(iterator it):删除双端队列中的某一个元素

Iterator erase(iterator first,iterator last):删除双端队列中[first,last)中的元素

void pop_front():删除双端队列中最前一个元素

void pop_back():删除双端队列中最后一个元素

void clear():清空双端队列中最后一个元素

(4)    遍历函数

reference at(int pos):返回pos位置元素的引用

reference front():返回手元素的引用

reference back():返回尾元素的引用

iterator begin():返回向量头指针,指向第一个元素

iterator end():返回指向向量中最后一个元素下一个元素的指针(不包含在向量中)

reverse_iterator rbegin():反向迭代器,指向最后一个元素

reverse_iterator rend():反向迭代器,指向第一个元素的前一个元素

(5)    判断函数

bool empty() const:向量是否为空,若true,则向量中无元素

(6)    大小函数

Int size() const:返回向量中元素的个数

int max_size() const:返回最大可允许的双端对了元素数量值

(7)    其他函数

void swap(deque&):交换两个同类型向量的数据

void assign(int n,const T& x):向量中第n个元素的值设置为x

 

操作示例:

[cpp] view plaincopy

// deque.cpp : 定义控制台应用程序的入口点。  //    #include "stdafx.h"  #include<iostream>  #include<deque>    using namespace std;  int _tmain(int argc, _TCHAR* argv[])  {      deque<int> d;      d.push_back( 10 );      d.push_back(20);      d.push_back(30);      cout<<"原始双端队列:"<<endl;      for(int i = 0; i < d.size(); i++)      {          cout<<d.at(i)<<"\t";      }      cout<<endl;      d.push_front(5);      d.push_front(3);      d.push_front(1);        cout<<"after push_front(5.3.1):"<<endl;      for(int i = 0;i < d.size();i++)      {          cout<<d.at(i)<<"\t";      }      cout<<endl;      d.pop_front();      d.pop_front();      cout<<"after pop_front() two times:"<<endl;      for(int i = 0;i < d.size();i++)      {          cout<<d.at(i)<<"\t";      }      cout<<endl;      return 0;  }  

程序运行结果如下所示:

2.deque与vector内存分配比较:

[cpp] view plaincopy

// deque.cpp : 定义控制台应用程序的入口点。  //    #include "stdafx.h"  #include<iostream>  #include<deque>  #include<vector>    using namespace std;  int _tmain(int argc, _TCHAR* argv[])  {      vector<int>v(2);      v[0]=10;      int *p = &v[0];      cout<<"vector第一个元素迭代指针*p="<<*p<<endl;      v.push_back(20);      cout<<"vector容量变化后原vector第1个元素迭代指针*p="<<*p<<endl;        deque<int> d(2);      d[0]=10;      int *q = &d[0];      cout<<"deque第一个元素迭代指针*q="<<*q<<endl;      d.push_back(20);      cout<<"deque容量变化后第一个元素迭代器指针*q="<<*q<<endl;  }  

程序运行结果如下图所示

该段程序的功能是:deque、vector初始化后大小为2,第一个元素都为10,当通过push_back函数分别给两个容器增加一个元素后,从结果发现原先保持的指针元素值对vector容器前后发生了变化,而对deque容器前后没有发生变化。原因为,在建立vector容器时,一般来说伴随这建立空间->填充数据->重建更大空间->复制原空间数据->删除原空间->添加新数据,如此反复,保证vector始终是一块独立的连续内存空间;在建立deque容器时,一般便随着建立空间->建立数据->建立新空间->填充新数据,如此反复,没有原空间数据的复制和删除过程,是由多个连续的内存空间组成的。

                 六、

STL:vector容器用法详解

vector类称作向量类,它实现了动态数组,用于元素数量变化的对象数组。像数组一样,vector类也用从0开始的下标表示元素的位置;但和数组不同的是,当vector对象创建后,数组的元素个数会随着vector对象元素个数的增大和缩小而自动变化。

    vector类常用的函数如下所示:

 

    1.构造函数

vector():创建一个空vectorvector(int nSize):创建一个vector,元素个数为nSizevector(int nSize,const t& t):创建一个vector,元素个数为nSize,且值均为tvector(const vector&):复制构造函数vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中

    2.增加函数

 

 

void push_back(const T& x):向量尾部增加一个元素Xiterator insert(iterator it,const T& x):向量中迭代器指向元素前增加一个元素xiterator insert(iterator it,int n,const T& x):向量中迭代器指向元素前增加n个相同的元素xiterator insert(iterator it,const_iterator first,const_iterator last):向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据

   3.删除函数

 

 

iterator erase(iterator it):删除向量中迭代器指向元素iterator erase(iterator first,iterator last):删除向量中[first,last)中元素void pop_back():删除向量中最后一个元素void clear():清空向量中所有元素

  4.遍历函数

 

 

reference at(int pos):返回pos位置元素的引用reference front():返回首元素的引用reference back():返回尾元素的引用iterator begin():返回向量头指针,指向第一个元素iterator end():返回向量尾指针,指向向量最后一个元素的下一个位置reverse_iterator rbegin():反向迭代器,指向最后一个元素reverse_iterator rend():反向迭代器,指向第一个元素之前的位置

  5.判断函数

 

 

bool empty() const:判断向量是否为空,若为空,则向量中无元素

  6.大小函数

 

 

int size() const:返回向量中元素的个数int capacity() const:返回当前向量张红所能容纳的最大元素值int max_size() const:返回最大可允许的vector元素数量值

  7.其他函数

 

 

void swap(vector&):交换两个同类型向量的数据void assign(int n,const T& x):设置向量中第n个元素的值为xvoid assign(const_iterator first,const_iterator last):向量中[first,last)中元素设置成当前向量元素

示例:

  1.初始化示例

[cpp] view plaincopy

#include "stdafx.h"  #include<iostream>  #include<vector>    using namespace std;    class A  {      //空类  };  int _tmain(int argc, _TCHAR* argv[])  {            //int型vector      vector<int> vecInt;        //float型vector      vector<float> vecFloat;        //自定义类型,保存类A的vector      vector<A> vecA;        //自定义类型,保存指向类A的指针的vector      vector<A*> vecPointA;        return 0;  }  

 

[cpp] view plaincopy

// vectorsample.cpp : 定义控制台应用程序的入口点。  //    #include "stdafx.h"  #include<iostream>  #include<vector>    using namespace std;    class A  {      //空类  };  int _tmain(int argc, _TCHAR* argv[])  {            //int型vector,包含3个元素      vector<int> vecIntA(3);            //int型vector,包含3个元素且每个元素都是9      vector<int> vecIntB(3,9);        //复制vecIntB到vecIntC      vector<int> vecIntC(vecIntB);            int iArray[]={2,4,6};      //创建vecIntD      vector<int> vecIntD(iArray,iArray+3);        //打印vectorA,此处也可以用下面注释内的代码来输出vector中的数据      /*for(int i=0;i<vecIntA.size();i++)     {         cout<<vecIntA[i]<<"     ";     }*/        cout<<"vecIntA:"<<endl;      for(vector<int>::iterator it = vecIntA.begin();it!=vecIntA.end();it++)      {          cout<<*it<<"     ";      }      cout<<endl;        //打印vecIntB      cout<<"VecIntB:"<<endl;      for(vector<int>::iterator it = vecIntB.begin() ;it!=vecIntB.end();it++)      {          cout<<*it<<"     ";      }      cout<<endl;        //打印vecIntC      cout<<"VecIntB:"<<endl;      for(vector<int>::iterator it = vecIntC.begin() ;it!=vecIntC.end();it++)      {          cout<<*it<<"     ";      }      cout<<endl;        //打印vecIntD      cout<<"vecIntD:"<<endl;      for(vector<int>::iterator it = vecIntD.begin() ;it!=vecIntD.end();it++)      {          cout<<*it<<"     ";      }      cout<<endl;      return 0;  }  

程序的运行结果如下:

 

上面的代码用了4种方法建立vector并对其初始化

  2.增加及获得元素示例:

[cpp] view plaincopy

// vectorsample.cpp : 定义控制台应用程序的入口点。  //    #include "stdafx.h"  #include<iostream>  #include<vector>    using namespace std;      int _tmain(int argc, _TCHAR* argv[])  {            //int型vector,包含3个元素      vector<int> vecIntA;        //插入1 2 3      vecIntA.push_back(1);      vecIntA.push_back(2);      vecIntA.push_back(3);            int nSize = vecIntA.size();        cout<<"vecIntA:"<<endl;        //打印vectorA,方法一:      for(int i=0;i<nSize;i++)      {          cout<<vecIntA[i]<<"     ";      }      cout<<endl;        //打印vectorA,方法二:          for(int i=0;i<nSize;i++)      {          cout<<vecIntA.at(i)<<"     ";      }      cout<<endl;        //打印vectorA,方法三:      for(vector<int>::iterator it = vecIntA.begin();it!=vecIntA.end();it++)      {          cout<<*it<<"     ";      }      cout<<endl;            return 0;  }  

上述代码对一个整形向量类进行操作,先定义一个整形元素向量类,然后插入3个值,并用3种不同的方法输出,程序运行结果如下:

 

 

[cpp] view plaincopy

// vectorsample.cpp : 定义控制台应用程序的入口点。  //    #include "stdafx.h"  #include<iostream>  #include<vector>    using namespace std;    class A  {  public:      int n;  public:      A(int n)      {          this->n = n;      }  };    int _tmain(int argc, _TCHAR* argv[])  {            //int型vector,包含3个元素      vector<A> vecClassA;        A a1(1);      A a2(2);      A a3(3);        //插入1 2 3      vecClassA.push_back(a1);      vecClassA.push_back(a2);      vecClassA.push_back(a3);                  int nSize = vecClassA.size();        cout<<"vecClassA:"<<endl;        //打印vecClassA,方法一:      for(int i=0;i<nSize;i++)      {          cout<<vecClassA[i].n<<"     ";      }      cout<<endl;        //打印vecClassA,方法二:        for(int i=0;i<nSize;i++)      {          cout<<vecClassA.at(i).n<<"     ";      }      cout<<endl;        //打印vecClassA,方法三:      for(vector<A>::iterator it = vecClassA.begin();it!=vecClassA.end();it++)      {          cout<<(*it).n<<"     ";      }      cout<<endl;            return 0;  }  

上述代码通过定义元素为类的向量,通过插入3个初始化的类,并通过3种方法输出,运行结果如下:

 

 

[cpp] view plaincopy

// vectorsample.cpp : 定义控制台应用程序的入口点。  //    #include "stdafx.h"  #include<iostream>  #include<vector>    using namespace std;    class A  {  public:      int n;  public:      A(int n)      {          this->n = n;      }  };    int _tmain(int argc, _TCHAR* argv[])  {            //int型vector,包含3个元素      vector<A*> vecClassA;        A *a1 = new A(1);      A *a2 = new A(2);      A *a3 = new A(3);        //插入1 2 3      vecClassA.push_back(a1);      vecClassA.push_back(a2);      vecClassA.push_back(a3);                  int nSize = vecClassA.size();        cout<<"vecClassA:"<<endl;        //打印vecClassA,方法一:      for(int i=0;i<nSize;i++)      {          cout<<vecClassA[i]->n<<"\t";      }      cout<<endl;        //打印vecClassA,方法二:        for(int i=0;i<nSize;i++)      {          cout<<vecClassA.at(i)->n<<"\t";      }      cout<<endl;        //打印vecClassA,方法三:      for(vector<A*>::iterator it = vecClassA.begin();it!=vecClassA.end();it++)      {          cout<<(**it).n<<"\t";      }      cout<<endl;      delete a1; delete a2;delete a3;      return 0;  }  

上述代码通过定义元素为类指针的向量,通过插入3个初始化的类指针,并通过3种方法输出指针指向的类,运行结果如下:

 

  3.修改元素示例

修改元素的方法主要有三种:1.通过数组修改,2.通过引用修改,3.通过迭代器修改

[cpp] view plaincopy

// vectorsample.cpp : 定义控制台应用程序的入口点。  //    #include "stdafx.h"  #include<iostream>  #include<vector>    using namespace std;      int _tmain(int argc, _TCHAR* argv[])  {            //int型vector,包含3个元素      vector<int> vecIntA;        //插入1 2 3      vecIntA.push_back(1);      vecIntA.push_back(2);      vecIntA.push_back(3);            int nSize = vecIntA.size();        //通过引用修改vector      cout<<"通过数组修改,第二个元素为8:"<<endl;      vecIntA[1]=8;        cout<<"vecIntA:"<<endl;      //打印vectorA      for(vector<int>::iterator it = vecIntA.begin();it!=vecIntA.end();it++)      {          cout<<*it<<"     ";      }      cout<<endl;            //通过引用修改vector      cout<<"通过引用修改,第二个元素为18:"<<endl;      int &m = vecIntA.at(1);      m=18;        cout<<"vecIntA:"<<endl;      //打印vectorA      for(vector<int>::iterator it = vecIntA.begin();it!=vecIntA.end();it++)      {          cout<<*it<<"     ";      }      cout<<endl;        //通过迭代器修改vector      cout<<"通过迭代器修改,第二个元素为28"<<endl;      vector<int>::iterator itr = vecIntA.begin()+1;      *itr = 28;        cout<<"vecIntA:"<<endl;      //打印vectorA      for(vector<int>::iterator it = vecIntA.begin();it!=vecIntA.end();it++)      {          cout<<*it<<"     ";      }      cout<<endl;        return 0;  }  

程序运行结果如下:

 

4.删除向量示例

删除向量主要通过erase和pop_back,示例代码如下

[cpp] view plaincopy

// vectorsample.cpp : 定义控制台应用程序的入口点。  //    #include "stdafx.h"  #include<iostream>  #include<vector>    using namespace std;      int _tmain(int argc, _TCHAR* argv[])  {            //int型vector,包含3个元素      vector<int> vecIntA;        //循环插入1 到10      for(int i=1;i<=10;i++)      {          vecIntA.push_back(i);      }            vecIntA.erase(vecIntA.begin()+4);                cout<<"删除第5个元素后的向量vecIntA:"<<endl;      //打印vectorA      for(vector<int>::iterator it = vecIntA.begin();it!=vecIntA.end();it++)      {          cout<<*it<<"\t";      }      cout<<endl;        //删除第2-5个元素      vecIntA.erase(vecIntA.begin()+1,vecIntA.begin()+5);        cout<<"删除第2-5个元素后的vecIntA:"<<endl;      //打印vectorA      for(vector<int>::iterator it = vecIntA.begin();it!=vecIntA.end();it++)      {          cout<<*it<<"\t";      }      cout<<endl;        //删除最后一个元素      vecIntA.pop_back();        cout<<"删除最后一个元素后的vecIntA:"<<endl;      //打印vectorA      for(vector<int>::iterator it = vecIntA.begin();it!=vecIntA.end();it++)      {          cout<<*it<<"\t";      }      cout<<endl;        return 0;  }  

程序运行结果如下:

 

3.进一步理解vector,如下图所示:

    当执行代码vector<int> v(2,5)时,在内存里建立了2个整形元素空间,值是5.当增加一个元素时,原有的空间由2个编程4个整形元素空间,并把元素1放入第3个整形空间,第4个空间作为预留空间。当增加元素2时,直接把值2放入第4个空间。当增加元素3时,由于原有向量中没有预留空间,则内存空间由4个变为8个整形空间,并把值放入第5个内存空间。

   总之,扩大新元素时,如果超过当前的容量,则容量会自动扩充2倍,如果2倍容量仍不足,则继续扩大2倍。本图是直接在原空间基础上画的新增空间,其实要复杂的多,包括重新配置、元素移动、释放原始空间的过程。因此对vector容器而言,当增加新的元素时,有可能很快完成(直接存在预留空间中),有可能稍慢(扩容后再放新元素);对修改元素值而言是较快的;对删除元素来说,弱删除尾部元素较快,非尾部元素稍慢,因为牵涉到删除后的元素移动。

4.综合示例

[cpp] view plaincopy

// vectorsample.cpp : 定义控制台应用程序的入口点。  //    #include "stdafx.h"  #include<iostream>  #include<vector>  #include<string>  using namespace std;    class Student  {  public:      string m_strNO;      string m_strName;      string m_strSex;      string m_strDate;  public:      Student(string strNO,string strName,string strSex,string strDate)      {          m_strNO = strNO;          m_strName = strName;          m_strSex = strSex;          m_strDate = strDate;      }      void Display()      {          cout<<m_strNO<<"\t";          cout<<m_strName<<"\t";          cout<<m_strSex<<"\t";          cout<<m_strDate<<"\t";      }  };    class StudCollect  {      vector<Student> m_vStud;  public:      void Add(Student &s)      {          m_vStud.push_back(s);      }      Student* Find(string strNO)      {          bool bFind = false;          int i;          for(i = 0;i < m_vStud.size();i++)          {              Student& s = m_vStud.at(i);              if(s.m_strNO == strNO)              {                  bFind = true;                  break;              }          }          Student *s = NULL;          if(bFind)              s = &m_vStud.at(i);          return s;      }  };    int _tmain(int argc, _TCHAR* argv[])  {      Student s1("1001","zhangsan","boy","1988-10-10");         Student s2("1002","lisi","boy","1988-8-25");      Student s3("1003","wangwu","boy","1989-2-14");        StudCollect s;      s.Add(s1);      s.Add(s2);      s.Add(s3);        Student *ps = s.Find("1002");      if(ps)          ps->Display();      return 0;  }  

代码运行实例如下:

                                                  七、

STL:字符串用法详解

字符串是程序设计中最复杂的变成内容之一。STL string类提供了强大的功能,使得许多繁琐的编程内容用简单的语句就可完成。string字符串类减少了C语言编程中三种最常见且最具破坏性的错误:超越数组边界;通过违背初始化或被赋以错误值的指针来访问数组元素;以及在释放了某一数组原先所分配的存储单元后仍保留了“悬挂”指针。

    string类的函数主要有:

    

Member functions

(constructor)

Construct string object (public member function )

(destructor)

String destructor (public member function )

operator=

String assignment (public member function )

Iterators:

begin

Return iterator to beginning (public member function )

end

Return iterator to end (public member function )

rbegin

Return reverse iterator to reverse beginning (public member function )

rend

Return reverse iterator to reverse end (public member function )

cbegin 

Return const_iterator to beginning (public member function )

cend 

Return const_iterator to end (public member function )

crbegin 

Return const_reverse_iterator to reverse beginning (public member function )

crend 

Return const_reverse_iterator to reverse end (public member function )

Capacity:

size

Return length of string (public member function )

length

Return length of string (public member function )

max_size

Return maximum size of string (public member function )

resize

Resize string (public member function )

capacity

Return size of allocated storage (public member function )

reserve

Request a change in capacity (public member function )

clear

Clear string (public member function )

empty

Test if string is empty (public member function )

shrink_to_fit 

Shrink to fit (public member function )

Element access:

operator[]

Get character of string (public member function )

at

Get character in string (public member function )

back 

Access last character (public member function )

front 

Access first character (public member function )

Modifiers:

operator+=

Append to string (public member function )

append

Append to string (public member function )

push_back

Append character to string (public member function )

assign

Assign content to string (public member function )

insert

Insert into string (public member function )

erase

Erase characters from string (public member function )

replace

Replace portion of string (public member function )

swap

Swap string values (public member function )

pop_back 

Delete last character (public member function )

String operations:

c_str

Get C string equivalent (public member function )

data

Get string data (public member function )

get_allocator

Get allocator (public member function )

copy

Copy sequence of characters from string (public member function )

find

Find content in string (public member function )

rfind

Find last occurrence of content in string (public member function )

find_first_of

Find character in string (public member function )

find_last_of

Find character in string from the end (public member function )

find_first_not_of

Find absence of character in string (public member function )

find_last_not_of

Find non-matching character in string from the end (public member function )

substr

Generate substring (public member function )

compare

Compare strings (public member function )

 

Member constants

npos

Maximum value for size_t (public static member constant )

 

Non-member functions overloads

operator+

Concatenate strings (function )

relational operators

Relational operators for string (function )

swap

Exchanges the values of two strings (function )

operator>>

Extract string from stream (function )

operator<<

Insert string into stream (function )

getline

Get line from stream into string (function )

 

1.string对象的定义和初始化

    初始化string对象的几种方式有:

string s1;//默认构造函数,s1为空串string s2(s1);//将s2初始化为s1的一个副本string s3("value");//将s3初始化为valuestring s4(n,'c');//将s4初始化为字符'c'的n个副本string s5(s4,0,3)//从s4中下标为0的字符开始,连续取3个字符构成s5string s6 = s5 + "value";//value 接在s5后面,注意+操作符的左右操作数至少有一个是string类型的迭代器创建,    由于可将string看作字符的容器对象,因此可以给string类的构造函数传递两个迭代器,将它们之间的数据复制到心的string对象中。

[cpp] view plaincopy

#include "stdafx.h"  #include <iostream>  #include <string>    using namespace std;    int _tmain(int argc, _TCHAR* argv[])  {      string s1("How are you");      string s2(s1.begin(),s1.end());      string s3(s1.begin()+4,s1.begin()+7);      cout<<s1<<endl;      cout<<s2<<endl;      cout<<s3<<endl;      return 0;  }  

 

2.string 对象的读写

    string对象的读写可以通过两个方式:

通过cin从标准输入中读取,cin忽略开题所有的空白字符,读取字符直至再次遇到空白字符,读取终止。用getline读取整行文本,getline函数接受两个参数:一个输入流对象和一个string对象。getline函数从输入流的下一行读取,并保存读取的内容到string中,但不包括换行符。和输入操作符不一样的是,getline并不忽略开头的换行符。即便它是输入的第一个字符,getline也将停止读入并返回。如果第一个字符就是换行符,则string参数将被置为空string。

3.string对象的插入操作

    字符串一般通过包括首字符前、尾字符后、任意位置插入等几种情况。

    

[cpp] view plaincopy

#include "stdafx.h"  #include <iostream>  #include <string>    using namespace std;    int _tmain(int argc, _TCHAR* argv[])  {      string s1("do");      cout<<"Initial size is:"<<s1.size()<<endl;      s1.insert(0,"How ");      s1.append(" you");      s1 = s1 + " do ?";      cout<<"Final size is:"<<s1.size()<<endl;      cout<<s1<<endl;      return 0;  }  

程序运行结果如下:

通过该函数可以得出:

    insert函数,第一个参数表明插入源串的位置,第二个参数表面要插入的字符串,因此利用该函数可以实现串首、串尾及任意位置处的字符串插入功能。append函数,仅有一个输入参数,在源字符串尾部追加该字符串。利用+实现字符串的连接,从而创建新的字符串。

4.替换操作

    常用的是replace函数,有三个输入参数:第一个用于指示从字符串的什么位置开始改写,第二个用于指示从源字符串中删除多少个字符,第三个是替换字符串的值。

    

[cpp] view plaincopy

#include "stdafx.h"  #include <iostream>  #include <string>    using namespace std;    int _tmain(int argc, _TCHAR* argv[])  {      string s1("I love you forever !");      cout<<"替换前:"<<s1<<endl;      s1.replace(7,3,"dachun");      cout<<"替换后"<<s1<<endl;            return 0;  }  

程序运行结果如下:

 

5.查询操作

    查询常用的函数有:

    string::npos:这是string类中的一个成员变量,一般应用在判断系统查询函数的返回值上,若等于该值,表明没有符合查询条件的结果值。find函数:在一个字符串中查找指定的单个字符或字符组。如果找到,就返回首次匹配的开始位置;如果没有找到匹配的内容,则返回string::npos。一般有两个输入参数,一个是待查询的字符串,一个是查询的起始位置,默认起始位置为0.find_first_of函数:在一个字符串中进行查找,返回值是第一个与指定字符串中任何字符匹配的字符位置;如果没有找到匹配的内容,则返回string::npos。一般有两个输入参数,一个是待查询的字符串,一个是查询的起始位置,默认起始位置为0.find_last_of函数:在一个字符串中进行查找,返回值是最后一个与指定字符串中任何字符匹配的字符位置;如果没有找到匹配的内容,则返回string::npos。一般有两个输入参数,一个是待查询的字符串,一个是查询的起始位置,默认起始位置为0.find_first_not_of函数:在一个字符串中进行查找,返回值是第一个与指定字符串中任何字符都不匹配的字符位置;如果没有找到匹配的内容,则返回string::npos。一般有两个输入参数,一个是待查询的字符串,一个是查询的起始位置,默认起始位置为0.find_last_not_of函数:在一个字符串中进行查找,返回下标值最大的与指定字符串中任何字符都不匹配的字符位置;如果没有找到匹配的内容,则返回string::npos。一般有两个输入参数,一个是待查询的字符串,一个是查询的起始位置,默认起始位置为0.rfind函数:对一个串从尾至头查找指定的单个字符或字符组,如果找到,就返回首次匹配的开始位置;如果没有找到匹配的内容,则返回string::npos。一般有两个输入参数,一个是待查询的字符串,一个是查询的起始位置,默认起始位置为0.

[cpp] view plaincopy

#include "stdafx.h"  #include <iostream>  #include <string>    using namespace std;    int _tmain(int argc, _TCHAR* argv[])  {      string s1("what's your name? my name is TOM. How do you do? Fine,thanks.");      int n = s1.find("your");      cout<<"the first your pos:"<<n<<endl;      n = s1.find("you",15);      cout<<"the first you pos begin from 15:"<<n<<endl;      n = s1.find_first_of("abcde");      cout<<"find pos when character within abcde:"<<n<<endl;      n = s1.find_first_of("abcde",3);      cout<<"find pos when character within abcde from third character:"<<n<<endl;            return 0;  }  

程序运行结果如下:

 

6.删除字符操作

    主要用erase函数,有两个迭代器输入参数,之间表示的字符将被删除掉。

    

[cpp] view plaincopy

#include "stdafx.h"  #include <iostream>  #include <string>    using namespace std;    int _tmain(int argc, _TCHAR* argv[])  {      string s1("what's your name? my name is TOM. How do you do? Fine,thanks.");      s1.erase(s1.begin(),s1.begin()+17);      cout<<"after erase to s1 is:"<<s1<<endl;        string s2 = "i love you forever!";      s2.erase(s2.begin(),s2.end());      cout<<"after erase to s2 is"<<s2<<endl;      return 0;  }  

程序运行结果如下:

 

7.比较操作

    主要是一句ASCII值来比较大小。若字符串s1“大于”s2,表明两者相比较时遇到了第一对不同的字符,字符串s1中第一个不同的字符比字符串s2中同样位置的字符在ASCII表中位置更靠后。

    C++ STL提供了多钟字符串比较方法,他们各具特色。其中最简单的就是使用非成员的重载运算符函数operator==、operator!=、operator>、operator<、operator>=和operator<=。

 

 

 

 

转载请注明原文地址: https://www.6miu.com/read-18498.html

最新回复(0)