第七章 c++学习入门之标准库的使用

c++系列文章

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
第七章 c++学习入门之标准库的使用


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言C++标准库

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

c++标准库是什么?

IO库,容器类(顺序容器,关联容器(关键字))和泛型算法(顺序容器),动态内存。

一、IO库

C++不直接处理输入输出。通过标准库类型来处理IO。
IO库操作:从设备读取数据,向设备写入数据。

1.1 IO 类

支持不同类型的IO操作,要用到三个不同的头文件。
控制台窗口(普通流)。文件(文件流)。string(string流)。

//从流输入/输出数据
include<iostream>
//从文件读取/写入数据
include<fstream>
//从string读取/写入数据
include<sstream>

1.2 文件输入输出

fstream,利用>>,<<来写读文件,
管理与流关联的文件,fsttream独有,

//成员函数
fstream.open(s)
fstream.close()

使用文件流对象

定义一个文件流对象,

ifstream in(ifile); //构造一个ifstream对象并打开指定文件
ofstream out;//构造输出文件
//检查out是否open成功
if(out)     
out.open(ifile);//打开指定文件
ifstream in(ifile); //构造一个ifstream对象并打开指定文件
ofstream out;//构造输出文件
//检查out是否open成功
if(out)     
out.open(ifile);//打开指定文件

文件模式

每个文件流都定义了一个默认文件模式
in 读
out 写
app 写
trunc 截断
binary 二进制

ofstream app("file", ofstream::app); //输出模式

1.3 string流

sstream

二.顺序容器

容器:特定类型对象的集合。
标准库有三种容器适配器。
顺序位置固定的容器。控制元素存储和访问顺序。
所有容器共享公共接口。

2.1 什么是顺序容器

快速访问元素。容器的元素保存在连续的内存中,
顺序容器种类

vector可变大小数组。尾部添加/删除很快。可快访
deque双端队列 。头尾部添加删除很快。可快访
list双向链表。 任意位置添加/删除很快。可双向顺序访
forward_list单向链表 。任意位置添加/删除很快。可单向顺序访
array固定大小数组 。不能添加/删除。可快访
string与vector相似的容器,专用保存字符。尾部添加/删除很快。可快访

c++程序应使用标准库容器。

如何确定使用哪种容器?

基本原则:
一般,使用vector
容器要随机访问元素,使用vector或deque
容器中间添加/删除元素,使用list或forward_list
容器头尾添加/删除元素,使用deque
读取/输入时容器中间添加元素,然后需要随机访问:
1.向vector追加数据,再使用标准库的sort函数重排vector元素,避免在中间位置添加元素;
2.如果必须在中间添加元素,在输入阶段使用list,输入完后,讲list的元素复制到vector中。

2.2 所有容器适用操作

对所有容器都适用的操作,
每个容器都定义在一个头文件中,文件名和类型名相同。
容器都定义成模板类,
提供元素类型

deque<double> //保存double类型元素的deque容器

容器保存元素

容器中保存任意类型元素。

vector<vector<string>>  lines;//vector中的vector

容器操作:
类型别名;构造函数;赋值和swap;大小;添加/删除元素(不适用array);获取迭代器。

赋值c1=c2
swapswap(a,b)
大小c.size() 不支持单向链表
大小c.max_size()
添加删除不适用array
添加c.insert(args)
删除c.erase(args)
删除所有元素c.clear()
关系运算符==,!=
获取迭代器c.begin(),c.end()

迭代器

迭代器范围:
由一对迭代器表示,两个迭代器分别指向同一个容器中的元素或者是尾元素之后的位置。分别为begin()和end(),指定了容器中元素的范围。[begin(),end())。

容器类型成员

每个容器都定义了多个类型,
size_type,iterator,const_iterator,
如:
通过作用域运算符::,说明希望使用list类的iterator成员,vector类的difference_type成员。

list<string>::iterator iter;//string类型链表的迭代器
vector<int>::difference_type count;//int类型容器的带符号整型

begin和end成员

begin()操作:生成一个指向容器中第一个元素的迭代器,
end()操作,生成一个指向容器中尾元素之后位置的迭代器,
然后用这两个迭代器生成一个迭代器范围,
当不需要写访问时,使用cbegin和cend,表示const
使用,auto和begin()结合,如:

list<string> word={"a","b","c"};
auto it1=word.begin()//获得list<string>::iterator
auto it2=word.end()//获得list<string>::iterator
auto it3=word.cbegin()//获得list<string>::const_iterator

当auto和begin,end结合使用时,获得的迭代器类型依赖于容器类型。

容器定义和初始化

每个容器都定义了一个默认构造函数。
默认初始化,拷贝初始化列表初始化(每个容器都可以)构造函数初始化(array不可以)
容器定义

C c;//默认构造函数
C c1=c2;//c1初始化为c2,相同容器,相同元素类型
C c={a,c,b,f};//c初始化为列表中元素的拷贝,列表元素与c中元素相同
C c(b,e);//c初始化为迭代器b和e指定范围元素的拷贝,元素类型要相同

只有顺序容器(不包含array)的构造函数能接受大小参数

C seq(n,t);//seq包含n个初始化值为t的元素

初始化:

vector<string> words={"ai","deq","ad"};//列表初始化
//构造函数初始化,
vector<int> num(10,7)//构造函数初始化,10个int元素,每个元素值都是7
vector<int> num1(10)//10个0
deque<string> sVec(10);//10个空string
list<string> sVec1(10,"hi");//10个"hi"
forward_list<int> fVec(10);//10个0

只有顺序容器的构造函数接受大小参数。

特例array

标准库array的大小是类型的一部分,定义array时,指定元素类型和容器大小,
如:
array<int, 50> ia;//50个默认初始化的int
array<int,4> ia1={1,2,3,4};//列表初始化
array<int,4> ia2=ia1;//copy初始化

赋值和swap

赋值 =
将左边容器所有元素替换成右边容器使用元素的拷贝。
标准库array允许赋值,
使用assign() 在顺序容器中(除array)
assign从一个不同但相容的类型赋值,
seq.assign(b,e);将seq中元素替换为迭代器b和e中的元素,
如:将一个vector中的char*值赋给一个list中的string:

list<string> name;
vector<const char*> olds//
name.assign(olds.cbegin(),olds.cend());//将name中的元素替换为迭代器指定范围中元素的拷贝。

使用swap
交换两个相同类型容器的内容,
swap两个array会真正交换它们的元素,
交换两个容器速度很快(除array)
如:

vector<int> ivec(10);
vector<int>  ivec2(5);
swap(ivec,ivec2);//ivec包含5个元素,ivec2包含10个元素

容器大小操作

除了forward_list外(不支持size()),每个容器类型都有三个大小相关的操作。
成员函数

size();//返回容器中元素个数
max_size();//返回容器容纳的最大元素个数
empty();//size为0返回布尔值true,否则返回false

关系运算符

每个容器都支持相等运算符(==,!=)。
关系运算符(>,>=,<,<=)左右两边运算对象必须是相同类型容器,
如vector和vector进行比较,

比较两个容器本质是对两个容器的元素逐对比较(一个元素一个元素 的比较),
原则:
如果两个容器:
大小相同,所有元素对应相等,两个容器相等,否则不等;
大小不同,较小容器中每个元素都等于较大容器中对应元素(部分元素相等),则较小容器小于较大容器
③都不是另一个容器的前缀子序列(大小不同元素不相等),比较结果取决于第一个不相等元素的比较结果
如:

//列表初始化容器
vector<int> iv1={1,2,3,4,5};
vector<int> iv2={1,2,5};
vector<int> iv3={1,2,3,4};
vector<int> iv4={1,2,3,4,5};
//进行容器大小比较
iv1<iv2;//ture,③
iv1<iv3;//false,所有元素对应相等,但是iv1元素个数更多,容器更大
iv1==iv4;//ture.①
iv1==iv2;//false,iv2元素个数更少,容器更小。

容器的关系运算符使用元素的关系运算符完成比较

容器的相等运算符本质是使用元素的" == “运算符来进行比较的。
其他关系运算符使用元素的” < “运算符。
如sales_data类型并未定义” == “和” < "运算,因此不能比较两个保存sales_data类型元素的容器。

vector<sales_data> storeA,storeB;//声明两个sales_data类型的vector,默认初始化
if(storeA<storeB) //false,sales_data没有<运算符

2.3 顺序容器特有操作

顺序容器,元素如何存储,添加,访问,删除。
顺序容器特有操作。

添加元素

除array外,所有标准库容器的大小都可以灵活改变。可以动态添加或删除元素改变容器大小。
向顺序容器(非array)添加元素操作
forward_list有专用的insert和emplace
forward_list不支持push_back和emplace_back
vector和string不支持push_front和emplace_front

c.push_back(t);//在c的尾部添加t
c.emplace_back(args);//在c的尾部添加args

c.push_front(t);//头部添加
c.emplace_front(args);//头部添加args

c.insert(p,t);//在迭代器p指向的元素前创建值为t的元素,返回指向新添加元素的迭代器
c.emplace(p,args);//

c.insert(p,n,t);//在迭代器p指向的元素前插入n个值为t的元素,返回指向新添加元素的迭代器
c.insert(p,b,e);//在迭代器p指向的元素前插入迭代器b和e指定范围的元素,返回指向新添加的第一个元素的迭代器

c.insert(p,il);//在迭代器p指向的元素前插入一个花括号包围的元素值列表il,返回指向新添加的第一个元素的迭代器。

向一个vector,string,deque插入元素,会使原迭代器,引用,指针失效
不同元素使用不同策略分配元素空间,
如:
在一个vector,string尾部外的任何位置,一个deque首尾外的任何位置,添加元素,都需要移动元素。
使用push_back()
除array和forward_list之外,每个顺序容器(包括string)都支持push_back
如:

//循环每次读取一个string到word,然后添加到容器尾部
string word;
while(cin>>word)
   container.push_back(word);
//container的类型可以是vector,list,deque。

//string也可以使用push_back
string &word;
word.push_back("s");

使用push_front()
list,forward_list,deque容器支持将元素插入容器头部。

list<int> il;
size_t ix=0;
il.push_front(ix);//将元素添加到il开头

deque像vector一样提供了随机访问元素的能力,提供了vector不支持的push_front。
在容器特定位置添加元素
push_back,push_front只能添加单个元素
使用insert(),在任意位置添加0或多个元素,
vector,deque,list,string都支持Insert。
forward_list提供特殊版本的insert。
insert函数接受一个迭代器作为第一个参数,迭代器指出在容器什么位置添加新元素。insert函数将元素插入到迭代器指定的位置之前。
如:

slist.insert(iter,"hi");//将"hi"添加到iter之前的位置

如将元素插入到容器的开始位置:

vector<string> sVec;
list<string> sLi;
sLi.insert(sLi.begin(),"hi");//将"hi"添加到容器开始位置
//等价于使用push_front
sLi.push_front("hi");

//对于vector,不支持push_front,
sVec.insert(sVec.begin(),"hi");//将"hi"添加到容器开始的位置

将元素插入到vector,deque,string任何位置都是合法的,但是可能很耗时。

添加范围内元素
insert函数可以接受更多的参数,如一个元素个数和一个值,可以将指定个数的元素添加到指定位置之前,
如:

sVec.insert(sVec.end(),5,"hi");//将5个"hi"添加到sVec尾部,并且所有添加元素初始化为string"hi"。
vector<string> v={"a","d","f","h"};
//将v的后两个元素添加到sLi开始位置
sLi.insert(sLi.begin(),v.end()-2,v.end());
//将初始化列表添加到指定位置之前
sLi.insert(sLi.end(),{"this","add","at","end","now"});

使用insert的返回值
insert返回迭代器,
list sLi;
auto iter=sLi.begin();
string word;
while(cin>>word)
iter=iter.insert(iter,word);//迭代器返回值指向新元素,等价于push_front()。每一步将一个新元素添加到list头元素之前的位置。
使用emplace操作
c11引入emplace_front,emplace,emplace_back;
将参数传递给元素类型的构造函数。
如;假定c保存sales_data元素,
//在c的尾部构造一个sales_data对象,
//使用三个参数的sales_data构造函数
c.emplace_back(""555-555,25,56.9);
c.push_back(sales_data(“555-5656”,25,56.9));//创建一个临时的sales_data对象传递给push_back
emplace_back和push_back会创建新的sales_data对象。

访问元素

在顺序容器中访问元素的操作
at和下标操作只适用于vector,deque,string,array
back不适用于forward_list
c.back();//返回c中尾元素的引用
c.front();//返回c中头元素的引用
c[n];返回c中下标为n的元素的引用,
c.at(n);返回下标为n的元素的引用
访问成员函数返回的是引用
在容器中访问元素成员函数(back,front,下标,at)返回的都是引用。
对于普通引用,可以用来改变元素的值:

if(!c.empty()){
	c.front()=42;//将42赋予给c中第一个元素
	auto &v=c.back();//获得指向最后一个元素的引用
	v=1024;//改变c中元素
	auto v2=c.back();//v2不是一个引用,是c.back()的一个拷贝
	v2=0;//没改变c中元素
}

下标操作和安全的随机访问
提供快速随机访问的容器(vector,deque,sting,array)也都提供下标运算符。
下标运算符接受一个下标参数,返回容器中该位置的元素的引用。
可以使用at()函数,

vector<string> sVec;//空vector
cout<<sVec.at(0);//抛出一个out_of_range的异常,

删除元素

容器(非array)有多种删除元素的方式,
forward_list有特殊版本的erase
forward_list不支持pop_back,
vector和string不支持pop_front,

c.pop_back();//删除c中尾元素
c.pop_front();删除c中头元素
c.erase(p);//删除迭代器p指定元素,返回一个迭代器
c.erase(b,e);//删除迭代器b和e所指定范围内的元素,返回一个迭代器
c.clear();//删除c中所有元素

pop_front()和pop_back()函数
pop_front()删除头元素,
pop_back()删除尾元素,
vector,string不支持pop_front,
forward_list不支持pop_back,
不能对一个空容器执行弹出操作。

从容器内部删除一个元素
erase()从容器中指定位置删除元素,
删除由一个迭代器指定的单个元素,或由两个迭代器指定范围的所有元素,
删除多个元素
sLi.clear();//删除所有元素

特殊的forward_list操作

改变容器大小

使用resize()改变容器大小,
c.resieze(n);//调整大小尾n个元素

容器操作可能使迭代器失效

2.4 vector对象增长

2.5 string操作

2.6 容器适配器

三.泛型算法

3.1 概述

3.2

四.关联容器

五.动态内存


总结

提示:这里对文章进行总结:

例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CN-JackZhang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值