C++的学习之旅——string类和标准模板库

目录

一、string类

1、构造字符串

2、string类输入

3、使用字符串

 二、智能指针模板

1、作用

2、指针模板的使用 

3、智能指针模板注意事项

 三、标准模板库

1、vector

扫描二维码关注公众号,回复: 14616233 查看本文章

2、deque

3、stack

4、queue

5、list容器

6、set/multiset

7、map

四、函数对象

1、什么是函数对象

2、谓词

3、内建函数对象

(1)算术仿函数

(2)关系仿函数

(3)逻辑仿函数

五、算法

1、遍历算法

2、查找算法

3、排序算法

4、拷贝和替换算法

5、算术生成算法

6、集合算法


一、string类

1、构造字符串

string one("Lottery Winner!");//one=Lottery Winner!
string two(20,'$');//two=$$$$$$$$$$$$$$$$$$$$
string three(one);//three=Lottery Winner!
three[0]='P';three=Pottery Winner!
string four;
two="sorry! That was ";
four=two+three;//four=sorry! That was Pottery Winner!
char alls[]="All's well that ends well";
string five(alls,20);//five=All's well that ends
string six(alls+6,alls+10);//six为alls的第六到第十的字符即:six=well
string seven(&five[6],&five[10]);//seven为alls的第六到第十的字符即:six=well
string eight(four,7,16);//eight为four的第七开始,输出的十六个字符:eight=That was Pottery

2、string类输入

string stuff;
cin>>stuff;
getline(cin,stuff);
getline(stuff,':')//':'符号为边界

string类的getline版本读取结束标志:

①遇到文件尾,fail和eof返回true

②遇到分界字符,比如上面的‘:’

③读取到的字符数达到最大值,即string::npos(一般为unsigned int的最大值)和可分配的内存字节数中较小的一个

3、使用字符串

 可以将string对象和C-风格字符串进行比较,另外,还可以通过line()和size()函数返回对象的字符串,find函数搜索给定的子字符串或字符

string snake1("cobra");
string snake1("coral");
char snake3=("anaconda");
if(snake1<snake2){....}
if(snake1==snake3){....}
if(snake3!=snake2){...}

 二、智能指针模板

1、作用

使用new开辟内存空间后将地址赋给指针,并且在指针过期的时候需要将对应内存释放,即使用delete,不过有时候忘记释放将导致内存泄漏。使用智能指针模板可以避免这种情况,在指针过期时,将自动调用模板的折构函数,其中包含delete释放内存。这意味着将new返回的地址赋给这些对象后,无需记住释放内存。有三智能指针模板(auto_ptr,unique_ptr和shared_ptr).

2、指针模板的使用 

 使用智能指针需要包含头文件memory,再使用通常的模板语句来实例化所需类型指针。另外,智能指针模板位于名称空间std中。

auto_ptr<double> pd(new double);
auto_ptr<string> ps(new string);

3、智能指针模板注意事项

auto_ptr<string> ps(new string("I reigned longly as a cloud."));
auto_ptr<string> vocation;
vocation=ps;

 使用上述赋值语句,将使得ps和vocation指向同一个string对象,这将导致删除同一个对象两次(ps过期以及vocation过期时),避免此类问题的方法如下:

①定义赋值运算符,使之执行深复制,将两个指针指向不同的对象,其中一个是另一个的对象副本。

②建立所有权概念,即一个对象只能有一个智能指针拥有它,这样只有拥有对象的智能指针的构造函数删除对象。赋值操作将转让所有权。这是auto_ptr以及unique_ptr的策略

③创建智能更高的指针,可以统计对象的智能指针数(引用计数),赋值+1,过期-1,当最后一个指针过期时,才调用delete。这是shared_ptr的策略。

unique_ptr<string>demo(const char *s)
{
    unique_ptr<string> temp(new string(s));
    return temp;
}

unique_ptr<string>ps;
ps=demo("Uniquely special");//返回的temp是个临时变量,再转移所有权后会被销毁

//不过unique_ptr禁止这类语句
unique_ptr<string> ps(new string("auto"));
unique_ptr<string> pd;

//即允许是一个临时变量,不允许存在一段时间

 三、标准模板库

STL(标准模板库)提供了一组表示容器,迭代器,函数对象和算法的模板。

容器:类似于数组的存储单元,可以存储各种数据(但是容器只能存储同一变量的值)

迭代器:用来遍历容器的对象,与遍历数组的指针类似

函数对象:函数的对象,可以是类对象或者函数指针

STL使得能够构造各种容器(包括数组,队列和链表)和执行各种操作(包括搜索,排序和随机排列)

1、vector

vector使用需要包含头文件<vector>,使用

①构造函数

vector<T> v;//采用模板

vector(v.begin(),v.end());//将v[begin(),end()]区间中的元素拷贝给本身

vector(n,elem);//将n个elem拷贝给本身

vector(const vector &vec)//拷贝构造函数

②赋值操作

vector& operator=(const vector &vec);//重载等号运算符

assign(beg,end);

assign(n,elem);

③容量及大小

empty();//判断容器是否为空

capacity();//容器的容量

size();//返回容器中元素的个数

resize(int num);//重新定义容器长度为num,若变长,以默认值填充新位置,变短则删除

resize(int num,elem);//elem为默认值

④插入与删除

push_back();//尾部插入ele

pop_back();//删除最后一个元素

insert(const_iterator pos,ele);//在pos插入指定元素ele

insert(const_iterator pos,int count,ele);//在pos插入count个元素ele

erase(const_iterator pos);//删除指定位置元素

erase(const_iterator start,const_iterator end);//删除从start到end的内容

clear();//删除所有

⑤数据获取

at(int idx);//返回索引idx所指的数据

operator[];//返回索引idx所指的数据

front();//返回第一个数据

back();//返回最后一个数据

⑥互换容器

swap(vec);//将vec与本身元素互换

⑦预留空间

reserve(int len);//预留长度

#include <iostream>
#include <vector> 
#include <algorithm>
#include <string>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;

//定义类用于存放名字及年龄 
class Person
{
	public:
		Person(string name,int age)
		{
			this->m_name=name;
			this->m_age=age;
		}
		string m_name;
		int m_age;
};
//打印数据 
void myPrint(int val)
{
	cout<<val<<endl;
}

//vector用于存放整型 
void test01()
{
	
	vector<int> v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	
	vector<int>::iterator itBegin=v.begin();
	vector<int>::iterator itEnd=v.end();
	
	while(itBegin!=itEnd)
	{
		cout<<*itBegin<<endl;
		*itBegin++;
	}
	
	for(vector<int>::iterator it=v.begin();it!=v.end();it++)
	{
		cout<<*it<<endl; 
	}
	
	for_each(v.begin(),v.end(),myPrint);
}

//vector用于存放对象 
void test02()
{
	vector<Person>v;
	
	Person P1("aaa",44);
	Person P2("bbb",55);
	Person P3("ccc",66);
	Person P4("ddd",77);
	Person P5("eee",88);
	
	v.push_back(P1);
	v.push_back(P2);
	v.push_back(P3);
	v.push_back(P4);
	v.push_back(P5);
	
	for(vector<Person>::iterator it=v.begin();it!=v.end();it++)
	{
		cout<<"姓名:"<<(*it).m_name<<" 年龄:"<<(*it).m_age<<endl;
		cout<<"姓名:"<<it->m_name<<" 年龄:"<<it->m_age<<endl;
	}	
}
//vector用于存放对象指针 
void test03()
{
	vector<Person*>v;
	
	Person P1("aaa",44);
	Person P2("bbb",55);
	Person P3("ccc",66);
	Person P4("ddd",77);
	Person P5("eee",88);
	
	v.push_back(&P1);
	v.push_back(&P2);
	v.push_back(&P3);
	v.push_back(&P4);
	v.push_back(&P5);
	
	for(vector<Person*>::iterator it=v.begin();it!=v.end();it++)
	{
		cout<<"姓名:"<<(*it)->m_name<<" 年龄:"<<(*it)->m_age<<endl;
		//cout<<"姓名:"<<it->m_name<<" 年龄:"<<it->m_age<<endl;
	}	
}
//vector用于存放vector容器 
void test04()
{
	vector<vector<int>>v;
	
	//创建小容器
	vector<int>v1;
	vector<int>v2;
	vector<int>v3;
	vector<int>v4;
	
	for(int i=0;i<4;i++)
	{
		v1.push_back(i+1);
		v2.push_back(i+2);
		v3.push_back(i+3);
		v4.push_back(i+4);
	}
	 
	 //将小容器插入到大的容器
	 v.push_back(v1);
	 v.push_back(v2);
	 v.push_back(v3);
	 v.push_back(v4);
	 
	 for(vector<vector<int>>::iterator it=v.begin();it!=v.end();it++)
	 {
	 	for(vector<int>::iterator it1=(*it).begin();it1!=(*it).end();it1++)
	 	{
	 		cout<<*it1<<' ';
		 }
		 cout<<endl;
	  } 
}


int main(int argc, char** argv) {
	test01();
	test02();
	test03();
	test04();
	return 0;
}

2、deque

双端数组

与vector区别:

①vector对于头部的插入删除效率低,数据量越大,效率越低
②deque相对而言,对头部的插入删除速度回比vector快
③vector访问元素时的速度会比deque快,这和两者内部实现有关

其使用:

①构造函数

deque<T> deqT; //默认构造形式
deque(beg, end); //构造函数将[beg, end)区间中的元素拷贝给本身。
deque(n, elem); //构造函数将n个elem拷贝给本身。
deque(const deque &deq); //拷贝构造函数

 ②赋值

deque& operator=(const deque &deq); //重载等号操作符
assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem); //将n个elem拷贝赋值给本身。

③容器及大小

deque.size(); //返回容器中元素的个数
deque.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。

④插入与删除:
两端插入操作:
push_back(elem); //在容器尾部添加一个数据
push_front(elem); //在容器头部插入一个数据
pop_back(); //删除容器最后一个数据
pop_front(); //删除容器第一个数据
指定位置操作:
insert(pos,elem); //在pos位置插入一个elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem); //在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end); //在pos位置插入[beg,end)区间的数据,无返回值。
clear(); //清空容器的所有数据
erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos); //删除pos位置的数据,返回下一个数据的位置。

⑤索引

at(int idx); //返回索引idx所指的数据
operator[]; //返回索引idx所指的数据
front(); //返回容器中第一个数据元素
back(); //返回容器中最后一个数据元素

⑥排序

sort(iterator beg, iterator end) //对beg和end区间内元素进行排序

3、stack

stack是一种先进后出(First In Last Out,FILO)的数据结构,它只有一个出口(堆栈)

①构造函数:
stack<T> stk; //stack采用模板类实现, stack对象的默认构造形式
stack(const stack &stk); //拷贝构造函数
②赋值操作:
stack& operator=(const stack &stk); //重载等号操作符
③数据存取:
push(elem); //向栈顶添加元素
pop(); //从栈顶移除第一个元素
top(); //返回栈顶元素
④大小操作:
empty(); //判断堆栈是否为空
size(); //返回栈的大小

4、queue

queue是一个先进先出的数据结构

①构造函数:
queue<T> que; //queue采用模板类实现,queue对象的默认构造形式
queue(const queue &que); //拷贝构造函数
②赋值操作:
queue& operator=(const queue &que); //重载等号操作符
③数据存取:
push(elem); //往队尾添加元素
pop(); //从队头移除第一个元素
back(); //返回最后一个元素
front(); //返回第一个元素
④大小操作:
empty(); //判断堆栈是否为空
size(); //返回栈的大小

5、list容器

 将数据进行链式存储(链表)

①构造函数
list<T> lst; //list采用采用模板类实现,对象的默认构造形式:
list(beg,end); //构造函数将[beg, end)区间中的元素拷贝给本身。
list(n,elem); //构造函数将n个elem拷贝给本身。
list(const list &lst); //拷贝构造函数。

②赋值

assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem); //将n个elem拷贝赋值给本身。
list& operator=(const list &lst); //重载等号操作符
swap(lst); //将lst与本身的元素互换。

③容量与大小

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

④插入与删除1

push_back(elem);//在容器尾部加入一个元素
pop_back();//删除容器中最后一个元素
push_front(elem);//在容器开头插入一个元素
pop_front();//从容器开头移除第一个元素
insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。

insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除pos位置的数据,返回下一个数据的位置。
remove(elem);//删除容器中所有与elem值匹配的元素。

⑤数据获取

front(); //返回第一个元素。
back(); //返回最后一个元素。

⑥反转和排序

reverse(); //反转链表
sort(); //链表排序

6、set/multiset

所有元素在插入时会自动排序(底层使用二叉树) 

两者差别:

set不允许容器中有重复的元素
multiset允许容器中有重复的元素

①构造:

set<T> st; //默认构造函数:
set(const set &st); //拷贝构造函数
②赋值:
set& operator=(const set &st); //重载等号操作符

③大小及切换

empty();//判断容器是否为空
swap(st); //交换两个集合容器

size(); //返回容器中元素的数目

④插入和删除

insert(elem); //在容器中插入元素。
clear(); //清除所有元素

erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(elem); //删除容器中值为elem的元素。

⑤查找和统计

find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
count(key); //统计key的元素个数

7、map

map所有元素都是pair,pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)所有元素都会根据元素的键值自动排序。

map和multimap区别:
map不允许容器中有重复key值元素
multimap允许容器中有重复key值元素

①构造与赋值
构造:
map<T1, T2> mp; //map默认构造函数:
map(const map &mp); //拷贝构造函数
赋值:
map& operator=(const map &mp); //重载等号操作符

②大小与切换

size(); //返回容器中元素的数目
empty(); //判断容器是否为空
swap(st); //交换两个集合容器

③插入与删除

insert(elem); //在容器中插入元素。
clear(); //清除所有元素
erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(key); //删除容器中值为key的元素。

④查找与统计

find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
count(key); //统计key的元素个数

四、函数对象

1、什么是函数对象

通过重载()运算符,使得使用时方式类似函数调用,也叫仿函数

特点:

①函数对象在使用时,可以像普通函数那样调用, 可以有参数,可以有返回值
②函数对象超出普通函数的概念,函数对象可以有自己的状态
③函数对象可以作为参数传递

class Linear
{
    private:
        double slope;
        double y0;
    public:
        Linear(double s1_=1,double y_=0):slope(s1_),y0(y_){}
        double operator()(double x){return y0+slope*x;}
}

Linear f1;
Linear f2(2.5,10.0);
double y1=f1(12.5);//y1=0+1*12.5
double y2=f2(0.4);//y2=10.0+0.4*2.5

2、谓词

返回类型为bool的仿函数叫做谓词,如果operator()接受一个参数,那么叫做一元谓词
两个参数,叫做二元谓词

3、内建函数对象

STL内建了一些函数对象:算术、关系、逻辑仿函数,需要包含头文件functional

(1)算术仿函数

template<class T> T plus<T> //加法仿函数
template<class T> T minus<T> //减法仿函数
template<class T> T multiplies<T> //乘法仿函数
template<class T> T divides<T> //除法仿函数
template<class T> T modulus<T> //取模仿函数
template<class T> T negate<T> //取反仿函数

(2)关系仿函数

template<class T> bool equal_to<T> //等于
template<class T> bool not_equal_to<T> //不等于
template<class T> bool greater<T> //大于
template<class T> bool greater_equal<T> //大于等于
template<class T> bool less<T> //小于
template<class T> bool less_equal<T> //小于等于 

(3)逻辑仿函数

template<class T> bool logical_and<T> //逻辑与
template<class T> bool logical_or<T> //逻辑或
template<class T> bool logical_not<T> //逻辑非 

五、算法

算法主要是由头文件 <algorithm> <functional> <numeric> 组成。
①<algorithm> 是所有STL头文件中最大的一个,范围涉及到比较、 交换、查找、遍历操作、复制、修改等等
②<numeric> 体积很小,只包括几个在序列上面进行简单数学运算的模板函数
③<functional> 定义了一些模板类,用以声明函数对象。

1、遍历算法

for_each(iterator beg, iterator end, _func); //遍历容器

transform(iterator beg1, iterator end1, iterator beg2, _func);//搬运容器到另一个容器中(搬运的目标容器需要提前开辟空间,否则无法正常搬运)

2、查找算法

find(iterator beg, iterator end, value);//查找元素

find_if(iterator beg, iterator end, _Pred);//按条件查找元素(条件在_Pred中,可以是函数或者谓词(返回bool))

adjacent_find(iterator beg, iterator end);//查找相邻重复元素,返回第一个位置迭代器

bool binary_search(iterator beg, iterator end, value);//查找指定元素是否存在

count(iterator beg, iterator end, value);//统计元素个数

count_if(iterator beg, iterator end, _Pred);//按照条件统计数据

3、排序算法

sort(iterator beg, iterator end, _Pred);//按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

random_shuffle(iterator beg, iterator end);//指定范围内随机调整次序

merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);//两容器合并,并加到另一个容器中(dest)

reverse(iterator beg, iterator end);//将容器1元素进行反转

4、拷贝和替换算法

copy(iterator beg, iterator end, iterator dest);//将指定元素复制到另一个元素中

replace(iterator beg, iterator end, oldvalue, newvalue);//将容器中指定范围的旧元素修改为新元素

replace_if(iterator beg, iterator end, _pred, newvalue);//将满足条件的元素替换成新元素

swap(container c1, container c2);//互换两个容器的元素

5、算术生成算法

包含头文件numeric

accumulate(iterator beg, iterator end, value);//计算容器元素总和

fill(iterator beg, iterator end, value);//向容器中添加元素

6、集合算法

set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);求两个容器的交集

set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);//两个容器的并集

set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);//两个容器的差集


C++的学习笔记持续更新中~

要是文章有帮助的话

就点赞收藏关注一下啦!

感谢大家的观看

欢迎大家提出问题并指正~

猜你喜欢

转载自blog.csdn.net/qq_47134270/article/details/129109502