C++青少年简明教程:数组

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; // 输出:1cout << arr[2] << endl; // 输出:4return 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/21908.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

期权懂带你懂50etf认沽期权和认购期权有什么区别?

今天带你了解期权懂带你懂50etf认沽期权和认购期权有什么区别&#xff1f;在金融市场中&#xff0c;期权是一种允许持有者在未来某个时间以特定价格买入或卖出基础资产的金融衍生品。 50etf认沽期权和认购期权有什么区别&#xff1f; 50ETF认沽期权和认购期权的主要区别在于它…

聚类算法—DBSCAN算法

文章目录 DBSCAN算法基本概念1个核心思想&#xff1a;基于密度2个算法参数&#xff1a;邻域半径R和最少点数目minpoints3种点的类别&#xff1a;核心点&#xff0c;边界点和噪声点4种点的关系&#xff1a;密度直达&#xff0c;密度可达&#xff0c;密度相连&#xff0c;非密度相…

Spi Pwm Tim 对比分析

spi SPI时序图 (spi是主从机 所以主机需要从机数据 需要主极先喊从机 把从机喊答应了 才能开始读从机的数据&#xff09; cpol时钟极性 和cpha时钟相位分析 1.cpha为高&#xff0c;cpol为高&#xff0c;则偶数上升沿有效 2.cpha为高&#xff0c;cpol为低&#xff0c;则偶数…

JVM之【GC-垃圾清除算法】

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集算法主要分为以下几种&#xff1a; 标记-清除算法&#xff08;Mark-Sweep&#xff09;复制算法&#xff08;Copying&#xff09;标记-整理算法&#xff08;Mark-Compact&#xff09;分代收集算法&#xff08;Generational C…

vue3+three.js给glb模型设置视频贴图

1.在网上下载一个显示屏或者自己画一个,在blender中设置好显示屏的Mesh,UV设置好,这样方便代码中添加纹理贴图。可以让美术在建模软件中,先随机设置一张图片作为纹理,验证UV是否设置好 关于如何 在blender中给模型设置UV贴图百度很多的 // 视频 import * as THREE from…

MacOS13-将数据库转为markdown,docx格式

MacOS13-将数据库转为markdown&#xff0c;docx格式 文章目录 先说踩坑点各种模块缺失 代码效果总结参考 先说踩坑点 各种模块缺失 tkinter mysql 没错&#xff0c;你可以直接点击安装&#xff1b; 如果还出现报错 你需要打开终端 pip install mysqlclient再次点进去安…

xcode开发swift允许发送http请求设置

Xcode 现在新建项目默认只支持HTTPS请求&#xff0c;认为HTTP请求不安全&#xff0c;所以不支持。但是开发环境一般都是http模式&#xff0c;所以需要单独配置才可以访问。 需要到项目的设置里面&#xff0c;点击info&#xff0c;如果没有App Transport Security Setting这一项…

项目优化方案之---实现邮箱用户登录

之前的项目中我写的基于SpringBoot和Vue的全栈项目已经实现了基本的用户接口开发&#xff0c; 不过其代码的功能单一&#xff0c;而且写的也是有不少漏洞&#xff08;基本就像刚接手的代码*山一样&#xff09; 那之后的几篇文章都来分享一下如何优化项目&#xff08;每一章都独…

JMeter性能测试实现与分析分享

JMeter是由著名开源软件巨头Apache组织开发的纯Java的压力测试工具&#xff0c;它即能测试动态服务&#xff08;WebService&#xff09;&#xff0c;也能测试静态资源&#xff0c;包括Servlet服务、CGI脚本等&#xff0c;还能测试动态语言服务&#xff08;PHP、Java、ASP.NET等…

JVM学习-监控工具(二)

jmap&#xff1a;导出内存映像文件&内存使用情况 基本情况 jmap(JVM Memory Map)&#xff1a;一方法获取dump文件(堆转储快照文件&#xff0c;二进制文件)&#xff0c;还可以获取目标Java进程的内存相关信息&#xff0c;包括Java堆各区域的使用情况、堆中对象的统计信息、…

MyBatis学习(二)--MyBatis获取参数值的两种方式

1、搭建新的module:mybatis_parameter MyBatis获取参数值的两种方式&#xff1a;${}和#{} ${}的本质就是字符串拼接&#xff0c;采用sql拼接&#xff0c;无法防止sql注入 #{}的本质就是占位符赋值 &#xff0c;采用预编译 防止sql注入 不同参数使用案例 2、单个字面量类型…

OpenHarmony嵌套类对象属性变化:@Observed装饰器和@ObjectLink装饰器

上文所述的装饰器仅能观察到第一层的变化&#xff0c;但是在实际应用开发中&#xff0c;应用会根据开发需要&#xff0c;封装自己的数据模型。对于多层嵌套的情况&#xff0c;比如二维数组&#xff0c;或者数组项class&#xff0c;或者class的属性是class&#xff0c;他们的第二…

实时瞳孔分割算法-RITnet论文复现

源代码在这里RITnet-Github 这个模型比较小众&#xff0c;我们实验室使用了官方提供的模型进行瞳孔中心位置提取&#xff0c;以实现视线追踪&#xff0c;效果很好 一、数据集准备 RITnet也是那一届openEDS数据集挑战赛的冠军模型&#xff0c;openEDS数据集可以从Kaggle上下载&a…

数据结构--关键路径

事件v1-表示整个工程开始&#xff08;源点&#xff1a;入度为0的顶点&#xff09; 事件v9-表示整个工程结束&#xff08;汇点&#xff1a;出度为0的顶点&#xff09; 关键路径&#xff1a;路径长度最长的路径 求解关键路径问题&#xff08;AOE网&#xff09; 定义四个描述量 …

网络网络层之(6)ICMPv4协议

网络网络层之(6)ICMPv4协议 Author: Once Day Date: 2024年6月2日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: 通信网络技术_Once-Day的博客-CS…

大模型备案项目补贴政策一览【保持更新】

大模型项目、AI类项目、大模型备案通过后等一篮子财政补贴政策 上海市 加快创新体系构建 1. 提升自主创新水平&#xff1a;对引领大模型发展或取得颠覆性突破的项目&#xff0c;最高给予1000万元补贴支持。 2. 加强算力资源保障&#xff1a;实施算力伙伴计划&#xff0c;对…

力扣174题动态规划:地下城游戏(含模拟面试)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 关注微信公众号 数据分析螺丝钉 免费领取价值万元的python/java/商业…

Java进阶学习笔记36——算法

什么是算法&#xff1f; 解决某个实际问题的过程和方法。 1&#xff09;导航&#xff1b; 2&#xff09;滴滴打车&#xff1b; 3&#xff09;抖音&#xff1b; 不同的算法&#xff0c;效率高、性能好&#xff01; 在Java中&#xff0c;代码已经帮我们写好了&#xff0c;但为…

离散点云拟合三维平面参数推导(基于最小二乘)

1、背景介绍 实际中&#xff0c;很多人工构造物是由平面结构构造而成&#xff0c;如下图所示&#xff0c;为一典型的由多个平面组成的人工构筑物。因此&#xff0c;根据离散点拟合成平面&#xff0c;获取拟合平面方程&#xff0c;是点云数据处理中非常常见的数据处理操作。 2、…

鸿蒙Ability Kit(程序框架服务)【ExtensionAbility组件】

ExtensionAbility组件 ExtensionAbility组件是基于特定场景&#xff08;例如服务卡片、输入法等&#xff09;提供的应用组件&#xff0c;以便满足更多的使用场景。 每一个具体场景对应一个[ExtensionAbilityType]&#xff0c;开发者只能使用&#xff08;包括实现和访问&#…