C++STL入门之String,Vector

1.基本概念
STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称。现然主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间。
STL的从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),容器和算法通过迭代器可以进行无缝地连接。几乎所有的代码都采 用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
STL的六大组件:

  • 容器(Container)
  • 算法(Algorithm)
  • 迭代器(Iterator)
  • 仿函数(Function object)
  • 适配器(Adaptor)
  • 空间配制器(allocator)

使用STL的好处 1)STL是C++的一部分,因此不用额外安装什么,它被内建在你的编译器之内。
2)STL的一个重要特点是数据结构和算法的分离。尽管这是个简单的概念,但是这种分离确实使得STL变得非常通用。
例如,在STL的vector容器中,可以放入元素、基础数据类型变量、元素的地址;STL的sort()函数可以用来操作vector,list等容器。
3) 程序员可以不用思考STL具体的实现过程,只要能够熟练使用STL就OK了。这样他们就可以把精力放在程序开发的别的方面。 4)
STL具有高可重用性,高性能,高移植性,跨平台的优点。
高可重用性:STL中几乎所有的代码都采用了模板类和模版函数的方式实现,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。关于模板的知识,已经给大家介绍了。
高性能:如map可以高效地从十万条记录里面查找出指定的记录,因为map是采用红黑树的变体实现的。(红黑树是平横二叉树的一种)
高移植性:如在项目A上用STL编写的模块,可以直接移植到项目B上。
跨平台:如用windows的Visual Studio编写的代码可以在Mac OS的XCode上直接编译。
4) 程序员可以不用思考STL具体的实现过程,只要能够熟练使用STL就OK了。这样他们就可以把精力放在程序开发的别的方面。
5)了解到STL的这些好处,我们知道STL无疑是最值得C++程序员骄傲的一部分。每一个C++程序员都应该好好学习STL。只有能够熟练使用STL的程序员,才是好的C++程序员。

2.容器
STL容器就为我们提供了这样的方便,它允许我们重复利用已有的实现构造自己的特定类型下的数据结构,通过设置一些模板,STL容器对最常用的数据结构提供了支持,这些模板的参数允许我们指定容器中元素的数据类型,可以将我们许多重复而乏味的工作简化。容器部分主要由头文 件vector,list,deque,set,map,stack 和queue组成。对于常用的一些容器和容器适配器(可以看作由其它容器实现的容器),可以通过下表总结一下它们和相应头文件的对应关系。

2.1容器的分类
序列式容器(Sequence containers)
每个元素都有固定位置--取决于插入时机和地点,和元素值无关。
vector、deque、list
关联式容器(Associated containers)
元素位置取决于特定的排序准则,和插入顺序无关
set、multiset、map、multimap
在这里插入图片描述

3.迭代器
概括来说,迭代器在STL中用来将算法和容器联系起来,起着一种黏和剂的作用。几乎STL提供的所有算法都是通 过迭代器存取元素序列进行工作的,每一个容器都定义了其本身所专有的迭代器,用以存取容器中的元素。

4.算法

函数库对数据类型的选择对其可重用性起着至关重要的作用。举例来说,一个求方根的函数,在使用浮点数作为其参数类型的情况下的可重用性肯定比使 用整型作为它的参数类性要高。而C++通过模板的机制允许推迟对某些类型的选择,直到真正想使用模板或者说对模板进行特化的时候,STL就利用了这一点提 供了相当多的有用算法。它是在一个有效的框架中完成这些算法的——可以将所有的类型划分为少数的几类,然后就可以在模版的参数中使用一种类型替换掉同一种 类中的其他类型。 
 
STL提供了大约100个实现算法的模版函数,比如算法for_each将为指定序列中的每一个元素调用指定的函数,stable_sort以 你所指定的规则对序列进行稳定性排序等等。这样一来,只要熟悉了STL之后,许多代码可以被大大的化简,只需要通过调用一两个算法模板,就可以完成所需要 的功能并大大地提升效率。

算法部分主要由头文件,和组 成。是所有STL头文件中最大的一个(尽管它很好理解),它是由一大堆模版函数组成的,可以认为每个函数在很大程度上 都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。体积很 小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。中则定义了一些模板类, 用以声明函数对象。

5.定义容器类的模板的头文件及简单介绍
在这里插入图片描述

6容器用法
6.1STL的String

6.1.1string的构造函数
默认构造函数:
string(); //构造一个空的字符串string s1。
拷贝构造函数:
string(const string &str); //构造一个与str一样的string。如string s1(s2)。
带参数的构造函数
string(const char *s); //用字符串s初始化
string(int n,char c); //用n个字符c初始化

6.1.2string的长度
int length() const; //返回当前字符串的长度。长度不包括字符串结尾的’\0’。
bool empty() const; //当前字符串是否为空

6.1.3string的赋值
string &operator=(const string &s);//把字符串s赋给当前的字符串
string &assign(const char *s); //把字符串s赋给当前的字符串
string &assign(const char *s, int n); //把字符串s的前n个字符赋给当前的字符串
string &assign(const string &s); //把字符串s赋给当前字符串
string &assign(int n,char c); //用n个字符c赋给当前字符串
string &assign(const string &s,int start, int n); //把字符串s中从start开始的n个字符赋给当前字符串

6.1.4string字符串连接
string &operator+=(const string &s); //把字符串s连接到当前字符串结尾string &operator+=(const char *s);//把字符串s连接到当前字符串结尾
string &append(const char *s); //把字符串s连接到当前字符串结尾
string &append(const char *s,int n); //把字符串s的前n个字符连接到当前字符串结尾
string &append(const string &s); //同operator+=()
string &append(const string &s,int pos, int n);//把字符串s中从pos开始的n个字符连接到当前字符串结尾
string &append(int n, char c); //在当前字符串结尾添加n个字符c

6.1.510string的子串
string substr(int pos=0, int n=npos) const; //返回由pos开始的n个字符组成的子字符串

6.1.6string的查找 和 替换查找
int find(char c,int pos=0) const; //从pos开始查找字符c在当前字符串的位置
int find(const char *s, int pos=0) const; //从pos开始查找字符串s在当前字符串的位置
int find(const string &s, int pos=0) const; //从pos开始查找字符串s在当前字符串中的位置find函数如果查找不到,就返回-1
int rfind(char c, int pos=npos) const; //从pos开始从后向前查找字符c在当前字符串中的位置
int rfind(const char *s, int pos=npos) const;
int rfind(const string &s, int pos=npos) const;//rfind是反向查找的意思,如果查找不到, 返回-1 替换
string &replace(int pos, int n, const char *s);//删除从pos开始的n个字符,然后在pos处插入串s
string &replace(int pos, int n, const string &s); //删除从pos开始的n个字符,然后在pos处插入串s
void swap(string &s2); //交换当前字符串与s2的值

6.2Vector
6.2.1Vecor容器介绍

  1. vector是将元素置于一个动态数组中加以管理的容器。
    2)vector可以随机存取元素(支持索引值直接存取, 用[]操作符或at()方法 )。vector尾部添加或移除元素非常快速。但是在中部或头部插入元素或移除元素比较费时

6.2.2vector对象的构造
vector采用模板类实现,vector对象的默认构造形式
vector vecT; vector vecInt; //一个存放int的vector容器。vector vecFloat; //一个存放float的vector容器。
vector vecString; //一个存放string的vector容器。
//尖括号内还可以设置指针类型或自定义类型。
Class CA{};
vector<CA*> vecpCA; //用于存放CA对象的指针的vector容器。vector vecCA; //用于存放CA对象的vector容器。由于容器元素的存放是按值复制的方式进行的,所以此时CA必须提供CA的拷贝构造函数,以保证CA对象间拷贝正常。

6.2.3vector对象的带参数构造
int iArray[] = {0,1,2,3,4};
vector vecIntA( iArray, iArray+5 );
vector vecIntB ( vecIntA.begin() , vecIntA.end() ); //用构造函数初始化容器
vecIntB vector vecIntB ( vecIntA.begin() , vecIntA.begin()+3 ); vector vecIntC(3,9); //此代码运行后,容器vecIntB就存放3个元素,每个元素的值是9。
vector vecIntD(vecIntA);

6.2.4vector的赋值
vector vecIntA, vecIntB, vecIntC, vecIntD;
int iArray[] = {0,1,2,3,4};
vecIntA.assign(iArray,iArray+5);
vecIntB.assign( vecIntA.begin(), vecIntA.end() ); //用其它容器的迭代器作参数。
vecIntC.assign(3,9);
vector vecIntD;
vecIntD = vecIntA;
vecIntA.swap(vecIntD);

6.2.5vector的大小
1)vector.size(); //返回容器中元素的个数
2)vector.empty(); //判断容器是否为空
3)vector.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
4)vector.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。

6.2.6vector末尾的添加移除操作api
vector vecInt;
vecInt.push_back(1); //在容器尾部加入一个元素
vecInt.push_back(3); //移除容器中最后一个元素
vecInt.push_back(5);
vecInt.push_back(7);
vecInt.push_back(9);
vecInt.pop_back();
vecInt.pop_back();
//{5 ,7 ,9}

6.2.7vector的数据存取
vec.at(idx); //返回索引idx所指的数据,如果idx越界,抛出out_of_range异常。
vec[idx]; //返回索引idx所指的数据,越界时,运行直接报错 vector vecInt; //假设包含1 ,3 ,5 ,7 ,9
vecInt.at(2) == vecInt[2] ; //5
vecInt.at(2) = 8; 或 vecInt[2] = 8;
//vecInt 就包含 1, 3, 8, 7, 9值
int iF = vector.front(); //iF1
int iB = vector.back(); //iB
9
vector.front() = 11; //vecInt包含{11,3,8,7,9}
vector.back() = 19; //vecInt包含{11,3,8,7,19}

6.2.8迭代器基本原理
迭代器是一个“可遍历STL容器内全部或部分元素”的对象.
迭代器的类别:

  • 输入迭代器:也有叫法称之为“只读迭代器”,它从容器中读取元素,只能一次读入一个元素向前移动,只支持一遍算法,同一个输入迭代器不能两遍遍历一个序列。
  • 输出迭代器:也有叫法称之为“只写迭代器”,它往容器中写入元素,只能一次写入一个元素向前移动,只支持一遍算法,同一个输出迭代器不能两遍遍历一个序列。
  • 正向迭代器:组合输入迭代器和输出迭代器的功能,还可以多次解析一个迭代器指定的位置,可以对一个值进行多次读/写。
  • 双向迭代器:组合正向迭代器的功能,还可以通过–操作符向后移动位置。
  • 随机访问迭代器:组合双向迭代器的功能,还可以向前向后跳过任意个位置,可以直接访问容器中任何位置的元素。

6.2.9双向迭代器与随机访问迭代器
双向迭代器支持的操作:
it++, ++it, it–, --it,*it, itA = itB,itA == itB,itA != itB
其中list,set,multiset,map,multimap支持双向迭代器。
随机访问迭代器支持的操作:在双向迭代器的操作基础上添加 it+=i, it-=i, it+i(或it=it+i),it[i],itA<itB, itA<=itB, itA>itB, itA>=itB 的功能。 其中vector,deque支持随机访问迭代器。

6.2.10vector与迭代器的配合使用

vector<int> vec;
vec.push_back(1);
vec.push_back(3);
vec.push_back(5);
vec.push_back(7);
vec.push_back(9);
vector<int>::iterator it;//声明容器vector<int>的迭代器
it = vec.begin(); //*it=1
cout<<*it<<endl;

//正向遍历:
for(vector<int>::iterator it = vec.begin();it!=vec.end();++it)
{
    int item = *it;
    cout<<item;
}
//输出 1 3 5 7 9
//逆向遍历
for(vector<int>::reverse_iterator it = vec.rbegin();it!=vec.rend();++it)
{
    int item = *it;
    cout<<item;
}
//s输出 9 7 5 3 1

6.2.11vector的插入API
vector.insert(pos,elem); //在pos位置插入一个elem元素的拷贝,返回新数据的位置。
vector.insert(pos,n,elem); //在pos位置插入n个elem数据,无返回值。vector.insert(pos,beg,end); //在pos位置插入[beg,end)区间的数据,无返回值

6.2.12vector的删除API
vector.clear(); //移除容器的所有数据
vec.erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置。
vec.erase(pos); //删除pos位置的数据,返回下一个数据的位置。

7.vector代码示例

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <iterator>
using namespace std;

int test() {
 vector<int> intvec;
 vector<float> floatvec;
 vector<string> stringvec;
 vector<int> intvec1;
 vector<int> intvec2;
 vector<int> intvec3;
 vector<int> intvec4;
 intvec.push_back(1);
 intvec.push_back(2);
 intvec.push_back(3);
 intvec.push_back(4);
 vector<int>::iterator it;
 it = intvec.begin();
 for (it; it!=intvec.end(); ++it) {
  int item = *it;
  cout << item;
 }
 cout << endl;
 for (vector<int>::reverse_iterator rit = intvec.rbegin(); rit != intvec.rend(); ++rit)
 {
  int iltem = *rit;
  cout << iltem;
 }
 cout << endl;
 int b = intvec.size();
    int a=intvec.empty();
 cout << "a=" << a << endl;
 intvec.push_back(5);
 intvec.pop_back();
 cout << intvec.front() << " " << intvec.back ()<< " " << endl;
 intvec.resize(10, 0);
 cout << intvec.at(4) << "   " << intvec[3] << endl;
    intvec.insert(intvec.begin()+7,10);
 //intvec.erase(intvec.begin()+1, intvec.end());
 //intvec.clear();
 vector<int>::iterator it1=intvec.begin();
 for (it1; it1 != intvec.end(); ++it1) {
  int item = *it1;
  cout << item;
 }
 cout << endl;
 return 0;
}

class vac 
{
public:
    int a;
    float b;
};

int main()
{
    test();
    vector<vac> vec1;
    vac a1;
    a1.a = 1;
    a1.b = 2;
    vec1.push_back(a1);
    cout << vec1.begin()->a << " " << vec1.begin()->b << endl;
    return 0;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值