文章目录
前言
这里是对c++标准库类型Vector的用法和相关操作的部分小结。
一、vector是什么?
标准库类型vector表示对象的集合 ,其中所有对象的类型都相同。集合中的每一个对象都有一个与之对应的索引,索引用于访问对象。由于vector“容纳着”其他对象,所以它常被称作容器(container)。
要想使用vector,必须包含适当的头文件。在后续的例子中都将假定做了如下using声明:
#include<vector>
using std::vector;
二、定义和初始化vector对象的方法
1.初始化vector对象
- 定义和初始化vector对象
vector<T> v1; v1是一个空vector,它潜在的元素是T类型的,执行默认初始化
vector<T> v2(v1); v2中包含有v1所有元素的副本
vector<T> v2 = v1; 等价于v2(v1),v2中包含有v1所有元素的副本
vector<T> v3(n,val); v3包含了n个重复的元素,每个元素的值都是val
vector<T> v4(n); v4包含了n个重复地执行力值初始化的对象
vector<T> v5{a,b,c...}; v5包含了初始值个数的元素,每个元素被赋予相应的初始值
vector<T> v5={a,b,c...}; 等价于v5{a,b,c...}
- 实例带入
vector<int> v1; //v1不含任何元素
vector<int> v1={1,2,3}; //v1中有3个元素,对应的值分别为1,2,3
vector<int> v2(v1); //v2和v1相等
vector<int> v3(4,7); //v3中有4个元素,每个元素的值都是7
vector<int> v4(5); //v4有个元素,每个元素的值都是0
2.列表初始化vector对象
如果提供的是初始元素值得列表,则只能把初始值放在花括号里进行列表初始化,而不是放在圆括号里
vector<string> v1{"a","an","the"}; //列表初始化
vector<string> v2("a","an","the"); //错误
- 创建指定数量的元素
vector<int> ivec(10,-1); //10个int类型的元素,每个都被初始化为-1
vector<string> svec(10,"hi"); //10个string类型的元素没每个都被初始化为"hi"
3.区分列表初始值还是元素数量
1) int类型
vector<int> v1(10); //v1有10个元素,每个的值都是0
vector<int> v2{10}; //v2有1个元素,该元素的值是10
vector<int> v3(10,1); //v3有10个元素,每个元素的值都是1
vector<int> v4{10,1}; //v4有2个元素,值分别是10,1
2)string类型
想要列表初始化vector对象,花括号里的值必须与元素类型相同。显然不能用int初始化string对象,所以v7和v8提供的值不能作为元素的初始值。确认无法执行列表初始化后,编译器会尝试用默认值初始化vector对象。
vector<string> v5("hi"); //错误:圆括号不能使用字符串字面值构建vector对象
vector<string> v6{"hi"}; //列表初始化:v6有一个元素
vector<string> v7{10}; //v7有10个元素默认初始化的元素
vector<string> v8{10,"hi"}; //v8有10个值为"hi"的元素
三、对vector对象的操作
1.向vector对象中添加元素
如果想创建一个vector对象令其包含0 ~ 9共10个元素,使用列表初始化的方法很容易做到这一点;但如果vector对象包含的元素是从0 ~ 99 或者0 ~ 999,这时通过列表初始化把所有元素一一罗列出来就不太合适了。
数据量较大时,更好的处理方法是先创建一个空vector,然后在运行时再利用vector的成员函数push_back向其中添加元素。push_back负责把一个值当成vector对象的尾元素"压到(push)“vector对象的"尾端(back)”。
例如:
vector<int> v2; //空的vector对象
for(int i=0;i!=100;i++)
v2.push_back(i); //依次把整数放到v2的尾端
如果运行时才知道vector对象中元素的确切个数,也应该使用上述方法创建vector空对象并为其添加元素。
例如:有时需要实时读入数据然后将其赋予vector对象。
string word;
vector<string> text; //空的vector对象
while(cin>>word){
text.push_back(word); //把word添加到text后面
}
2.其他vector操作
除了push_back之外,vector还提供了几种其他操作。大多数都和string类型的相关操作类似。
v.empty(); 如果v不含有任何元素,返回真(true);否则返回假(false)(返回值为布尔类型)
v.size(); 返回v中元素的个数
v[n] 返回v中第n个位置上的元素的引用
v1 = v2 用v2中元素的拷贝替换v1中的元素
v1 = {a,b,c...} 用列表中元素的拷贝替换v1中的元素
v1 == v2 v1和v2相等当且仅当它们的元素数量相同且对应位置的元素值都相同
v1 != v2 v1和v2不相等
<,<=,>,>= 顾名思义,以字典顺序进行比较
访问vector对象中元素的方法和访问string对象中字符的方法差不多,也是通过元素在vector对象中的位置。
例如:可以使用范围for语句处理vector对象中的所有元素:
vector<int> v{1,2,3,4,5,6,7,8,9};
for(auto &i:v) //对于v中的每个元素(注意:i是一个引用,能够对原来的数据赋予新的值)
i*=i; //求元素值的平方
for(auto i:v) //对于v中的每个元素(i的类型由auto关键字指定,同上)
cout<<i<<" "; //输出该元素
3.计算vector内对象的索引
使用下标运算符能获取到指定的元素。
通过例子能更好的理解:
假设有一组成绩的集合,其中成绩的取值是0~100。以10分为一个分数段,要求统计各个分数段各有多少个成绩。显然,从0到100总共有101种可能的成绩取值,这些成绩分布在11个分数段上:每10个分数构成一个分数段,这样的分数段有10个,额外还有一个分数段表示满分100分。这样第一个分数段将统计成绩在0到9之间的数量;第二个分数段将统计成绩在10到19之间的数量,以此类推。最后一个分数段统计满分100分的数量。
按照上述,如果输入的成绩如下:
42 65 95 100 39 67 95 76 88 76 83 92 76 93
则输出的结果应该是:
0 0 0 1 1 0 2 3 2 4 1
表示:30分以下没有人,30到39分数段1人,40到49分数段1人…(以此类推),最后一个表示有一个100分。
vector<unsigned> scores(11,0); //11个分数段,全部初始化为0
unsigned grade;
while(cin>>grade){ //读取成绩
if(grade<=100) //只处理有效成绩
++scores[grade/10]; //将对应分数段的计数值加1(将分数/10就得到分数所在的分数段)
}
4.不能用下标形式添加元素
vector<int> ivec; //空vector对象
for(decltype(ivec.size()) ix=0;ix!=10;++ix) //decltype(x)用于识别x的类型并返回该类型
ivec[ix] = ix; //严重错误:ivec不包含任何元素
ivec.push_back(ix); //正确:添加一个新元素,该元素的值是ix
注意1:vector对象(以及string对象)的下标运算符可用于访问已存在的元素,而不能用于添加元素。
注意2:确保下标合法(不越界、不溢出)的一种有效手段就是尽可能使用范围for语句。
四、总结
相关实例
1)从cin读入一组词并把它们存入一个vector对象,然后设法把所有词都改写为大写形式。输出改变后的结果,每个词占一行。
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<string> ivet;
string s;
while (cin >> s) {
if (s == "no")
break;
ivet.push_back(s);
}
for (string &x : ivet) {//引用型才能够容器中修改原来的值
for(char &c:x)
c = toupper(c);
cout << x << " ";
}
return 0;
}
2)读入一组整数并把它们存入一个vector对象,先输出第1个和最后1个元素的和,接着输出第2个和倒数第2个元素的和,以此类推。
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<int> ivec;
int x,i = 0;
while (cin >> x) { //以0作为输入的结束符
if (x == 0)
break;
ivec.push_back(x);
}
for (i = 0; i < ivec.size()/2; i++) {
cout << ivec[i] + ivec[ivec.size()-1-i] << " ";
}
if (ivec.size() % 2 == 1) //若输入的数据个数为奇数,最后将输出中间的数
cout << ivec[i];
return 0;
}
3)读入一组整数并把它们存入一个vector对象,将每对相邻整数的和输出出来。
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<int> ivec;
int x, i = 0;
while (cin >> x) { //以0作为输入的结束符
if (x == 0)
break;
ivec.push_back(x);
}
if (ivec.size() == 0) {
cout << "没有元素";
return -1;
}
for (i = 0; i < ivec.size()-1; i+=2) { //相邻两两一对,不重复
cout << ivec[i] + ivec[i+1] << " ";
}
if (ivec.size() % 2 == 1) //若输入的数据个数为奇数,对最后一个元素单独处理
cout << ivec[ivec.size() - 1];
return 0;
}