初识C语言数组(带你全面玩转C语言数组)

1.前言😃

Hi,大家好👏。这篇算是我真正意义上的第一篇博客,为大家介绍C语言数组的相关知识。

在CSDN上我搜索查看了数组相关内容,部分内容我认为还是没有介绍完全,所以我今天通过这篇博客向家人们简要介绍数组的相关内容,在最后会附加几个典型的数组习题代码供大家练手查看,体会数组相关知识。

如果家人们觉得不错的话,防止刷着刷着就找不到了,记得点个赞加收藏啊,谢谢家人们!✌✌✌
在这里插入图片描述

2.一维数组🎈

2.1一维数组的创建🌵

在介绍数组之前我们先引入数组的概念>>
数组:数组是一组有序数据的集合,数组中每一个元素都属于同一个数据类型
简单来说,数组是一组相同类型元素的集合

type_t arr_name [const_n]
//type_t是数组类型,可以是int、double、float、char等
//arr_name是数组名称
//const_n是常量表达式 
#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int arr[10];//整型类型
	double arr[10];//浮点类型
	float arr[10];//浮点类型
	char arr[10];//字符类型
	return 0;
}
创建数组的时候,数组大小是10.

那么创建数组的时候是否可以将指定数组大小的常量表达式变成整型变量呢?
接下来引入变长数组的概念与写法。🤦‍♂️

//变长数组:指用整型变量或表达式定义的数组
//变长数组的创建:
#include<stdio.h>
int main()
{
  int n=10;
  int arr[n];
  return 0;
}

变长数组的写法在C99标准之后才支持,而在C99之前则是不支持的!所以大家测试的时候部分编译器会进行报错,这个是正常现象,大家了解这个变长数组的概念即可!

2.2一维数组的初始化🌵

#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
//整型数组
    //对数组全部元素赋予初值
	int arr[5] = { 1, 2, 3, 4, 5};
	//对数组部分元素赋予初值,未赋值的元素系统自动赋值为0
	int arr1[5] = {1, 2, 3};
	//由于数据个数已经确定,可不指定数组长度,系统会自行分配
	int arr2[] = { 1, 2, 3, 4, 5};
//字符数组
    //同int类型一样,系统会根据字符个数自动分配数组长度
	char arr3[] = { 'a','b','c' };
	//值得注意的是,C语言中字符串是作为字符数组来进行处理的
	char arr4[] = "abc";
	//处理字符串时,一般不需要指定数组大小,直接让系统进行分配
	//与单个字符数组不同的是,字符串末尾会加上'\0'作为结束标志,所以上面的字符串的字符数组实际空间是4
}

通过监视,我们很好的看到了上面定义的5个数组中的内容
在这里插入图片描述

2.3一维数组的引用🌵

通过上面的数组的创建和初始化之后,那么数组是如何引用的呢?

数组的引用:数组名[下标],[ ]叫做下标引用操作符
值得注意的是:只能引用单个数组元素而不能一次整体调用整个数组的全部的元素值,所以需要访问数组所有的元素时,通过for、while等循环即可

拓展:前面提到[]是操作符,所以它的操作数是数组名和索引值。

#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4 };
	printf("%d\n", arr[3]);
	printf("%d\n", 3[arr]);
	return 0;
}
//此时arr[3]=3[arr]=4;可以正常打印输出

下面代码则是引用数组,给各个数组元素赋予初值并打印,在此不进行赘述
在这里插入图片描述在数组引用中,要清楚数组是通过下标来进行访问的。若数组n个元素,那下标从0开始,到(n-1)结束

2.4一维数组在内存中的存储🌵

通过前三部分的介绍相信家人们对于数组已经有了一定的认识,那么数组在内存中是如何进行存储的呢?在内存中是连续存放还是跳跃性存放的呢?

在这我们在这可以创建数组,通过%p来打印每一个数组元素的地址,来观察数组元素的存储情况:在这里插入图片描述
✨✨✨
我们创建i的nt 型数组,而int类型元素占4个字节,因为数组中一共有10个元素,所以该数组在内存中占40个字节。编译器用16进制表示,所以我们很容易看到打印出来每个元素的地址是差4的。

👇👇👇👇
以上很轻易得出结论:数组在内存中是连续存放的。随着数组元素下标的增长,数组元素的地址也是有规律递增的。

2.5一维数组的越界🌵

我们接着数组引用的代码,将打印数组元素的for循环进行改动,代码与运行结果如下:
在这里插入图片描述
由上述数组引用我们了解到,数组从下标为0的元素开始访问,到下标为(n-1)的元素停止。若数组下标增大到n,即访问下标为n的元素arr[n],即表示数组越界,此时编译器不报错,由上图可以看到,最后一个元素为随机值,这种情况就被称为数组越界。

2.6strlen()和sizeof()🌵

在介绍二维数组前,引入操作符sizeof()和库函数strlen(),后续编写代码时会利用sizeof()和strlen()进行数组大小的计算继而引用数组

2.6.1sizeof()的使用🧗‍♂️

sizeof():是C语言操作符的一种,计算代码中某一类型字节的大小,反映了该类型变量所占内存的大小,单位是字节。
在这里插入图片描述
💡在使用sizeof计算字符数组时,因为char类型占1个字节,所以在计算单个字符组成的数组时返回的就是字符的个数,也就是字节的个数,上图arr2[]即是这种情况,字节数是6

💡 值得注意的是,在计算字符串形成的字符数组时,因为字符串结束的标志是’\0’,所以返回字节个数时也包括了’\0’。上图打印输出了字符串型的字符数组arr3[],字节数是7

✨✨✨
当然sizeof()的用法有很多,也可以计算int、float、double、char、指针等字节大小,在这不多进行介绍,有兴趣的可以自行上机验证

2.6.2strlen()的使用🧗‍♂️

strlen():计算字符串长度的一个库函数,使用时需要引用库函数#include<string.h>,在计算字符串长度时不计算’\0’,只计算’\0’之前字符的个数。
在这里插入图片描述
💡前面提到strlen()计算’\0’前字符的个数,所以在使用strlen()计算单个字符形成的数组时,因为arr2[]没有给出’\0’,所以打印输出arr2[]数组字符个数时会产生一个随机值,所以strlen()要正确使用!!!

char arr1[] = "abcdef";
char arr2[] = { 'a','b','c','d','e','f','\0'};
//此时arr1[]与arr2[]等价

💡 这是因为编译器会在该字符数组预开辟空间中找到’\0’才会停止,所以才会产生随机值。这个在此不多进行赘述,了解即可

3.二维数组🎈

3.1二维数组的创建与初始化🌵

与一维数组一样,二维数组也是存放类型相同的元素。通常,二维数组被称为矩阵

int arr1[2][3] = {1,2,3,4,5,6};//顺序赋值
int arr2[2][3] = { {1,2,3},{4,5,6} };//按行赋值
//arr1与arr2等价

int arr3[2][3] = { 1,2,3,4 };//1 2 3 4 0 0
int arr4[2][3] = { {1,2},{3,4} };//1 2 0 3 4 0
//部分元素赋初值,未赋初值自动为0

int arr5[][3] = { 1,2,3,4,5,6 };//1 2 3 4 5 6
int arr6[][3] = { 1,2,3,4 };//1 2 3 4 0 0
//列不可以省略,行可以省略,系统会根据元素个数及列数赋初值

int arr7[2][3] = { {},{4,5,6} };//0 0 0 4 5 6
int arr8[][3] = { {},{4,5,6} };//0 0 0 4 5 6

以上是二维数组基本的初始化和赋值方式,已经基本将赋值的各种类型和情况罗列出来,大家自行体会。或在IDE上编写调试监视可直观地观察数组元素样式

👇👇👇
顺带提一下,二维数组可以看成一维数组的组合,它的元素是一个一维数组。

int arr[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
-->a[0]----a[0][0] a[0][1] a[0][2] a[0][3]
-->a[1]----a[1][0] a[1][1] a[1][2] a[1][3]
-->a[2]----a[2][0] a[2][1] a[2][2] a[2][3]
//可以把a[0]、a[1]、a[2]看成一维数组的名字

我们不妨进行调试监视:
在这里插入图片描述

3.2二维数组的引用🌵

与一维数组一样,同样是通过下标进行数组引用,在这不进行赘述,下面附一个代码练习自行体会。

💡Question
下面是一个3*4的一个矩阵,找出其中的最大值,并输出其所在的行和列。

#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int i = 0, j = 0;
	int arr[3][4] = { {1,2,3,4},{9,8,7,6},{-10,10,-5,2} };
	int row, col;
	int max = arr[0][0];
	for (i = 0; i < 3; i++)//遍历行
	{
		for (j = 0; j < 4; j++)//遍历列
		{
			if (max < arr[i][j])
			{
				max = arr[i][j];
				row = i;
				col = j;
			}
		}
	}
	printf("max=%d\nrow=%d\ncol=%d\n", max,row,col);
	return 0;
}

3.3二维数组在内存中的存储🌵

在了解到一维数组在内存中的存储方式是连续存储的,那二维数组的存储方式呢?是与一维数组一样连续存储还是按矩阵二维方式进行存储的呢?

看下图:
在这里插入图片描述
👇👇👇
由调试结果很明显可以看出在二维数组里,每个单元地址差4个字节,所以得出二维数组中数据也是线性存储的,不是二维的,这点务必明确!!!

4.习题🎈

以上就是数组的基础内容已经基本提出来了,大家可以根据C语言课本进行比对参考。

当然二维数组也存在char、bool类型,在这不进行列举,下来介绍几种C数组习题,熟悉上面所提内容。

4.1斐波那契数列🌵

在分支循环结构中,我们了解到斐波那锲数列,那在数组中则可以更好的解决该问题。

//本代码只打印前20项,所以数组长度定义为20
#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int i = 0;
	int arr[20];
	arr[0] = 1;
	arr[1] = 1;
	for (i = 2; i < 20; i++)
	{
		arr[i] = arr[i - 1] + arr[i - 2];
	}
	for (i = 0; i < 20; i++)
	{
		if (i% 5==0) printf("\n");
		printf("%12d", arr[i]);
	}
}

4.2冒泡排序🌵

如下图所示,存在5个无序的数字,那么如何将这5个数字从小到大排列呢?
在这里插入图片描述

💡💡💡
在图片可以清晰看到,每两个相邻的数在进行互相交换位置,在第一次比较当中40>8,所以两两交换位置,第二次比较40>15,同理位置进行交换,所以当前一个数大于后一个数时它们俩的位置进行交换。依照这个思路重复进行交换,最终40"沉底",较小的数"上浮",第一趟比较随之结束,此时40这个最大值沉底,在这个过程中比较了4次。

当第1趟比较结束后,我们从上图可以清楚的看出除40外,其他4个数的大小顺序依然是乱的。所以根据上面相同的思路,我们对除40这个数以外的其余4个数再次进行上面相同方法进行第2趟排序,此时这4个数比较3次后即可。不断重复这个过程,第3趟3个数比较2次,第4趟2个数比较1次。


👇👇👇
所以我们轻松地可以推出这个结论:冒泡排序中,如果有n个数,则进行n-1趟排序,第i+1趟排序进行n-1-i次(i从0开始)
代码实现如下:

#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int i = 0, j = 0;
	int arr[] = { 34,67,90,43,124,87,65,99,132,26 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//sz利用sizeof计算数组大小,即40(字节)/4(字节)=10;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz-1-i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int t = arr[j+1];
				arr[j + 1] = arr[j];
				arr[j] = t;
			}
		}
	}
	//打印
	for (i = 0; i < sz; i++)
	{
		printf("%-4d", arr[i]);
	}
	return 0;
}

5.结束🎈

Ending,数组的基本内容就介绍到这里,相信家人们对于数组也都有了一定的认识😀。因为篇幅有限,本文对于sizeof()和strlen()未列举太多实例供大家参考,所以如果不清楚的话,大家可以自行上机验证。本次的博客分享就到这结束了,如果大家感觉不错的话,记得收藏点赞啊。有问题的话留言区评论提出哦🎉

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kkkkvvvvvxxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值