首页 > 其他分享 >走进数组的奇妙之旅

走进数组的奇妙之旅

时间:2024-07-19 22:30:05浏览次数:15  
标签:arr 之旅 int 元素 存储 奇妙 二维 数组

引言:

在前几篇文章中,我们深入探讨了函数的奥秘。在讲述函数知识的过程中,我们邂逅了一个新的概念,你或许还记得在演示 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. 文本处理:分析文本的二维结构,如表格形式的文本。

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


结语:

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

标签:arr,之旅,int,元素,存储,奇妙,二维,数组
From: https://blog.csdn.net/2401_85010100/article/details/140543423

相关文章

  • day 7二维整型数组、字符型数组
    二维整形数组1、二维整形数组的定义:    数据类型数组名[第一维数组的元素个数][第二维数组的元素个数];    数据类型数组名[行数][列数];    例如:inta[2][3];2、数组元素的访问:    数组名[行下标][列下表];    例如:a[0][......
  • day 8字符型二维数组、函数
    字符型二维数组作用:在C语言中字符型二维数组主要用来存放字符串数组1、定义:    数据类型数组名[第一维元素个数][第二维元素个数];例如:charstr[5][32];  2.元素访问:例如:str[0][0];或者  str[0]    3、数组存储的特性:    连续性:数......
  • 树状数组
    什么是树状数组顾名思义就是一个结构为树形结构的数组,于二叉树的结构类似但又不同,它是在二叉树的结构上删除了一些中间节点,来看两幅图就明白了.1.这是二叉树的结构 2.这是树状数组的结构 不难发现,树状数组相比于二叉树删除了一些节点,但是为什么要删除呢?这就和树状数组的......
  • java数组之数组工具类——Arrays的使用
    一、Arrays工具类简述    在java的类库中有许多现成的已经封装好的方法,可以供开发人员使用,比如我们之前学的二分法查找或者快速排序等。所以在实际的开发中,我们是不用自己编写这些常用的方法的。那么在常用的数组方法在哪里的?java作为面向对象的语言,所有方法都会封装......
  • 奇妙的 c++ 混合运算式
    先来看看如下的式子:a*b+c当你在c++中运行它时,你很清楚它是先计算*再计算+的。那么请再来看看这个式子:a+b+c请问它是先执行第一个+,还是先执行第二个+呢?这个问题看上去无解,但实际上我们可以解答:#definelllonglonginta=INT_MAX,b=INT_MAX;llc......
  • C语言_数组(1)
    一、一维数组1、数组的创建方式:数组是有限个相同类型数据元素的集合。type_t arr_name [const_n];//type_t是指数组的元素类型//const_n是一个常量表达式,用来指定数组的大小创建例子:注意:数组在创建时,[]里的必须是常量。但是如果编译器支持C99标准的话可以使用......
  • 《白话机器学习的数学》第1章——开始二人之旅
    1.1对机器学习的兴趣1.2机器学习的重要性    1.无论是过去还是现在,计算机都特别擅长处理重复的任务。所以计算机能够比人类更高效地读取大量的数据、学习数据的特征并从中找出数据的模式。这样的任务也被称为机器学习或者模式识别,以前人们就有用计算机处理这种任......
  • 【Linux】Linux进程揭秘:从理论到实践的深度探索之旅
    目录前言:操作系统简介概念设计目的理解进程:程序的执行之魂进程和程序的联系与区别 描述进程-PCB进程的标识符 进程状态 状态转换僵尸进程孤儿进程前言:操作系统简介概念操作系统(英语:OperatingSystem,缩写:OS)是一组主管并控制计算机操作、运用和运行硬件、软......
  • 合并排序数组
    合并排序数组(蓝桥杯题库)题目描述给定排序数组A和B,实现一个算法将B按排序顺序合并到A中。介绍如下:数组A和B的均为排序数组,数字按从小到大排列。数组A的的长度为 ......
  • 34.拷贝数组
    定义一个方法:copyOfRange(int[]arr,intx,inty)将数组arr中从索引x开始(包含x)到索引y结束(不包含y)中的元素,复制到新数组中,并将新数组返回例:原始数组arr={1,2,3,4,5,6,7,8,9},新数组newArr={4,5,6,7}publicstaticvoidmain(String[]args){//1.静态初始化定......