十、数组
1、数组的概念
1)引出数组
需求:学校为了统计学生的信息,需要设计一个程序,要求如下,一共有十个学员,要求依次输入各位学员的学号,并将其打印出来。
#include <iostream>
int main()
{
int studentId1, studentId2, studentId3, studentId4, studentId5;
std::cin >> studentId1;
std::cin >> studentId2;
std::cin >> studentId3;
std::cin >> studentId4;
std::cin >> studentId5;
std::cout << "第一个学生的学号为" << studentId1 << std::endl;
std::cout << "第二个学生的学号为" << studentId2 << std::endl;
std::cout << "第三个学生的学号为" << studentId3 << std::endl;
std::cout << "第四个学生的学号为" << studentId4 << std::endl;
std::cout << "第五个学生的学号为" << studentId5 << std::endl;
}
问题描述:实际生活中,我们经常会需要处理多个具有相同性质的数据,比如100个员工的工资、10个学院的学号,这种情况下,依次申请多个变量变得不太现实或者太过繁杂,这种情况下,我们使用数组来解决这样的问题。
2)数组的声明
//数组声明语法
数据类型 数组变量名称[数组元素个数]{初始化值,初始化值...}
//示例:申请10个学员的学号
int studentId[10]{1,2,3,4} //后面的没初始化,默认为0。代表有10个元素
//示例:申请100个员工的工资
int salary[100]{} //不初始化,默认为0
注:同一个数组,其数据类型是一样的
3)数组的使用及遍历
//输入10个学生的学号,并且输出
#include <iostream>
int main()
{
int studentId[10]{};
for (int i = 0; i < 10; i++)
{
std::cout << "请输入第" << i << "个学生的学号:";
std::cin >> studentId[i];
}
for (int i = 0; i < 10; i++)
{
std::cout << "第" << i << "个学生的学号为:";
std::cout << studentId[i]<<std::endl;
}
//计算数组中元素个数
std::cout << "studentId数组中有" << sizeof(studentId) / sizeof(int) << "个元素";
}
注:数组不初始化可以编译,但是有可能使用内存中的垃圾数值
2)数组的本质
数组本质:数组的本质是按照所申请的数据类型,向操作系统申请了一段连续的内存空间,中间不能插入其他的变量
例:int age[6]在内存中是按照如下显示的,总共占用4*6=26字节
//计算数组的大小
#include <iostream>
int main()
{
int studentId[10]{};
std::cout<<"数组studentId的大小为"<<sizeof(studentId)<<std::endl; //即4*10=40字节
}
2、数组的应用
1)项目设计
需求:学校今天开学,要求等级每一位报道的学生,因此我们要设计一个程序,要求输入学员的编号,并且打印出来。根据报名表得知,今天来报道的学生有100位,但是不排除有个别学生因为飞机晚点、火山喷发等原因无法即使到达,但是无论如何,我们的报道工作还是要做的
#include <iostream>
int main()
{
int studentId[100]{ 0 };
int indexId{}; //已等级的学生信息
while (indexId < 100)
{
std::cout << "输入学号(输入0查看已等级的学生信息):";
std::cin >> studentId[indexId];
if (studentId[indexId] == 0)
{
system("cls");
for (int i = 0; i < indexId; i++)
{
std::cout << i << "号 学生学号" << studentId[i] << std::endl;
}
}
else indexId++; //,不是0,就代表学号。表示变成了下一个元素
}
}
2)数组的另外一种声明方式
//数组的另外一种声明方式:不告诉数组的元素个数,但是对值进行赋值
变量类型 数组名[]{初始化,初始化}
//示例
int a[]{1,2,3}; //编译器会自动将a声明为只有一个有3个元素的数组
3、基于数组的循环
C++11之后的新用法:
1)案例:打印出一个数组的所有元素
//打印出一个数组的所有元素
#include <iostream>
int main()
{
int studentId[]{ 1001,1002,1003,1004,1005,1006 };
for (int i = 0; i < sizeof(studentId) / sizeof(int); i++) //先计算元素个数
{
std::cout << "第"<<i<<"个学生的学号为:" << studentId[i] << std::endl;
}
}
2)基于数组的循环
①基于数组的循环语法
//基于数组的循环语法
for(变量类型 变量名称:数组名称)
{
循环内容;
}
//例
for(int i:studentId) //给i赋予studentId数组中每个元素的值,
{
循环内容;
}
//第一次i=studentId[0],第二次i=studentId[1],第三次i=studentId[3],依次。。。
//变量类型根据实际需求进行定义,例如char、auto都可以
for(auto 变量名称:数组)
{
循环内容;
}
②基于数组的循环用法
//基于数组的循环用法
#include <iostream>
int main()
{
int studentId[]{ 9991,9992,9993,9994,9995,9996 };
for (int i : studentId)
{
std::cout << i << std::endl; //取元素时,不再使用studentId[i]取数据中的值,而是直接通过i
}
}
③通过auto指定变量类型
//通过auto指定变量类型
#include <iostream>
int main()
{
int studentId[]{ 9991,9992,9993,9994,9995,9996 };
for (auto i : studentId) //系统通过auto自动推断出变量类型
{
std::cout << i << std::endl;
}
}
④变量类型可以是任意类型
#include <iostream>
int main()
{
int studentId[]{ 65,66,67,68,69,70 };
for (char i:studentId) //次数会进行强制类型转化
{
std::cout << i<< std::endl;
}
}
4、多维数组
1)引出多维数组:
需求:学校冬季要发大白菜,一共有3个班级,每个班级5个学员,要求统计这三个班所有学员的学号,并且打印出来。
//一维数组实现
#include <iostream>
int main()
{
int studentId[15]{ };
for (int x = 0; x < 15; x++)
{
std::cout << "第" << (x / 5) + 1 << "班,第" << (x % 5)+1 << "个学生" << std::endl;
}
}
2)多维数组的定义
//多维数组声明语法
类型 变量名称[元素个数][元素个数]...[元素个数]{};
//示例
int studentId[3][5]{}; //即可表示3个班,5个学员
//多维数组初始化示例
int studentId[3][5]
{
{101,102,103,104,105}, //访问第一个元素studentId[0][0]
{201,202,203,204,205},
{301,302,303,304,305} //访问第15个元素studentId[2][4]
}
案例:学校冬季要发大白菜,一共有3个班级,每个班级5个学员,要求统计这三个班所有学员的学号,并且打印出来。
#include <iostream>
//学院冬季发放大白菜,,一共3个班,每个班5个学院,要求统计这三个班所以学员的学号,并且打印出来
int main()
{
int studentId[3][5]
{
{101,102,103,104,105},
{201,202,203,204,205},
{301,302,303,304,305}
};
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 5; y++)
{
std::cout << x+1 << "班第" << y+1 << "个同学的学号是:" << studentId[x][y] << std::endl;
}
}
}
3)多维数组的遍历
除上述方式外,还可使用如下方式遍历多维数组,但是需要单独引入一个变量进行计数
#include <iostream>
//学院冬季发放大白菜,,一共3个班,每个班5个学院,要求统计这三个班所以学员的学号,并且打印出来
int main()
{
int studentId[3][5]
{
{1,2,3,4,5},
{1,2,3,4,5},
{1,2,3,4,5}
};
for (int x=0;x<3;x++)
{
int count{};
for (int y :studentId[x]) //y就表示student[x]中的值
{
count++; //单独引入一个变量进行计数
std::cout << x + 1 << "班第" << count << "个同学的学号是:" <<y << std::endl;
}
}
}
4)多维数组的本质
本质:多维数组的本质也是向操作系统申请一块连续的内存,一般来讲是按照低纬度优先排序的方式来排序(可能因操作系统和编译器不同而不同),而索引只是为了方便访问对应的内存区域
示例:int studentId[3][5]在内存中的样子如下
studentId[0][0] | studentId[0][1] | studentId[0][2] | studentId[0][3] | studentId[0][4] |
---|---|---|---|---|
studentId[1][0] | studentId[1][1] | studentId[1][2] | studentId[1][3] | studentId[1][4] |
studentId[3][0] | studentId[3][1] | studentId[3][2] | studentId[3][3] | studentId[3][4] |
4)数组的安全问题
由于数组的本质是向操作系统申请了一块内存,因此越界的数组将会访问到不该访问的地址,这种越界将会造成程序奔溃、BUG、错误,更可怕的是数组越界漏洞,可能会让攻击者拿到操作系统的控制权。
5、安全的数组(std::array容器)
1)std::array概念
由于原生的数组存在着安全问题,使用不当会造成程序的漏洞,因此C++标准库里提供了容器,后面详细的进行容器学习,本次只简单了解array这种容器如何实现类似数组的功能。
//array数组的语法
#include <array> //需要先引入头文件
std::array<变量类型,元素数量>变量名{初始化值}; //array的声明
//案例
std::array<int,5>studentId; //5个学员的学号
2)array使用
#include <iostream>
#include <array> //引入头文件
int main()
{
std::array<int, 4>studentId{ 1001,1002,1003,1004 }; //声明一个int类型的数组,包含4个元素,并进行初始化
for (int x : studentId) //遍历数组,x表示数组中的每个元素
{
std::cout << x << std::endl;
}
}
2)std::array的几个常见用法
//std::array的几个常见用法
std::array<int,5>studentId; //声明5个学员的学号
studentId.size(); //返回studentId拥有几个元素
studentId.fill(250); //将studentId数组的每个元素都设置为250
studentId.at(1); //返回studentId[1]的内容
#include <iostream>
#include <array>
int main()
{
std::array<int, 5>studentId; //声明5个学员的学号
std::cout << "数组studentId拥有" << studentId.size() << "个元素" << std::endl;; //返回studentId拥有几个元素
studentId.fill(250); //将studentId数组的每个元素都设置为250
for (int i : studentId)
{
std::cout << i << std::endl;
}
std::cout << "数组studentId的第4个值为" << studentId.at(3)<<std::endl; //返回studentId[3]的内容
}
3)std::array的安全性
当使用【数组名.at】时,如果数组越界会直接报错,便于寻找错误,但是原生数组对于越界访问的数组不报错。
4)array数组的比较
通过std::array可以比较两个数组是否相同,但是原生数组无法进行比较
//数组的比较
#include <iostream>
#include <array>
int main()
{
int classA[3]{ 123,456 };
int classB[3]{ 123,456 };
std::array<int, 5>studentIdA{123,456,789};
std::array<int, 5>studentIdB{123,456,789};
std::array<int, 5>studentIdC{121,456,789 };
std::cout << (classA == classB) << std::endl; //返回0,说明原生数组不可以进行比较
std::cout << (studentIdA == studentIdB) << std::endl; //返回1
std::cout << (studentIdA == studentIdC) << std::endl; //返回0
}
6、std::vector容器
1)std::vector语法
//vector数组的语法
#include <vector> //需要先引入头文件
std::vector<数据类型>变量名{初始化值}; //vector的声明
//案例
std::vector<int>studentId; //声明一个int类型的数组studentId,但是没有元素
std::vector<int>studentId{1,2,3}; //声明一个int类型的数组studentId,初始化3个元素
std::vector<int>studentId(5); //注意是(),不是{},设置这个vector拥有5个元素
std::vector<int>studentId(5,100); //注意是(),不是{},设置这个vector拥有5个元素,且初始值都为100
2)std::vector简单使用
#include <iostream>
#include <vector>
int main()
{
std::vector<int> studentId(5); //告诉数组有5个元素,默认有初始值
std::cout << "数组有:" << studentId.size() <<"个元素" << std::endl;
std::cout << studentId.at(2) << std::endl; //查看studentId[2]的值
for (int x : studentId)
{
std::cout << x << std::endl;
}
}
2)std::vector的新用法
注:array具备的有点,vector都具备
//向数组中动态添加值
#include <iostream>
#include <vector>
int main()
{
int userId;
std::vector<int>studentId; //定义vector数组
do
{
std::cout << "请输入学号:";
std::cin >> userId;
if (!userId) break; //如果学号为0,直接退出
studentId.push_back(userId); //向数组中动态的添加值
} while (true); //因为已经有跳出循环机制,不需要再利用while的判断
for (int x : studentId)
{
std::cout << x << std::endl;
}
}
标签:std,studentId,cout,int,数组,include
From: https://www.cnblogs.com/piaolaipiaoqu/p/17837546.html