C语言之数组

引:在日常应用中,可能会遇到需要存放很多数据的情况,比如你要存放1—100,这时候可以用到数组。

1.数组的概念:一类相同类型的集合

接下来是重点:数组存放的是一个或多个数据,但是数组的元素不能为0。数组存放的多个数据类型是相同的。而数组分为一维数组和多为数组,多维数组比较常见的是二维数组。

一维数组的创建基本语法形式:type arr_name[常量值],类型+数组名+中括号。

在创建时可以自己定义数组的大小和类型,类型可以是内置的类型,甚至可以是自定义的类型,例如你要存放5个整型常量,就可以 int arr[5];

上图就是这个数组,可以存放5个整型,每个格子代表一个元素。 

2.数组的初始化:数组的初始化一般使用大括号,将数据放到大括号里面。

完全初始化:int arr1[5] = { 1,2,3,4,5 };

不完全初始化:int arr2[5] = { 1 };//第一个元素初始化为1,剩余的元素初始化为0

错误的初始化:int arr3[4] = { 1,2,3,4,5 };//初始化的项太多

接下来关于数组类型的理解。int a表示a的类型是个整型,那么int arr[10]就表示数组的类型是整型吗?答案为否。int是元素的类型,对于整型变量来说去掉名字就是类型,那么对于数组来说,去掉数组名就是类型,即 int arr[10]的类型是int [10]。听上去有点扯,可就是这样。

OK有个灵魂拷问,就是 int arr[5]和 int arr[6]两者的类型是否一样,答案是否,因为一个是int [5],

一个是int [6],所以我们说数组也是一种自定义类型,当元素个数和元素类型不一样,数组类型就不一样。

3.一维数组的使用:首先介绍一个非常重要的概念,就是数组的下标,C语言规定数组下标从0开始,假设有n个元素,数组最后一个元素下标就是n-1,下标就相当于数组的编号。

在存放数据时,数组向内存申请一块空间,然后我们要去访问这个数组当中的元素时,就需要用到下标引用操作符([]) ,在此操作符中输入相应的下标就可以访问了。接下来尝试打印数组里面所有的元素:首先要打印每个元素,就要产生出相应的下标,就可以利用循环产生0~n-1的下标。

#include <stdio.h>
int main()
{
	int arr[5] = { 1,2,3,4,5 };
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

如果是要把数据存储在数组里面:

#include <stdio.h>
int main()
{
	int arr[5] = { 0 };
	for (int i = 0; i < 5; i++)
	{
		scanf("%d ", &arr[i]);
	}
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 arr[i]表示这是一个元素,不是地址,所以前面要加&。另外,有时候在创建数组的过程中 可能会出现int arr[]={0};的情况,这时候数组的大小就由初始化的后面的内容决定,就是说如果我是int arr[]={1,2,3,4,5},就相当于【】里面的数字大小是5,如果是 int arr[]={0},就相当于【】里面的是1。

4.一维数组在内存中的存储:首先可以打印每个元素的地址

#include <stdio.h>
//%p是专门来打印地址的
//以16进制的形式打印,同时最前面的0不会打印
int main()
{
	int arr[10] = { 0 };
	for (int i = 0; i < 10; i++)
	{
		printf("&arr[%d] = %p\n", i, &arr[i]);
	}
	return 0;
}

x86环境下打印出来的结果 

 可以看出,每个元素之间的地址差了4个字节,而且一个整型是4个字节,每个元素都是整型 ,由此我们大概可以推断出一维数组在内存中是连续存放的。如果我们知道了它是连续存放的话,那么我们只要知道起始位置的地址,就可以一直找到这后面的元素的地址,这样做的意义其实与后面所要学习的指针会有所联系。

5.sizeof计算数组元素的个数:sizeof是C语言中的一个关键字,可以用来计算类型或者变量的大小,也可以计算数组的大小.


#include <stdio.h>
int main()
{
	int arr[5] = { 1,2,3,4,5 };
		printf("%zd", sizeof(arr));
	return 0;
}

 由此可知,sizeof计算的是数组所占字节的大小,那么就可以求一个元素的大小了,

#include <stdio.h>
int main()
{
	int arr[5] = { 1,2,3,4,5 };
		printf("%zd\n", sizeof(arr));
		printf("%zd", sizeof(arr[0]));
	return 0;
}

 现在一个多大知道了,总的多大知道了,那么不就可以计算元素的个数了吗?

#include <stdio.h>
int main()
{
	int arr[5] = { 1,2,3,4,5 };
		printf("%zd\n", sizeof(arr));
		printf("%zd\n", sizeof(arr[0]));
		printf("%zd", sizeof(arr)/sizeof(arr[0]));
	return 0;
}

 strlen只能针对字符串,求字符串的长度,与sizeof还是有区别的。OK那么以后就可以使用sizeof来打印或者输入字符串。

#include <stdio.h>
int main()
{
	int arr[5] = { 1,2,3,4,5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 6.二维数组:一维数组的元素都是内置类型的,如果把一维数组作为数组的元素,这时候就是二维数组。它的创建方式为:type arr_name[常量值1][常量值2],例如int arr[3][4]表示三行四列的二维数组,一行有四个元素,总共有三行。

7.二维数组的初始化:如下图:

注意,不能写成如下形式:

 不然的话它里面会变成一个逗号表达式 ,会从左向右以此计算,所以这个数组相当于初始化为2和4。

另外在初始化的时候只能二维数组只能省略行,不能省略列,就像这样写: int arr[][4];

 只省略行的行的话 ,它会根据列的数字自己排列,如果都没有的话,它会继续下去都放在一行,这样会出错。

8.二维数组的使用:首先得先说一下它的下标,和一维数组一样,一开始都是从0开始的,不管是行还是列,二维数组的第一个元素就是arr[0][0],如果表示第二行第三列的元素,就是arr[1][2],有点类似于坐标。

二维数组的输入输出:二维数组有行和列,需要先输出一行,然后就是下一行,所以就需要两层循环。所以就可以定义两个变量,一次输入或者输出一行的数据。

#include <stdio.h>
int main()
{
	int arr[3][5] = { 0 };
	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)//当i=0时处理第一行,第一行处理完i再变成1处理下一行
	{
		for (j = 0; j < 5; j++)//和一维数组的处理方式一样
		{
			scanf("%d", &arr[i][j]);
		}
	}
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");//打印完一行换行
	}
	return 0;
}

9.二维数组在内存中的储存:

#include <stdio.h>
int main()
{
	int arr[3][5] = { 0 };
	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
		{
			printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
		}
	}
	return 0;
}

 由图可知,又是连续的差四位 ,包括换行的时候,也是差四。我们认为二维数组像是一个表格,但事实上它的存储也是和一维数组一样一条龙这样存下来的。如果把二维数组里面的每一行当作是一维数组,那么它每一行的数组名就是arr[i],因为比如你访问第一行的时候,第一行就都是arr[0][j],第二行就是arr[1][j],所以arr[i]就可以当作是这一行的数组名,这个理解还蛮重要的,会与后面的指针有联动,其实理解起来也不是很难。

10.变长数组:在创建数组的时候不太灵活,很难适应很多情况,[]里面的值是常量,就已经固定下来了,于是可能会空间不足或者空间浪费,这时候需要变长数组。C99中给出了变长数组,允许我们使用变量来指定数组的大小,并不是说数组想长就长,想短就短,数组的大小一旦确定好就不会再变了。但是很遗憾,VS不支持C99中的变长数组。变长数组的根本特征就是数组长度只有运行时才确定,所以变长数组不能初始化。

11.练习:多个字符从两端移动,向中间汇聚。就比如说我要打印“hello my friend!",然后我一开始全是#,下一次打印左边先有一个”h”,右边出来一个“d”,就这个意思。我们需要两组数据,第一组放我想要的句子,第二组放#,然后将第一组的内容慢慢的复制过来。其次是我们还得知道这个字符串的长度是多少以此来确定相应字母的下标,就可以用strlen来计算,我们将左边字母的下标记为left,右边的为right。最后就是复制,两组长度一样,就只需要将第一组的left和right分别复制给第二组的left和right就行了。复制完一次之后还有下一次,所以需要用到循环,由于左边的下标会增加,右边的下标会减少,在循环的过程中左右会交错,就可以终止了。综上,就可以写出如下代码:

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "hello my friend!";
	char arr2[] = "################";
	int left = 0;//左边的下标
	int right = strlen(arr1) - 1;//右边的下标

	while (left <= right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", arr2);
		left++;
		right--;
	}
	return 0;
}

可是这样是一下子出来的,如果想要效果好一点,有那种“渐渐的”感觉的话并且只有一行 ,可以:

#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <stdlib.h>
int main()
{
	char arr1[] = "hello my friend!";
	char arr2[] = "################";
	int left = 0;//左边的下标
	int right = strlen(arr1) - 1;//右边的下标

	while (left <= right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", arr2);
		Sleep(1000);//单位是毫秒
		system("cls");
		left++;
		right--;
	}
	printf("%s\n", arr2);
	return 0;
}

最后的结果可以自己去运行一下,还蛮有意思的。

OK以上就是关于C语言数组的相关知识了,今天就到这里了,拜拜。

  • 25
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值