C++青少年简明教程:数组
C++数组是一种存储固定大小连续元素的数据结构。数组中的每个元素都有一个索引,通过索引可以访问或修改数组中的元素。
在C++中,数组中的元素数据类型必须一致。数组是一个连续的内存区域,用于存储相同类型的元素。在声明数组时,需要指定数组元素的数据类型,并且在数组中的所有元素都必须是该指定类型。
如果需要存储不同类型的元素,可能需要使用结构体、类或模板等其他方式来实现。
C++数组的基本特点:
固定大小:创建时必须指定数组的大小,且大小在数组生命周期内不可改变。
同一类型:数组中所有元素必须是相同的数据类型。
连续内存:数组元素在内存中连续存储,这意味着可以通过指针算术来访问元素。
数组依据维度可分为:
一维数组:用于存储线性排列的数据。由单一的索引访问每个元素,适用于表示单行或单列的数据集合。
多维数组:用于存储表格形或更高维度的数据。二维数组(或矩阵)是最常见的多维数组形式。通过多个索引访问每个元素,每个额外的维度为数据结构增加一个层级,适用于更复杂的数据组织方式,如表格、立方体等。
一维数组
一维数组是一个线性的数据结构,它包含相同类型的元素,并通过一个索引来访问每个元素。一维数组可以看作是一个行或者一列的元素列表。如:
或
可以使用一排糖果或者水果来比喻一维数组。每个位置的糖果或者水果可以看作是数组的一个元素。你可以请示学生,如果我们想要找到第3个位置的糖果,应该搜索哪个位置呢?
C++ 中,声明(定义)数组语法格式
元素的数据类型 数组的名称[元素数目]
【数组元素指的是数组中存储的单个数据项。数组下标和索引是同一个概念,用于标识数组中每个元素的位置。数组下标从0开始递增,表示元素在数组中的位置。】
元素数目也称为数组大小,即数组中元素的个数,是一个常量值。【元素数目也称为数组大小是一个常量值(常量表达式)。特别说明:虽然某些编译器可能会支持变量数组,但这并不是标准的一部分。在C++中,如果你需要一个可以动态调整大小的数组,推荐使用vector容器,vector是一个动态数组,它可以在运行时动态地增加或减少元素。与数组(array)相比,vector提供了更多的灵活性,例如自动调整大小、插入和删除元素等。】
以下是一个声明了大小为5的整数数组的示例:
int numbers[5]; // 创建了一个能够存储5个整数的数组
也可以使用常量声明数组:
const int n = 5;
int numbers[n]; // 创建了一个能够存储5个整数的数组
【如果您需要在运行时动态地调整数组的大小,可以考虑使用动态数组或者标准库提供的容器类,例如vector。这些容器类提供了更灵活的数据结构,可以动态地增加或减少其大小。
以下是使用vector容器来实现动态大小的数组的示例:
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> numbers; // 创建一个使用int类型存储的动态数组
// 在运行时向数组中添加元素
numbers.push_back(10);
numbers.push_back(20);
numbers.push_back(30);
// 输出数组中的元素
for (int i = 0; i < numbers.size(); i++) {
cout << numbers[i] << " ";
}
return 0;
}
在这个示例中,vector容器可以存储动态数量的整数。通过使用push_back函数,我们可以在运行时向容器中添加元素。同时,通过调用size函数,我们可以获取容器中的元素数量,从而实现动态大小的数组。】
一维数组的初始化
1)使用大括号 {} 初始化数组,可以指定每个元素的初始值。例如:
int arr1[] = {1, 2, 3, 4, 5}; // 初始化一个包含5个元素的整型数组
2)指定整个数组的初始值。例如:
int arr2[5] = {1, 2, 3, 4, 5}; // 初始化一个包含5个元素的整型数组
3)不指定数组大小,直接使用大括号 {} 初始化数组,编译器会自动根据初始值的个数确定数组大小。例如:
int arr3[] = {1, 2, 3, 4, 5}; // 初始化一个包含5个元素的整型数组
4)部分初始化,未指定的元素将被默认初始化为零。例如:
int arr[5] = {1, 2, 3}; // 初始化前3个元素为1、2和3,其他两个元素默认初始化为0
5)使用循环进行初始化:
int arr[5];
for (int i = 0; i < 5; i++) {
arr[i] = i + 1; // 初始化元素为1到5
}
数组元素赋值示例:
#include <iostream>
using namespace std;
int main() {
// 声明一个整数数组,包含5个元素
int numbers[5];
// 初始化数组元素
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;
// 还可以这样声明数组并初始化int numbers[5] = {10, 20, 30, 40, 50};
// 访问数组元素并输出
cout << "第一个元素: " << numbers[0] << endl;
cout << "第三个元素: " << numbers[2] << endl;
// 修改数组元素
numbers[1] = 100;
// 输出修改后的数组元素
cout << "修改后的第二个元素: " << numbers[1] << endl;
return 0;
}
需要注意,一维数组的索引是从0开始的,即第一个元素的索引是0,第二个元素的索引是1,依此类推。
对一维数组进行赋值或修改元素的值,示例如下:
#include <iostream>
using namespace std;
int main() {
int arr[5];
// 赋值
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
// 修改元素值
arr[2] = 4;
// 访问数组元素
cout << arr[0] << endl; // 输出:1
cout << arr[2] << endl; // 输出:4
return 0;
}
例、统计数组中正数和负数和0的个数
#include <iostream>
using namespace std;
int main() {
int a[10] = {1, -10, 20, 0, 5, -6, 7, 0, -2, 0};
int positiveCount = 0; // 用于统计正数的个数
int negativeCount = 0; // 用于统计负数的个数
int zeroCount = 0; // 用于统计零的个数
// 遍历数组并统计
for (int i = 0; i < 10; ++i) {
if (a[i] > 0) {
++positiveCount;
} else if (a[i] < 0) {
++negativeCount;
} else {
++zeroCount;
}
}
// 输出结果
cout << "正数的个数: " << positiveCount << ",";
cout << "负数的个数: " << negativeCount << ",";
cout << "零的个数: " << zeroCount << endl;
return 0;
}
运行之,输出如下:
数组中正数4个,负数3个,零3个
【附C语言代码:
#include<stdio.h>
int main() {
int a[10] = {1, -10, 20, 0, 5, -6, 7, 0, -2, 0};
int positiveCount = 0; // 用于统计正数的个数
int negativeCount = 0; // 用于统计负数的个数
int zeroCount = 0; // 用于统计零的个数
// 遍历数组并统计
for (int i = 0; i < 10; ++i) {
if (a[i] > 0) {
++positiveCount;
} else if (a[i] < 0) {
++negativeCount;
} else {
++zeroCount;
}
}
// 输出结果
printf("数组中正数%d个,负数%d个,零%d个\n",positiveCount ,negativeCount, zeroCount);
}
】
二维数组
二维数组是一个包含多行和多列的表格结构,它由多个一维数组组成。二维数组的元素可以通过两个索引进行访问,第一个索引表示行号,第二个索引表示列号。可以将二维数组看作是一个矩阵,其中每个元素由其在矩阵中的行和列决定。
例如,以下是一个包含3行和4列的二维数组的示例:
在这个示例中,通过两个索引可以访问每个元素,例如a[0][2]表示行号为0、列号为2的元素。
二维数组和一维数组在使用和实现上有一些区别,二维数组需要使用两个索引来访问元素,而一维数组只需要一个索引。此外,二维数组在内存中被连续存储,每行的元素紧密相邻,而一维数组的元素在内存中是连续存储的。
可以使用一个矩阵或者棋盘来表示二维数组。你可以在黑板上画出一个3x4的方格矩阵,并把每个方格标上数字。然后向学生解释,我们可以使用两个索引来找到每个方格,第一个索引表示行号,第二个索引表示列号。
可以使用珠子串来比喻二维数组。你可以用不同颜色的珠子串成一条线,然后叠加多条珠子串,每条珠子串代表二维数组的一行。然后可以请示学生,如果我们想找到第2行第3列的珠子,应该搜索哪些珠子串?
二维数组的初始化
1)使用大括号 {} 初始化二维数组,可以指定每个元素的初始值。例如:
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}}; // 初始化一个包含2行3列的二维整型数组
也可以这样写:
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
每个括号对应一个维度,外层括号对应第一维,内层括号对应第二维。如果已经给出了足够的初始化项,就可以不用写内部嵌套的花括号了,需要注意的是,如果只给出了一部分初始化项,必须显式地使用大括号。
2)不指定二维数组的行数,直接使用大括号 {} 初始化二维数组,编译器会自动根据初始值的个数确定行数。例如:
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}}; // 初始化一个包含2行3列的二维整型数组
二维数组的列数必须在初始化时指定,行数可以根据初始值的个数自动确定。
3)部分初始化。例如:
int arr[2][3] = {{1, 2}, {4, 5}}; // 初始化部分元素,其他元素将默认初始化为0,相当于:
int arr[2][3] = {{1, 2,0}, {4, 5,0}};
内部嵌套的括号是可选的。
4)嵌套循环进行初始化。例如:
int arr[2][3];
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
arr[i][j] = i + j; // 根据需要自行给元素赋值
}
}
二维数组的示例:
#include <iostream>
using namespace std;
int main() {
int a[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 输出二维数组的元素
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++j) {
cout << a[i][j] << " ";
}
cout << endl;
}
return 0;
}
这个示例中,定义了一个 3 行 4 列的二维整数数组 a,并初始化其元素。然后,使用嵌套的 for 循环遍历二维数组并输出其元素。输出结果如下:
1 2 3 4
5 6 7 8
9 10 11 12
三维数组
C++中,三维数组的初始化和二维数组类似,但有点除外,二维数组的列数必须在初始化时指定,行数可以根据初始值的个数自动确定。但三维数组的每一维的大小都必须在定义时指定。
定义一个3维数组并赋初值
int a[2][3][4] = {{{1, 2, 3, 4},{5, 6, 7, 8}, 9, 10, 11, 12}}, {{13, 14, 15, 16}, {17, 18, 19, 20},{21, 22, 23, 24}}};
也可以这样写:
int a[2][3][4] = {
{{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}},
{{13, 14, 15, 16},
{17, 18, 19, 20},
{21, 22, 23, 24}}
};
如果已经给出了足够的初始化项,就可以不用写内部嵌套的花括号了。
每个括号对应一个维度,外层括号对应第一维,内层括号对应第二维,再内层括号对应第三维。需要注意的是,如果只给出了一部分初始化项,必须显式地使用大括号。
多维数组的构成元素优先按末尾的下标递增的顺序排列。
a[i][j][k] 中,最内层(从编程循环遍历访问数组元素的角度看)的下标是 k,其变化最快;次内层的下标是 j,其次变化;最外层的下标是 i,变化最慢。这种索引方式确实使得我们可以方便地访问任意一个多维数组中的元素。
请结合下面的示例理解,三重循环遍历三维元素的每个元素示例:
#include <iostream>
using namespace std;
int main() {
int a[2][3][4]; // 定义一个3维数组
// 给数组赋值
int num=1;
for(int i=0; i<2; i++){
for(int j=0; j<3; j++){
for(int k=0; k<4; k++){
a[i][j][k] = num++;
}
}
}
// 输出数组
for(int i=0; i<2; i++){
for(int j=0; j<3; j++){
for(int k=0; k<4; k++){
cout << "a[" << i << "][" << j << "][" << k << "] = " << a[i][j][k] << " ";
}
cout << endl;
}
cout << endl;
}
return 0;
}
这个例子中,我们定义了一个 a[2][3][4] 的3维数组。然后我们使用三重循环遍历每个元素,并给数组赋值。
最后,我们使用嵌套循环来遍历数组并输出每个元素的值。
这个程序的输出应该是以下这个样子:
a[0][0][0] = 1 a[0][0][1] = 2 a[0][0][2] = 3 a[0][0][3] = 4
a[0][1][0] = 5 a[0][1][1] = 6 a[0][1][2] = 7 a[0][1][3] = 8
a[0][2][0] = 9 a[0][2][1] = 10 a[0][2][2] = 11 a[0][2][3] = 12
a[1][0][0] = 13 a[1][0][1] = 14 a[1][0][2] = 15 a[1][0][3] = 16
a[1][1][0] = 17 a[1][1][1] = 18 a[1][1][2] = 19 a[1][1][3] = 20
a[1][2][0] = 21 a[1][2][1] = 22 a[1][2][2] = 23 a[1][2][3] = 24
定义数组时进行赋值,上面程序可修改为:
#include <iostream>
using namespace std;
int main() {
// 定义一个3维数组并赋初值
int a[2][3][4] = {{{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}},
{{13, 14, 15, 16},
{17, 18, 19, 20},
{21, 22, 23, 24}}};
// 输出数组
for(int i=0; i<2; i++){
for(int j=0; j<3; j++){
for(int k=0; k<4; k++){
cout << "a[" << i << "][" << j << "][" << k << "] = " << a[i][j][k] << " ";
}
cout << endl;
}
cout << endl;
}
return 0;
}
小结
在 C++ 中,数组是一种用于存储同类型数据集合的简单且高效的方式。以下是使用数组时需要注意的重要事项:
☆数组的大小在编译时确定,并且不能改变:
数组的大小必须在编译时指定,并且一旦定义,数组的大小在程序的生命周期内是固定的。
int arr[5]; // 定义一个包含5个整数的数组
☆数组名实际上是指向数组第一个元素的指针:
数组名本身可以作为指针使用,指向数组的第一个元素。
int* ptr = arr; // ptr 指向 arr[0]
☆当将数组作为函数参数传递时,传递的是数组的指针,而不是整个数组:
传递数组给函数时,实际上传递的是指向数组第一个元素的指针,这意味着函数内对数组的修改会影响到原数组。
void printArray(int* array, int size) {
for(int i = 0; i < size; ++i) {
std::cout << array[i] << " ";
}
}
☆使用 sizeof 运算符可以获取数组的大小(以字节为单位),但通常需要除以元素的大小来得到元素的数量:
int arr[10];
int size_in_bytes = sizeof(arr); // 获取数组大小(字节数)
int element_count = sizeof(arr) / sizeof(arr[0]); // 获取数组元素的个数
☆数组越界访问是未定义行为:
访问数组时索引超出范围会导致未定义行为,可能会导致程序崩溃或其他不可预测的结果。因此,务必确保访问数组时索引在有效范围内。
int arr[5];
arr[5] = 10; // 错误:索引越界
对于多维数组,需要按照对应的维度来访问元素。例如,对于二维数组arr,可以通过arr[i][j]来访问第i行第j列的元素。
☆数组是 C++ 中存储同类型数据集合的简单且有效的方式:
它提供快速的元素访问,适用于已知元素数量固定的场景。然而,对于需要动态调整大小的情况,可以考虑使用 C++ 标准模板库(STL)中的 std::vector。
关于数组更多情况可见 https://blog.csdn.net/cnds123/article/details/108936055