C++ 数组

news2024/11/15 8:40:06

**数组是具有一定顺序关系的若干对象的集合体,组成数组的对象称为该数组的元素。**数组元素用数组名与带方括号的下标表示,同一数组的各个元素具有相同的类型。数组可以由除void型以外的任何一种类型构成,构成数组的类型和数组之间的关系,可以类比为数学上数与向量或矩阵的关系。

每个元素有n个下标的数组称为n维数组。如果用array来命名一个数组,且其下标为从0到N的整数,则数组各元素为array[0],array[1],…,array[N]。这样一个数组可以顺序存储N+1个数据,因此N+1就是数组array的大小,数组的下标下界为0,数组的下标上界为N。

1.数组的声明与使用

(1)数组的声明

数组属于自定义数据类型,因此在使用之前首先要进行类型声明。声明一个数组类型,应该包括以下几个方面:

①确定数组的名称
②确定数组元素的类型
③确定数组的结构(包括数组维数,每一维的大小等)

数组类型声明的一般形式为:

数据类型 标识符[常量表达式1][常量表达式2]...;

数组中元素的类型是由“数据类型”给出,这个数据类型,可以是整型、浮点型等基本类型,也可以是结构体、类等用户自定义类型。数组的名称由“标识符”指定。

“常量表达式1”、“常量表达式2”、…称为数组的界,必须是在编译时就可求出的常量表达式,其值必须为正整数。数组的下标用来限定数组的元素个数、排列次序和每一个元素在数组中的位置。一个数组可以有多个下标,有n个下标的数组称为n维数组,数组元素的下标个数称为数组的维数。声明数组时,每一个下标表达式表示该维的下标个数(注意:不是下标上界)。数组元素个数是各下标表达式的乘积。例如:

int b[10];

表示b为int型数组,有10个元素:b[0]~b[9],可以用于存放10个元素的整数序列。

int a[5][3];

表示a为int型二维数组,其中第一维有5个下标(0~4),第二维有3个下标(0~2),数组元素的个数为15,可以用于存放5行3列的整型数据表格。值得注意的是数组下标的起始值为0。对于上面声明的数组a,第一个元素是a[0][0],最后一个元素是a[4][2]。也就是说每一维的下标都是从0开始。

(2)数组的使用

使用数组时,只能分别对数组的各个元素进行操作。数组的元素是由下标来区分的。对于一个已经声明过的数组,其元素的使用形式为:

数组名[下标表达式1][下标表达式2]...

其中下标表达式个数取决于数组的维数,N维数组就有N个下标表达式。

数组中的每一个元素都相当于一个相应类型的变量,凡是允许使用该类型变量的地方,都可以使用数组元素。可以像使用一个整型变量一样使用整型数组的每一个元素。同样,每一个类类型的数组也可以和一个该类的普通对象一样使用。在使用过程中注意以下两点:

(1)数组元素的下标表达式可以是任意合法的算术表达式,其结果必须为整数。
(2)数组元素的下标值不得超过声明时所确定的上下界,否则运算时数组越界错误。

【例】数组的声明与使用

#include<iostream>
using namespace std;

int main()
{
	int a[10], b[10];
	for (int i = 0; i < 10; i++)
	{
		a[i] = i * 2 - 1;
		b[10 - i - 1] = a[i];
	}
	for (int i = 0; i < 10; i++)
	{
		cout << "a[" << i << "]=" << a[i] << endl;
		cout << "b[" << i << "]=" << b[i] << endl;
	}
	return 0;
}

运行结果:
在这里插入图片描述
结果分析:
程序中,定义了两个有10个元素的一维数组a和b,使用for循环对它们赋值,在引用b元素时采用了算术表达式作为下标。程序运行之后将-1,1,3,…,17分别赋给数组元素a[0],a[1],…,a[9],数组b中元素的值刚好是数组a中的逆序排列。

如果把两个循环语句for(int i=0;i<10;i++)改写为for(int i=1;i<=10;i++),在编译和连接过程中都不会出错,但最后运行时不仅不会得到正确结果,而且有可能产生意想不到的错误,这就是一个典型的数组越界错误。如下:

#include<iostream>
using namespace std;

int main()
{
	int a[10], b[10];
	for (int i = 1; i <= 10; i++)
	{
		a[i] =  i * 2 - 1; ;
		b[10 - i - 1] = a[i];
	}
	for (int i = 1; i <= 10; i++)
	{
		cout << "a[" << i << "]=" << a[i] << endl;
		cout << "b[" << i << "]=" << b[i] << endl;
	}
	return 0;
}

运行结果:
在这里插入图片描述

2.数组的存储与初始化

(1)数组的存储

**数组元素在内存中是顺序、连续存储的。**数组元素在内存中占据一组连续的存储单位,逻辑上相邻的元素在物理地址上也是相邻的。一维数组是简单地按照下标的顺序连续存储的。多维数组的元素也是顺序、连续存储的,其存储顺序的约定非常重要。

元素的存储顺序问题关系到对数组做整体处理时,以什么样的顺序对数组元素进行操作。C++中很多操作都与数组元素的存储顺序相关,如数组初始化、函数间的数据传递等。

①一个一维数组可以看作是数学上的一个列向量,各元素是按下标从小到大的顺序连续存放在计算机内存单元中。例如,数组声明语句:

int arr[5];

声明了一个有5个元素的一维int型数组,可以看作是列向量[arr[0],arr[1],arr[2],arr[3],arr[4]],元素在内存中的存放顺序如下图所示:
在这里插入图片描述

②一个二维数组可以看作数学中的一个矩阵,第一个下标称为行标,第二个下标称为列标。例如,数组声明语句:

int m[2][3];

声明了一个数组,相当于一个2行3列的矩阵:
在这里插入图片描述
但在C++中,数组元素每一维的下标都是从0开始的,因此在程序中,矩阵M就被表示为:
在这里插入图片描述
其中,元素m[1][0],行标为1,列标为0,表示矩阵第2行第1个元素。二维数组在内存中是按行存放的,即先放第1行,再放第2行…每行中的元素是按列下标从小到大的顺序存放,这样的存储方式也称为优先存储。二维数组m在内存中的存放顺序如下图所示:
在这里插入图片描述
【注意】
C++中二维数组被当作一维数组的数组。例如int m[2][3]所定义的m,可以看作是这样一个数组,它的大小是2,每一个元素都是一个大小为3、类型为int的数组。由于数组的每个元素都要存放在连续空间中,因此二维数组自然会按行优先的顺序存储。

③多维数组也是采取类似的方式顺序存放。

(2)数组的初始化

数组的初始化就是在声明数组时给部分或全部元素赋初值。对于基本类型的数组,初始化过程就是给数组元素赋值;对于对象数组,每个元素都是某个类的一个对象,初始化就是调用该对象的构造函数。

声明数组时给出数组元素的初值,例如:

#include<iostream>
using namespace std;

int main()
{

	int a[10] = { 1,2,3,4,5,6,7,8,9,10 };

	for (int i = 0; i < 10; i++)
	{
		cout << "a[" << i << "]=" << a[i] << endl;
		
	}
	return 0;
}

运行结果:
在这里插入图片描述
表示声明了一个具有10个元素的int型数组,数组元素a[0],a[1],…,a[10]的值分别为1,2,3,4,5,6,7,8,9,10。声明数组时如果列出全部元素的初值,可以不用说明数组元素的个数,下面语句和int a[10] = { 1,2,3,4,5,6,7,8,9,10 };语句完全等价:

int a[] = { 1,2,3,4,5,6,7,8,9,10 };

当然,也可以只对数组元素中的部分元素进行初始化,比如声明一个有5个元素的浮点型数组,给前3个元素分别赋值1.0,2.0,3.0,可以写为:

int main()
{
	float fa[5] = { 1.0,2.0,3.0 };

	int a[10] = { 1,2,3,4,5,6,7,8,9,10 };

	for (int i = 0; i < 5; i++)
	{
		cout << "a[" << i << "]=" << fa[i] << endl;
	}
	return 0;
}

运行结果:
在这里插入图片描述
这时数组元素的个数必须明确指出,对于后面没有赋值的两个元素,也不用做任何说明。初始化只能针对所有元素或者从起始地址开始的前若干元素,而不能间隔赋初值。

【注意】
当指定的初值个数小于数组大小时,剩下的数组元素会被赋予0值。若定义数组时没有指定任何一个元素的初值,对于静态生存期的数组,每个元素仍然会被赋值为0;但对于动态生存期的数组,每个元素的初值都是不确定的。例如:
①静态生存期的数组

#include<iostream>
using namespace std;

int main()
{
	static int a[10]for (int i = 0; i < 10; i++)
	{
		cout << "a[" << i << "]=" << a[i]<<" ";
	}
	return 0;
}

运行结果:
在这里插入图片描述
②动态生存期的数组

#include<iostream>
using namespace std;

int main()
{
	int a[10];

	for (int i = 0; i < 10; i++)
	{
		cout << "a[" << i << "]=" << a[i] << ",";
	}
	cout << endl;
	return 0;
}

运行结果:
在这里插入图片描述
多维数组的初始化也遵守同样的规则。此外,如果给出全部元素的初值,第一维的下标个数可以不用显式说明,例如:

int a[2][3]={1,0,0,0,1,0};

等价于:

int a[][3]={1,0,0,0,1,0};

多维数组可以按第一维的下标进行分组,使用花括号将每一组的数据括起来。对于二维数组,可以分行用花括号括起来。下面的写法与上面的语句完全等效:

int a[2][3]={{1,0,0},{0,1,0}};

采用括号分组写法,容易识别,易于理解。

此外,数组也可以被声明为常量,例如:

const float fa[5]={1.0,2.0,3.0};

它表明fa数组中每个元素都被当作常量对待,也就是说它们的值在初始化后皆不可以改变。声明为常量的数组,必须给定初值。

3.数组作为函数参数

数组元素和数组名都可以作为函数的参数以实现函数间数据的传递和共享。

可以用数组元素作为调用函数时的实参,这与使用该类型的一个变量(或对象)作实参是完全相同的。

如果使用数组名作为函数的参数,则实参和形参都应该是数组名,且类型要相同。和普通变量做参数不同,使用数组名传递数据时,传递的是地址。 形参数组和实参数组的首地址重合,后面的元素按照各自在内存中的存储顺序进行对应,对应元素使用相同的数据存储地址,因此实参数组的元素个数不应该少于形参数组的元素个数。如果在被调函数中对形参数组元素值进行改变,主调函数中实参数组的相应元素值也会改变。

【例】使用数组名作函数参数。在主函数中初始化一个矩阵,并将每个元素都输出,然后调用子函数,分别计算每一行的元素之和,将和直接存放在每一行的第一个元素中,返回函数之后输出各行元素的和。

void rowSum(int a[][4],int nRow)
{
	for (int i = 0; i < nRow;i++)
	{
		for (int j = 1; j < 4; j++)
		{
			a[i][0] += a[i][j];
		}
		cout << "第" << i+1 << "行元素的和为:" << a[i][0] << endl;
	}
}

int main()
{
	int arr[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			cout<<arr[i][j]<<"     ";
		}
		cout << endl;
	}
	rowSum(arr, 2);

	return 0;
}

运行结果:
在这里插入图片描述
结果分析:
在子函数被调用之前,输出的arr[i][0]的值分别为1,2,3,而调用完成后arr[i][0]的值分别为10,14,18,也就是说在子函数中对形参元素的操作结果直接影响到函数实参的相应元素。

【注意】把数组作为函数参数时,一般不指定数组第一维的大小,即使指定,也会被忽略。

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

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

相关文章

全排列、子集、组合、子序列

全排列、子集、组合、子序列 1、全排列①回溯&#xff08;DFS&#xff09;交换法②回溯&#xff08;DFS&#xff09;选择法③ 插入法 2、子集①回溯选择法② 动态规划 ③ 位运算方式组合 1、全排列 全排列&#xff08;Permutation&#xff09;&#xff1a;全排列是指给定一组元…

【漏洞复现】Ruijie RG-BCR860 后台命令执行漏洞(CVE-2023-3450)

文章目录 前言声明一、简介二、漏洞概述三、影响版本四、环境搭建五、漏洞复现六、修复方式 前言 Ruijie RG-BCR860 2.5.13 版本存在操作系统命令注入漏洞&#xff0c;攻击者可通过该漏洞获取服务器敏感信息&#xff0c;导致服务器被沦陷。 声明 请勿利用文章内的相关技术从事…

git删除已经提交的大文件

当你不小心把一个巨大的二进制文件提交到git仓库的时候&#xff0c;此时删除再提交也没有用了&#xff0c;大文件已经在仓库中留底了。另外比如需要删除某个需要保密的文件&#xff0c;都是相同的解决办法。 我本来想着把dll放在三方库里面提交到仓库里&#xff0c;省得在不同…

入门级:路由器配置静态路由

软件&#xff1a;cicso packet tracer 8.0 拓扑图&#xff1a;路由器&#xff1a;Router-PT、连接线&#xff1a;Serial DTE、连接口&#xff1a;Serial口&#xff08;serial是串行口,一般用于连接设备,不能连接电脑&#xff09; 实验步骤&#xff1a; 1、构建拓扑图&#xf…

paddlenlp:社交网络中多模态虚假媒体内容核查

初赛之环境配置篇 一、背景二、任务三、数据集1、初赛阶段2、评分标准 四、环境操作五、写在最后 一、背景 随着新媒体时代信息媒介的多元化发展&#xff0c;各种内容大量活跃在媒体内中&#xff0c;与此同时各类虚假信息也充斥着社交媒体&#xff0c;影响着公众的判断和决策。…

re学习(27)攻防世界 re1-100

参考文章&#xff1a;攻防世界逆向高手题之re1-100_沐一 林的博客-CSDN博客 查壳&#xff1a; 用IDA打开&#xff0c;分析 编写脚本&#xff1a; d"{daf29f59034938ae4efd53fc275d81053ed5be8c}" d1d[1:11] d2d[11:21] d3d[21:31] d4d[31:41] print(d3d4d1d2) #…

我去,这是什么黑科技!用信号处理方法抑制瞬态噪声

对于语音增强来说&#xff0c;噪声一般可以分为稳态噪声&#xff08;如白噪声&#xff09;和瞬态噪声&#xff08;有的地方也叫非稳态噪声&#xff0c;如键盘声&#xff09;。如果对语音降噪有一定了解的读者会知道&#xff0c;一般的信号处理方法对稳态噪声比较有效&#xff0…

FreeIPA Server/Client不同版本组合,对podman rootless container的支持

FreeIPA Server/Client不同版本组合&#xff0c;对podman rootless container的支持 根据实验&#xff0c; CentOS 7.9 yum仓库自带的FreeIPA Server 4.6.8&#xff0c; ipa client版本支持CentOS 7.9 yum仓库自带的FreeIPA Client 4.6.8不支持subids&#xff0c;podman调用…

SqlServer2008如何解析Json—附详细代码

1、在数据库中创建存储过程parseJSON&#xff0c;具体文件请在如下链接下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1a-aNmSKk_yvv9wQTP3DCsg?pwdyxwx 提取码&#xff1a;yxwx 2、具体使用方法如下&#xff1a; DECLARE UserParameter NVARCHAR(MAX){"…

单元测试之 - Spring框架提供的单元/集成测试注解

Spring框架提供了很多注解来辅助完成单元测试和集成测试(备注&#xff1a;这里的集成测试指容器内部的集成测试&#xff0c;非系统间的集成测试)&#xff0c;先看看Spring框架提供了哪些注解以及对应的作用。RunWith(SpringRunner.class) / ExtendWith(SpringExtension.class)&…

无代码开发(BIP旗舰版-YonBuilder)

目录 我的应用 新建领域 菜单管理 应用构建 新建应用 对象建模 新增业务对象 新增业务实体 页面建模 新增页面 编辑页面 发布管理 我的应用 角色管理 yonbuilder开发平台&#xff0c;提供标准服务和专业开发服务&#xff1b; 本篇文章只演示标准服务的可视化应用…

软件外包开发的GO语言特点

Go语言&#xff08;也称为Golang&#xff09;是由Google开发的一种编程语言。它具有许多特点&#xff0c;使其成为许多项目范围的优秀选择。Go语言适用于需要高性能、并发和简洁易读的项目&#xff0c;特别是面向网络和分布式应用的项目。今天和大家分享项目的特点及适用的项目…

学习记录——TransNormerLLM、SRFormer、PLG-ViT、EfficientViT

关于Transformer Transformer 存在局限。首要的一点&#xff0c;它们有着对于序列长度的二次时间复杂度&#xff0c;这会限制它们的可扩展性并拖累训练和推理阶段的计算资源和时间效率。基于 Transformer的模型在提高窗口大小以优化性能的同时&#xff0c;也带来了相应的计算负…

刷完这个笔记,15K真的不能再少了....

大家好&#xff0c;最近有不少小伙伴在后台留言&#xff0c;得准备面试了&#xff0c;又不知道从何下手&#xff01;为了帮大家节约时间&#xff0c;特意准备了一份面试相关的资料&#xff0c;内容非常的全面&#xff0c;真的可以好好补一补&#xff0c;希望大家在都能拿到理想…

LVDS端口ESD静电放电保护电路图(经典)

Low Voltage Differential Signaling&#xff08;LVDS&#xff09;是一种低压差分信号技术接口&#xff0c;是美国NS公司为克服以TTL电平方式传输宽带高码率数据时功耗大、EMI电磁干扰大等缺点而研制的一种数字视频信号传输方式。LVDS端口电路包括两部分&#xff1a;驱动板侧的…

day50-springboot+ajax分页

分页依赖&#xff1a; <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency> 配置&#xff1a; …

spring — Spring Security 5.7与6.0差异性对比

1. spring security Spring Security 是一个提供身份验证、授权和针对常见攻击保护的框架。 凭借对保护命令式和反应式应用程序的一流支持&#xff0c;它成为基于Spring的标准安全框架。 Spring Security 在最近几个版本中配置的写法都有一些变化&#xff0c;很多常见的方法都…

Unity通过代码切换材质

效果展示 代码 using System.Collections; using System.Collections.Generic; using UnityEngine;public class MaterialSwitcher : MonoBehaviour {public Material newMaterial; // 新材质private Material oldMaterial; // 旧材质private Renderer renderer; // 渲染器组件…

C# Onnx Paddle模型 OCR识别服务

效果 项目 可运行程序exe下载 Demo&#xff08;完整源码&#xff09;下载

中小学分班查询系统如何制作?这个方法值得借鉴

暑假即将结束&#xff0c;新学年即将开始&#xff0c;学校面临着一个重要的任务&#xff0c;那就是学生的分班问题。这个问题涉及到新生入学的分班&#xff0c;以及低年级学生升入高年级时的分班。对于负责分班的老师们来说&#xff0c;这无疑增加了不少工作量和挑战。 在开学…