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 |
---|---|
swap | swap(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提供了大量能使我们快速便捷地处理数据的函数和方法。