C++面向对象程序设计(八)——标准模板库STL(一)


文章目录


本文是中国大学MOOC,北京大学​


​程序设计与算法C++面向对象程序设计​​第八周笔记。本课程学习的​


​github仓库​​欢迎Fork

string类

来自模板类​​typedef basic_string<char> string​

在使用前要包含头文件​​<string>​

#include<iostream>
#include<string>
using namespace std;

int main()
{
string s1("hello");
cout << s1 <<endl;
string s2(8,'x');
cout << s2 <<endl;
string month = "March";
cout << month << endl;
string s;
s = 'n';
cout << s<<endl;
return 0;
}
//输出:
//Hello
//xxxxxxxx
//March
//n

可以使用成员函数​​length()​​​读取长度,支持​​cin​​​和​​getline(cin,s)​

可以使用​​=​​​赋值,使用​​assign​​成员函数复制

string s1("cat"),s2;
s2 = s1;
string s1("cat"),s3;
s3.assign(s1);
string s1("catpig"),s3;
s3.assign(s1,1,3);

单个字符的复制

s2[5] = s1[3] ='a';

逐个访问对象中字符

string s1("Hello");
for(int i = 0;i<s1.length();i++)
cout<<s1.at(i)<<endl;
//成员函数at会做范围检查,如果超出范围会出现out_of_range异常,而[]不会检查

可以使用​​+​​运算符连接字符串

string s1("good"),s2("morning");
s1 += s2;
cout << s1;

用成员函数​​append​​连接字符串

string s1("good"),s2("morning");
s1.append(s2);
cout << s1;
s2.append(s1,3,s1.size());
cout << s2;

string间可以比较大小​​>=​

还可以使用​​compare​​比较string大小

求子串​​substr​

string s1("hello world"),s2;
s2 = s1.substr(4,5)//下标4开始长度5个字符
cout << s2 << endl;

交换​​swap​

s1.swap(s2);//两个字符串内容交换

正着查找​​find​

s1.find("lo");
s1.find("lo",2);//下标2开始找

倒着查找​​rfind​

s1.rfind("lo");

​find_first_of​

s1.find_first_of("abcd");//从前向后查找abcd中任意一个第一次出现的地方

​find_last_of​

s1.find_last_of("abcd")//查找最后一次出现的地方

​find_first_not_of​

s1.find_first_not_of("abcd");//从前向后查找不在abcd中的字符任意一个第一次出现的地方

删除string中的字符使用成员函数​​erase()​

s1.erase(5);//去掉下标5及之后的字符

替换string中的字符

成员函数​​replace()​

s1.replace(2,3,"haha");//将下标2开始的3个字符换成"haha"

成员函数​​insert()​

s1.insert(5,s2)//s2插入到下标5的位置

成员函数​​c_str()​

转换成C语言式的char *字符串

s1.c_str(); //返回const char  *

成员函数​​data​

返回​​char *​​​字符串,不带​​const​

字符串流处理

我们可以使用​​istringstream​​​和​​ostringstream​​进行字符串上的输入输出,也称为内存输入输出

#include<string>
#include<iostream>
#include<sstream>

string input("Input test 123 4.7 A");
istringstream inputString(input);
string string1,string2;
int i;
double d;
char c;
inputString >> string1 >> string2 >> i >>d >>c;
cout << string1 << endl <<string2 <<endl;
cout << i <<endl <<d <<endl <<c <<endl;
long L;
if(inputString >> L) cout <<"long\n";
else cout << "empty\n";

/*输出
Input
test
123
4.7
A
empty
*/
ostringstream outputString;
int a =10;
outputString << "This" << a << "ok" << endl;
cout << outputString.str();
/*
输出
This 10ok
*/

标准模板库STL概述(一)

C++语言的核心优势之一就是软件的重用

主要体现在:面向对象的思想:继承,多态,标准类库

泛型程序设计思想 :模板机制,STL

基本概念

容器:可容纳各种数据类型的通用数据结构,是类模板

容器分为三种

顺序容器​​vector​​​,​​deque​​​,​​list​

vector 动态数组

头文件​​<vector>​

元素在内存中连续存放,随机存取任何元素都能在常数时间完成。在尾端增删元素具有较佳性能

deque 双向队列

元素在内存连续存放。随机存取任何元素都能在常数时间完成。在两端增删元素具有较佳性能

list 双向链表

元素在内存不连续存放。在任何位置增删元素都能在常数时间完成,不支持随机存取

关联容器​​set​​​,​​multiset​​​,​​map​​​,​​multimap​

元素是排序的,插入任何元素都按相应的排序规则来确定其位置。

在查找时具有良好的性能

通常以平衡二叉树方式实现,插入和检索时间都是​​logN​

set/multiset 集合

头文件,​​set​​​中不允许相同元素,​​multiset​​允许存在相同的元素

map/multimap

​map​​​与``set​​的不同在于​​​map​​中存放的元素有且仅有两个成员变量,一个名为​​​first​​,另一个名为​​​second​​,​​​map​​根据​​first`值对元素进行小到大排序,可快速根据first检索元素

​map​​​与``multimap​​的不同在于是否允许相同的​​firsr`值的元素

容器适配器​​stack​​​,​​queue​​​,​​priority_queue​

stack 栈

头文件 是项的有限序列,满足序列中被删除,检索和修改的项只能是最近插入序列的项。后进先出

queue 队列

插入只可以在尾部进行,删除,检索和修改只允许从头部进行。先进先出

priority_queue

头文件

优先级队列,最高优先级元素总是第一个出列

对象被插入容器中时,被插入是对象的一个复制品。许多算法,比如排序,查找,要求对容器中的元素进行比较,有的容器本身是排序的,所以放入容器对象所属的类,往往还应该重载​​==​​​和​​<​​运算符

顺序容器和关联容器中都有的成员函数

​begin​​返回指向容器中第一个元素的迭代器

​end​​返回指向容器中最后一个元素后面的位置的迭代器

​rbegin​​返回指向容器中最后一个元素的迭代器

​rend​​返回指向容器中第一个元素前面的位置的迭代器

​erase​​从容器中删除一个或几个元素

​clear​​从容器中删除所有元素

顺序容器的常用成员函数

​front​​返回容器中第一个元素的引用

​back​​返回容器中最后一个元素的引用

​push_back​​在容器末尾增加新元素

​pop_back​​删除容器末尾的元素

​erase​​删除迭代器指向的元素,或删除一个区间,返回被删除元素后面那个元素的迭代器

迭代器:可用于依次存取容器中元素,类似于指针

算法:用来操作容器中元素的函数模板

迭代器

容器类名::iterator 变量名;
容器类名::const_iterator 变量名;

访问一个迭代器指向的元素:

* 迭代器变量名

用于指向顺序容器和关联容器中的元素。用法和指针类似。有​​const​​​和非​​const​​​两种。通过迭代器可以读取它指向的元素。通过非​​const​​迭代器能修改其指向的元素。迭代器可以执行++操作

#include<venctor>
#include<iostream>
using namesapce std;

int main()
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
vector<int>::const_iterator i;
for(i = v.begin();i != v.end();++i)
cout << *i << ",";
cout << endl;
vector<int>::reverse_iterator r;
for( r =v.rbegin();r != v.rend(); r++)
cout << * r <<",";
cout<<endl;
vector<int>::iterator j;
for(j=v.begin();j!=v.end();j++)
*j = 100;
for(i=v.begin();i!=v.end();i++)
cout << * i <<",";
}

/*输出结果
1,2,3,4,
4,3,2,1,
100,100,100,100,

双向迭代器

​++p​​​,​​p++​​使p指向容器中下一个元素

​–p​​​,​​p--​​是p指向容器中上一个元素

​*p​​取p指向的元素

​p = p1​​赋值

​p == p1​​​,​​p! = p1​​判断是否相等,不等

随机访问迭代器

双向迭代器所有操作都可以使用

​p+=i​​p向后移动i个元素

​p-=i​​p向前移动i个元素

​p+i​​值为指向p后面第i个元素的迭代器

​p-i​​值为指向p前面的第i个元素的迭代器

​p[i]​​值为p后面的第i个元素的引用

​p<p1​​​,​​p<=p1​​​,​​p>p1​​​,​​p>=p1​

容器

容器上迭代器类别

vector

随机访问

deque

随机访问

list

双向

set/multiset

双向

map/multimap

双向

stack

不支持

queue

不支持

priority_queue

不支持

vector迭代器是随机迭代器

遍历vector的几种做法(queue同)

vector<int> v(100);
int i;
for(i=0;i<v.size();i++)
cout << v[i];//根据下标随机访问
vector<int>::const_iterator ii;
for(ii = v.begin();ii != v.end();ii++)
cout << *ii;
for(ii = v.begin();ii<v.end();ii++)
cout << *ii;

list迭代器是双向迭代器

list<int> v;
list<int>::const_iterator ii;
for(ii = v.begin;ii!=v.end();++ii)
cout << *ii;

双向迭代器不支持​​<​​​,list没有​​[]​​成员函数

算法

是一个个函数模板,往往在中定义

find()

template<class InIt,class T>
InIt find(InIt first,InIt last,const T&val);

查找区间是[first,last),用​​==​​判断相等

#include<vector>
#include<algorithm>
#include<iostream>

using namespace std;

int main()
{
int array[10] = {10,20,30,40};
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
vector<int>::iterator p;
p = find(v.begin(),v.end(),3)
if(p!=v.end())
cout << *p << endl;//输出3
p = find(v.begin(),v.end(),9);
if(p==v.end())
cout << 'not found'<<endl;
p = find(v.begin()+1,v.end()-2,1);
if(p!=v.end())
cout << *p <<endl;
int * pp = find(array,array+4,20);
cout << *pp << endl;

}

vector

vector实现二维数组

vector<vector<int> >v(3);

deque双向队列

所有​​vector​​​的操作都适合​​deque​​​,​​deque​​​还有​​push_front​​​和​​pop_front​​操作

list双向链表

不支持随机存取,任何位置插入删除都是常数时间

​push_front​​在前面插入

​pop_front​​删除前面元素

​sort​​排序

​remove​​删除和指定值相等的所有元素

​unique​​删除和前一个元素相同的元素

​merge​​合并两个链表,并清空被合并的那个

​reverse​​颠倒链表

​splice​​指定位置前面插入另一个链表的一个或多个元素,并在另一个链表中删除被插入的元素

函数对象

若一个类重载了运算符​​()​​,那么该类的对象就是函数对象

class CMyAverge{
public:
double operator() (int a1,int a2,int a3)
{
return (double)(a1+a2+a3)/3;
}
CMyAverage average;
cout << average(3,2,3);
}