走进数组的奇妙之旅(1)

news2024/9/19 7:24:21

引言:

在前几篇文章中,我们深入探讨了函数的奥秘。在讲述函数知识的过程中,我们邂逅了一个新的概念,你或许还记得在演示 strcpy函数时,出现的这行代码:char1[20]={0};。当时,你是否感到好奇,心中是否升起了疑问:这是什么呢?没错,这正是我们本篇文章的主角——数组

在数字的世界里,数组就像是一座有序排列的宝库,它以一种简洁而高效的方式存储和管理着大量的数据。但你是否真正了解它的奥秘呢?让我们一起踏上探索数组的旅程吧!


1、一维数组

1.1 数组的创建

数组是一组相同类型元素的集合。

你可以这么理解什么是数组:想象一个书架,上面整齐地排列着同一类书籍,这就类似于一个数组。每本书的位置都是固定的,而且它们都属于同一类型(比如都是小说或者都是传记)。

在了解了什么是数组的情况下,我们又产生一个疑问,为什么要引入数组这个概念呢?

我们拿一个例子来解释一下:

存放一串整数,我们用代码可以怎么表示?

#include <stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = 3;
	//如果我们要存1~100个数字呢?
    //数组时一组相同类型的元素的集合
	return 0;
}

如果我们要存1~100的数字,难道我们就这样写下去吗?那也太麻烦了,这时数组就应运而生了!

当我们了解了为什么需要数组后,我们还需要知道该怎么使用它。

数组的创建方式:

type_t  arr_name    [const_n];
// type_t 是指数组的元素类型

// arr_name是指数组的名
// const_n 是一个常量表达式,用来指定数组的大小

比如说:

int arr[10];//整型数组,名为arr [10]指存放了10个元素
double data[20];
char ch[5];//字符数组,名为ch [5]指存放五个字符

也可以同时创建多个相同类型的数组

int arr 1 [10];
int arr 2 [2+8];

这里你或许还会有新的疑问, [ ] 这里面只能用常量或常量表达式吗? 

但是呢,并不是所有情况下都可以使用变量,比如

补充知识点:

在C99标准之前,数组的大小必须是常量或者常量表达式;

在C99之后,数组的大小可以是变量,这是为了支持变长数组;

变长数组的意思是 数组的大小是通过变量来指定的。

上图中的代码想要实现该怎么办呢?

#include <stdio.h>
int main()
{	
    int n = 10;
    scanf("%d",&n);
	int arr[n];	
	return 0;
}

但是呢,这里还有一个限制条件,就是只能在支持C99标准的编译器上编译

支持C99的编译器:

  • GCC:GNU Compiler Collection 的缩写,它在其编译器集合中提供了 C 编译器,支持 C99 标准。GCC 是一款广泛使用的开源编译器。
  • Clang:基于 LLVM 的 C 编译器,支持 C11 标准,同时也对 C99 有较好的支持。
  • Intel C++ Compiler:英特尔的 C++编译器,也支持 C99 标准。
  • Keil:在 Keil 编译器中,可通过相关设置使其支持 C99(变量声明在执行语句之后)。具体操作是在“Options for Target”中的“C/C++”选项卡下,勾选“C99 Mode”。

1.2 数组的初始化

数组的初始化:在创建数组的同时给数组的内容一些合理初始值(初始化)。

直接代码演示:

int arr1[10] = { 1,2,3 };//不完全初始化,剩余的元素,默认初始化为0
int arr2[] = { 1,2,3,4 };
int arr3[5] = { 1,2,3,4,5 };//完全初始化
char arr4[3] = { 'a',98,'c' };
char arr5[] = { 'a','b','c'};
char arr6[] = { "abcdef" };//[]括号里面也是可以不指定大小的

注意:

1. 不完全初始化(所给元素比指定元素要少),剩余的元素,默认初始化为 0;

2. 括号[ ]里面是可以不指定大小的,这样的话该数组大小(指定值)就等于所给的元素(初始化)。

数组在创建的时候如果不想不指定数组的确定的大小就得初始化。数组的元素个数根据初始化的内容来确定。

但是对于下面的代码要会区分,内存中如何分配。

char arr1[10] = { 'a','b','c'};
char arr2[10] = { "abc" };

对于arr1,里面的字符为:a b c 0 0 0 0 0 0 0

对于arr2,里面的字符为:a b c \0 0 0 0 0 0 0

1.3 一维数组的使用

对于数组的使用,我们要介绍了一个操作符: [ ] , 下标引用操作符。它其实就是数组访问的操作符。

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };	
	//编号        0 1 2 3 4 5 6 7 8 9
    //编号是0开始的,这里的编号就是数组的下标       
	printf("%d\n", arr[4]);
	return 0;
}

   打印结果是:

 图中可知打印 arr[4]的结果,我们可以得到整数5

使用下标引用操作符arr[i]来访问数组中索引为 i 的元素。

如果我们想把数组的内容全部打印出来,那么范围该怎么确定?

范围不需要我们计算,使用sizeof函数会自动帮我们计算范围。

代码如下:

int main()
{
	int arr[] = { 1, 2, 3 ,4 ,5 ,6, 7,8 ,9,10 };	
	//下标范围    0                        9         
	//printf("%d\n", arr[4]);
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);//自动计算范围 左边计算的时总数组的大小  右边的是第一个元素大小
	for (i = 0; i < sz; i++)//正序打印
	{
		printf("%d ", arr[i]);//i是0时打印1,i是1时打印2...
	}
    for(i = sz-1;i >= 0;i--)//倒序打印
    {
        printf("%d ", arr[i]);
    }
	return 0;
}

  下标用来定位数组

注意;使用下标引用操作符时,一定要确保索引值在有效范围内,否则可能导致访问越界错误。

总结:

1.数组是使用下标来访问的,下标是从0开始的。

2.数组的大小可以通过计算得到。                                                    

int sz = sizeof(arr) / sizeof(arr[0]);//计算公式

1.4 一维数组在内存中的存储

数组在内存中是连续存储的,这意味着数组中的元素在内存中是一个紧挨着一个排列的。

 比如说,有一个整数类型的一维数组 int arr[5] = {1, 2, 3, 4, 5} 。

注:地址是16进制的

在 C 语言中,一个整数通常占用 4 个字节的内存空间。

假设这段连续存储空间的起始地址为 0*1000 ,由于在 C 语言中,一个整数通常占用 4 个字节的存储空间。那么,数组中的第一个元素将被存储在地址 0*1000 ,第二个元素紧接着存储在地址 0*1004 ,第三个元素在 0*1008 ,第四个元素在 0*100C ,第五个元素则在 0*1010 。

这种连续存储有两个重要的特点和影响:

一方面,它使得随机访问数组元素的速度非常快。比如说,如果想要获取第三个元素,只需要通过简单的计算 起始地址 + 元素大小 * 索引 (也就是 1000 + 4 * 2 = 1008 ),就能直接找到并访问到第三个元素 3 ,几乎不需要额外的时间去查找。

另一方面,它也带来了一些不便。比如说,如果要在数组中间插入一个新元素,那就需要把插入位置后面的所有元素都向后移动,以腾出空间插入新元素。这是一个比较耗时的操作。同样,删除数组中间的元素时,也需要把后面的元素向前移动来填补空缺。

为了更加直观的解释,我们来用表格辅助理解:

假设有一个整数数组int num[3] = {10,20,30 } ,其在内存中的存储情况如下:

内存地址存储的值
0 * 200010
0 * 200420
0 * 200830

如果现在要在第二个位置插入一个新元素 15 ,那么原有的 20 和 30 都需要向后移动 4 个字节,变成:

内存地址存储的值
0 * 200010
0 * 200415
0 * 200820
0 * 200C30

同样,如果要删除第二个元素 15 ,则 20 和 30 需要向前移动:

内存地址存储的值
0 * 200010
0 * 200420
0 * 200830

综上所述,C 语言中一维数组在内存中的连续存储方式在提供快速随机访问的同时,也在插入和删除操作上带来了一定的复杂性。

当我们知道这一特点后,有助于我们在编程实践中根据具体需求合理地选择和使用数组,或者考虑其他更适合特定操作的数据结构。

所以,理解 C 语言中一维数组在内存中的连续存储方式,对于我们有效地使用数组、优化程序性能以及避免一些常见的错误(比如内存越界访问)都非常重要。

代码展示:

int main()
{
	int arr[] = { 1, 2, 3 ,4 ,5 ,6, 7,8 ,9,10 };	
	//下标范围    0                        9         
	//printf("%d\n", arr[4]);
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	//打印数组的每个元素的地址
	for (i = 0; i < sz; i++)
	{
		printf("&arr[%d] = %p\n",i, &arr[i]);
	}
	return 0;
}

结果展示:

随着数组下标的增加,元素的地址,也在有规律的递增。

2、二维数组

二维数组可以看作是由多个一维数组组成的数组

2.1 二维数组的创建

//数组创建
int arr[3][4];
char arr[3][3];
double arr[1][2];
//3 2 1
//1 2 3
//3 1 2
int main()
{
	int arr[3][3];
	return 0;
}

2.2 二维数组的初始化

int main()
{
	int arr[3][3] = { 3,2,1,1,2,3,3,1,2 };//完全初始化
	return 0;
}

这样排列元素,会先找前三个放在第一行,再找三个放在第二行,最后三个放在第三行。也就是会按顺序放 

如果所给的元素不够怎么办?

int main()
{
	int arr[3][3] = { 3,2,1,1,2,3,3};//不完全初始化
	return 0;
}

 

 我们可以看到少的位置被自动补上了 0 

我们还有另一种方法排放元素

int main()
{
	int arr[3][3] = { { 3,2},{1,1},{2,3} };//不完全初始化
	return 0;
}

如果数据不够的时候,我们可以按照分小组的方法,把想要的数据放在适当的位置。

二维数组如果有初始化,行可以省略,列不能省略

int arr[ ][4] = {{1,2},{3,4}};

2.3 二维数组的使用

代码展示: 

#include <stdio.h>
int main()
{
	int arr[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
	int i = 0;
	for (i = 0;i < 3; i++)//确定行
	{
		int j = 0;
		for (j = 0; j < 4; j++)//确定列
		{
			printf("%d", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

 结果展示:

也可以打印其中的单个元素

printf("%d\n",arr[2][0]);
//结果:3

2.4 二维数组在内存中的存储

二维数组可以理解为:一维数组的数组

在 C 语言中,二维数组在内存中是按照行优先(row-major order)的方式连续存储的。

假设我们有一个二维数组 int arr[2][3] ,其在内存中的存储方式类似于将其看作一个一维数组。 先存储第一行的所有元素,然后再存储第二行的元素。

也就是说,内存中元素的排列顺序是 arr[0][0] 、 arr[0][1] 、 arr[0][2] 、 arr[1][0] 、 arr[1][1] 、 arr[1][2] 。

以具体的内存地址为例,如果 arr[0][0] 的地址为 1000 ,且每个 int 类型占用 4 个字节,那么 arr[0][1] 的地址就是 1004 , arr[0][2] 的地址是 1008 , arr[1][0] 的地址是 1012 ,依此类推。

这种连续存储的方式使得可以通过简单的地址计算来快速访问二维数组中的元素。

但需要注意的是,在处理二维数组时,要确保索引不越界,以免访问到非法的内存地址导致程序出错。

2.5 二维数组的实际应用

二维数组在实际编程中有许多应用场景,以下是一些常见的例子:

1. 图像处理:可以用来存储图像的像素信息,其中行和列分别对应图像的高度和宽度。 - 例如,灰度图像可以用二维数组存储每个像素的灰度值。

2. 矩阵运算:如线性代数中的矩阵相加、相乘等操作。 - 在科学计算、机器学习和数值分析中经常用到。

3. 电子表格:类似于 Excel 中的表格数据,可以用二维数组表示行和列的数据。

4. 地图表示:将地图划分为网格,用二维数组存储每个网格的相关信息,如地形、资源等。

5. 游戏开发: - 表示游戏中的棋盘、地图布局。 - 存储游戏中多个角色的位置和状态。

6. 座位安排:例如在会议室、教室等场景中安排座位。

 7. 文本处理:分析文本的二维结构,如表格形式的文本。

这些只是二维数组的一些常见应用场景,实际上,只要数据具有二维的特性并且需要进行批量处理,都可以考虑使用二维数组来进行存储和操作。


结语:

本篇文章即将落下帷幕,在这篇文章中,我们共同探索了一元数组与二元数组的奥秘。在下篇文章中,我们将继续深入挖掘数组知识的精髓,期待您的持续关注与阅读。让我们共同期待,在知识的海洋中,不断探索,不断前行。

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

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

相关文章

前端组件化实践:Vue自定义加载Loading组件的设计与实现

摘要 随着前端技术的飞速发展&#xff0c;组件化开发已成为提高开发效率、降低维护成本的重要方法。本文介绍了前端Vue自定义加载Loading组件的设计思路与实现过程&#xff0c;该组件通过设置gif动画实现加载效果&#xff0c;可广泛应用于页面请求加载场景。通过该组件的实践&…

银行业务知识全篇(财务知识、金融业务知识)

第一部分 零售业务 1.1 储蓄业务 4 1.1.1 普通活期储蓄(本外币) 4 1.1.2 定期储蓄(本外币) 5 1.1.3 活期一本通 9 1.1.4 定期一本通 10 1.1.5 电话银行 11 1.1.6 个人支票 11 1.1.7 通信存款 13 1.1.8 其他业务规…

解决AI训练中的“Convergence Warning”报错:提高模型稳定性 ️‍♂️

解决AI训练中的“Convergence Warning”报错&#xff1a;提高模型稳定性 &#x1f3cb;️‍♂️ 解决AI训练中的“Convergence Warning”报错&#xff1a;提高模型稳定性 &#x1f3cb;️‍♂️摘要引言“Convergence Warning”报错的成因分析 &#x1f914;1. 学习率设置不当2…

昇思学习打卡-23-生成式/CycleGAN图像风格迁移互换

文章目录 模型介绍网络结构数据集可视化网络的其他细节模型推理 模型介绍 CycleGAN(Cycle Generative Adversarial Network) 即循环对抗生成网络&#xff0c;实现了一种在没有配对示例的情况下学习将图像从源域 X 转换到目标域 Y 的方法。 该模型一个重要应用领域是域迁移(Do…

VMware中Ubuntu磁盘空间的清理

最近发现Ubuntu占用空间过大&#xff0c;在网上找了一些方法&#xff0c;在这里总结一下。 1.删除快照 把不需要的快照删除&#xff0c;但要注意删除快照可能会影响到后续的快照链。每个快照依赖于前面的快照。如果删除一个中间快照&#xff0c;虚拟机可能无法找到完整的差异…

谷粒商城实战笔记-36-前端基础-Vue-介绍HelloWorld

文章目录 一&#xff0c;MVVM 思想直接操作DOM的示例使用Vue和MVVM的示例MVVM与DOM操作的主要区别 二&#xff0c;Vue 简介三&#xff0c;第一个Vue项目1 新建项目2 安装依赖3 使用Vue 这一节的主要内容是演示Vue的简单使用。 一&#xff0c;MVVM 思想 M&#xff1a;即 Model…

基础vrrp(虚拟路由冗余协议)

一、VRRP 虚拟路由冗余协议 比如交换机上联两个路由器&#xff0c;由两个路由虚拟出一台设备设置终端设备的网关地址&#xff0c;两台物理路由的关系是主从关系&#xff0c;可以设置自动抢占。终端设备的网关是虚拟设备的ip地址&#xff0c;这样&#xff0c;如果有一台路由设备…

c++模板初识

目录 一、 泛型编程 二、 函数模板 1.函数模板概念 2.函数模板格式 3.函数模板的原理 4.函数模板的实例化 1. 隐式实例化&#xff1a;让编译器根据实参推演模板参数的实际类型 2.显式实例化&#xff1a;在函数名后的<>中指定模板参数的实际类型 5.模板参数的…

万物互联时代,手机丢了我们该怎么办?

万物互联时代&#xff0c;我们的手机丢了该怎么办&#xff1f;全身家当都在一部手机里&#xff0c;这个时候我们更要冷静&#xff0c;然后先尝试着打电话、发短信、定位找手机。 如果实在找不到的话&#xff0c;先借个电话号码把以下四件事给做好&#xff1a; ①挂失手机号&am…

《昇思25天学习打卡营第21天|Pix2Pix实现图像转换》

Pix2Pix 是一种图像转换模型&#xff0c;使用条件生成对抗网络&#xff08;Conditional Generative Adversarial Networks&#xff0c;cGANs&#xff09;实现图像到图像的转换。它主要由生成器&#xff08;Generator&#xff09;和判别器&#xff08;Discriminator&#xff09;…

【UE5.1】NPC人工智能——04 NPC巡逻

效果 步骤 一、准备行为树和黑板 1. 对我们之前创建的AI控制器创建一个子蓝图类 这里命名为“BP_NPC_AIController_Lion”&#xff0c;表示专门用于控制狮子的AI控制器 2. 打开狮子蓝图“Character_Lion” 在类默认值中将“AI控制器类”修改为“BP_NPC_AIController_Lion” 3…

数据编织 Data Fabric:解决“数据孤岛”的新思路

一个不争的事实是&#xff0c;企业内部数据孤岛的形成&#xff0c;根因在于业务发展的复杂性与技术迭代的快速性导致。具体而言&#xff0c;随着企业业务快速增长&#xff0c;如新生产线的引入或外部公司的并购&#xff0c;这些活动往往伴随着新系统上线与独立数据体系的融入&a…

AI算法24-决策树C4.5算法

目录 决策树C4.5算法概述 决策树C4.5算法简介 决策树C4.5算法发展历史 决策树C4.5算法原理 信息熵&#xff08;Information Entropy&#xff09; 信息增益&#xff08;Information Gain&#xff09; 信息增益比&#xff08;Gain Ratio&#xff09; 决策树C4.5算法改进 …

产品经理-工作中5大类技术名词解析(19)

在产品经理与开发的团队协作中,如果自己知道一些专业术语,对业务的开展是有帮助的&#xff0c;很多时候,在沟通过程当中,就是因为自己不懂,所以才不知道怎么去做,想要什么样的结果 在力所能及的情况下,平时,多了解一些专业术语,是有好处的 数据结构 数据结构是技术人员将数据进…

LeetCode——被管绕的区域

题目描述 给你一个 m x n 的矩阵 board &#xff0c;由若干字符 X 和 O 组成&#xff0c;捕获 所有 被围绕的区域&#xff1a; 连接&#xff1a;一个单元格与水平或垂直方向上相邻的单元格连接。区域&#xff1a;连接所有 O 的单元格来形成一个区域。围绕&#xff1a;如果您可…

数据库系统概论:事务与并发一致性问题

随着网络应用的普及&#xff0c;数据库并发问题变得越来越重要。数据库并发指的是多个用户或进程同时访问和操作数据库的能力。它是数据库系统性能优化的重要方面&#xff0c;旨在提高系统的吞吐量和响应时间&#xff0c;以满足多用户同时访问数据库的需求。然而&#xff0c;这…

GPT-4o模型开通使用教学,解除使用限制【Outlook版】

OpenAI的GPT-4o模型免费用户都可以使用&#xff0c;但是遗憾的是每三小时可以使用十次问答。 但是还是有好多同学连使用都不会&#xff0c;今天这篇文章教会你如何使用并解除使用限制。 大家可以使用Outlook邮箱。 打开outlook官网选择中间获得免费账户。 ​ 在接下来的邮…

AGI 之 【Hugging Face】 的【零样本和少样本学习】之一 [构建标记任务] / [ 基线模型 ] 的简单整理

AGI 之 【Hugging Face】 的【零样本和少样本学习】之一 [构建标记任务] / [ 基线模型 ] 的简单整理 目录 AGI 之 【Hugging Face】 的【零样本和少样本学习】之一 [构建标记任务] / [ 基线模型 ] 的简单整理 一、简单介绍 二、零样本学习 (Zero-shot Learning) 和少样本学习…

【Qt】常用控件

文章目录 QWidgetenabledgeometrywindow framewindowTitlewindowIconqrc资源管理windowOpacitycursorfonttoolTipfocusPolicystyleSheet 按钮类PushButtonRadioButtonCheckBoxSignals 显示类LabelLCDNumberProgressBarCalendar 输入类LineEditTextEditComboBoxSpinBoxDateTimeE…

55 、mysql的存储引擎、备份恢复以及日志备份、恢复

一、数据库的存储引擎&#xff1a; 1.1、存储引擎的概念 概念&#xff1a;存储引擎&#xff0c;就是一种数据库存储数据的机制&#xff0c;索引的机制&#xff0c;索引的技巧&#xff0c;锁定水平。 存储的方式和存储的格式。 存储引擎也属于mysql当中的组件&#xff0c;实…