C语言数组

1,一维数组的创建和初始化

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

数组的创建:由数组类型 数组名[常量表达式];构成

代码1:

int arr1[10];

代码2:

int count = 10;

int arr2[count];

代码3:

char arr3[10];

float arr4[1];

double arr5[13+7];

数组的类型可以是任意类型,数组名可以自己取,一般用arr来表示,arr是数组英文(array)的简写;常量可以是任意值,当然我们也可以用常量表达式来写,如代码2。

注意:数组创建,在C99标准之前[]里一定要是常量表达式才可以,不能使用变量,C99标准之后支持了变长数组的概念。例如下面数组可以在C99标准下的编译器上编译。

int n = 0;

scanf("%d" &n);

int arr[n];

数组的初始化:

数组的初始化是指,在创建数组的同时给数组的内容一些合理的初始值。

int arr1[10]={1,2,3};//这个数组元素个数为10,前三个数被初始化1 2 3,剩余的没有给出的默认初始化为0,也就传入的数组是[1 2 3 0 0 0 0 0 0 0]

int arr2[ ]={1,2,3,4};//没有给出数组大小的,数组的元素个数,根据后面的初始化内容来确定,这个就相当于int arr2[4]={1,2,3,4}

char arr3[3]{'a',98,'c'};//98是数字b的ASCII码值,与arr4[ ]{'a','b','c'}效果相同;

char arr4[ ]{'a','b','c'};//相当于传入数组的是a b c ,3个元素

char arr5[ ]="abcdef";//相当于传入数组的是a b c d e f \0,7个元素。

数组长度不是字符长度,字符长度是指\0之前的元素个数,数组长度时传入参数的个数,arr4的数组长度是3,字符长度大于等于3,是一个不确定的值

整型(int)变量不完全初始化,会被默认为0,字符型(char)变量不完全初始化会被默认为\0。

 一维数组的使用:

对于我们之前介绍的操作符 [ ],下标引用操作符,他就是用来访问数组的操作符。

比如有一个数组:

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开始,这里的编号就是数组的下标。例如      arr[4]=5

}

这里我们需要介绍一个函数,sizeof表示计算字节的长度,一个int型占4个字节,char型占一个字节,short型占2~4个字节,long型占4~8个字节,longlong型占8个字节,float型占4个字节,double型占8个字节(每个字节占8个 bit比特位)。

所以我们可以用sizeof来计算数组的长度;sz=sizeof(arr)/sizeof(arr[0]),数组的总字节比上第一个数组的字节。

int sz=sizeof(arr)/sizeof(arr[0]);

输出数组内容(打印数组中的每个元素),可以采用for循环遍历的方法

#include
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };

	int sz = sizeof(arr) / sizeof(arr[0]);

	int i = 0;

	for (i = 0; i < sz;i++)

		{

		 printf("%d ",arr[i]); //使用for循环遍历,将每一项依次打印出来,当然也可以逆序打印。

		}
	return 0;

}

逆序打印(就是将每个数倒着往回打印 只需要改变for循环的遍历条件即可)

int main()

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

	int sz = sizeof(arr) / sizeof(arr[0]);

	int i = 0;

	for (i = sz - 1; i >= 0;i--)

	{

		printf("%d ",arr[i]); //使用for循环遍历,将每一项依次打印出来,当然也可以逆序打印。

	}
	return 0;
}

   对数组的内容进行赋值:可以采用for循环遍历的方式

//一维数组的赋值
#include
int main()

{
	int arr[10] = { 0 };//初始化为0

	int sz = sizeof(arr) / sizeof(arr[0]);

	int i = 0;

	for (i = 0; i < 10;i++)//数组有十个元素

	{
		arr[i] = i;//使用for循环,对每一项赋值
	}
	for (i = 0; i < sz;i++)

	{

		printf("%d ", arr[i]); //使用for循环遍历,将每一项依次打印出来,当然也可以逆序打印。

	}	
	return 0;

}

 键盘输入赋值:

#define _CRT_SECURE_NO_WARNINGS
#include
int main()

{
	int arr[10] = { 0 };//初始化为0

	int sz = sizeof(arr) / sizeof(arr[0]);

	int i = 0;

	for (i = 0; i < 10;i++)//数组有十个元素

	{
		scanf("%d", &arr[i]);//使用for循环,对每一项赋值
	}
	for (i = 0; i < sz;i++)

	{

		printf("%d ", arr[i]); //使用for循环遍历,将每一项依次打印出来,当然也可以逆序打印。

	}	
	return 0;

}

总结:

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

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

一维数组在内存中存储(数组元素的地址)

每个整型变量占四个字节:

C语言数组_第1张图片

每个字符占一个字节:

C语言数组_第2张图片注意%p打印地址;有上述地址我们知道,随着数组下标的增长,元素的地址也有规律的递增,我们可以知道:数组在内存中是连续存放的

(在数组中存储一个整型的数,开辟一个四个字节的存储单元,第一个存储单元的地址就是这个这个数的地址)

2,二维数组的创建和初始化

二维数组的创建:

与一维数组相同,有数组类型,数组名,和常量表达式构成。不过这列应该有两常量表达式。

int arr[3][4];

char arr[4][5];

double arr[2][6];

 二维数组的初始化:二维数组初始化时可以省略行,不能省略列

int arr[3][4]={1,2,3,4};//表示有三行四列我们可以大致理解为 1 2 3 4这样存储。

                                                                                              0 0 0 0

                                                                                              0 0 0 0

没有被赋值的默认初始化为0;但实际上他们也是连续存储的不过编号应该是[0][0],[0][1],[0][2],[0][3],[1][0],[1][1],[1][2],[1][3],[2][0],[2][1],[2][2],[2][3]这样。

我们可以说arr[0]存储的是{1,2,3,4},就是将二维数组理解成一维数组的数组。

                  arr[1]存储的是{0,0,0,0}

                  arr[2]存储的是{0,0,0,0}

int arr[3][4]={{1,2},{4,5}};//这个可以理解为1 2 0 0

                                                                  4 5 0 0

                                                                  0 0 0 0

int arr[][4]={{2,3},{4,5}};//二维数组初始化时可以省略行,不能省略列,不然不知道什么时候换行如何排数组,而行数可以根据给出的数据确定。这个可以理解为2 3 0 0,

                                                                                                            4 5 0 0 

一个两行四列的数组。

二维数组的使用:

二位数组的使用也是通过下标的方式

输出二维数组内容(打印数组中的每个元素),可以采用for循环嵌套的方法

#include
//打印二维数组
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;
}

二维数组的赋值

#include
//二维数组的赋值
int main()
{
	int arr[3][4] = {0};
	int i = 0;
	for (i = 0;i < 3;i++)
	{
		int j = 0;
		for (j = 0;j < 4;j++)
		{
			arr[i][j]=i*4+j;
		}
	}
	for (i = 0;i < 3;i++)
	{
		int j = 0;
		for (j = 0;j < 4;j++)
		{
			printf("%-3d", arr[i][j]);//占三格左对齐
		}
		printf("\n");
	}
	return 0;
}

二维数组的赋值(直接输入)

#define _CRT_SECURE_NO_WARNINGS
#include
//二维数组的赋值
int main()
{
	int arr[3][4] = {0};
	int i = 0;
	for (i = 0;i < 3;i++)
	{
		int j = 0;
		for (j = 0;j < 4;j++)
		{
			scanf("%d", &arr[i][j]);
		}
	}
	for (i = 0;i < 3;i++)
	{
		int j = 0;
		for (j = 0;j < 4;j++)
		{
			printf("%-3d", arr[i][j]);//占三格左对齐
		}
		printf("\n");
	}
	return 0;
}

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

二维数组在内存中的存储也是连续存储的。

3,数组越界

数组的下标是有范围限制的,规定是从0开始,如果有n个元素,最后一个元素的下标就是n-;所以数组下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组和发空间的访问。C语言本身不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的。所以程序员在写代码时,要自己做好越界检查。

因为数组可能会出现越界的情况,所以我们做for循环遍历数组时,可以用sizeof来求数组的总元素个数。

数组越界如下:

C语言数组_第3张图片

二维数组的行和列也会出现数组越界 

4,数组作为函数的参数

往往我们在写代码代码的时候,会将数组作为函数传给参数,比如我们要实现冒泡排序(这里要讲算法思想)

冒泡排序的核心思想:相邻两个元素进行比较,一趟冒泡排序让一个数据来到他最终应该出现的位置上(比如升序,就是将最大的数放的最后面)

#include
//冒泡排序
void bubble_sort(int arr[], int sz)
{
	int i = 0;
	//趟数
	for (i = 0;i < sz - 1;i++)
	{
		//一趟冒泡排序
		int j = 0;
		for (j = 0;j < sz - 1 - i;j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = tmp;
			}
		}
	}
}

int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	int i = 0;
	for (i = 0;i < sz;i++) {
		printf("%d ", arr[i]);
	}

	return 0;
 }

数组名的本质是首元素的地址,在上面bubble_sort函数中,传入参数应该是地址,应该用指针变量接收,int arr[ ],看似是数组,本质是指针变量(在这里也可以写成int* arr),所以在bubble_sort函数中,不能计算出数组的长度,我们可以用传参的形式将sz传入。

但若是要计算字符串的长度可以在自定义函数中调用strlen函数,并且strlen函数的传入参数可以是数组(数组的本质就是首元素地址),也可以直接是地址就是说:strlen(arr)(arr是我们创建的char类型的数组),strlen(str)(str是我们的自定义函数中用一个char类型的指针变量来接受数组的地址,是一个地址(char *str)),strlen函数中本来就是接受一个数组首元素的地址,看什么时候识别到\0,来计算字符串的长度。

int my_strlen(char* str)
{
	int count = 0;
	while (*str != 0)
	{
		str++;
		count++;
	}
	return count;
}

指针变量在64位机器上的地址:64bit位-8字节,指针变量的大小都是8字节。在32位机器上的地址:32bit为-4字节。在VS编译器中x64的环境下都占8个字节;在x86的环境下都站八个字节,所以如果在dubble_sort函数中计算sz=sizeof(arr)/sizeof(arr[0])是等于一的(都是指针类型)

C语言数组_第4张图片

C语言数组_第5张图片

 数组名的本质是首元素地址,但是有两个例外

1.sizeof(数组名),这里数组名,表示整个数组,计算的是整个数组的大小,单位是字节。

2.&数组名,这里数组名表示的是整个数组,取出的是整个数组的地址。

(strlen(数组名),计算的是这个数组字符的个数,strlen是计算字符个数的函数需要使用头文件,strlen本身就是计算字符个数的与地址无关)

数组首元素,与第二个元素之间差了一个整型,一个整型占4个字节,向内存中申请了4个存储单元,可以看出arr表示的就是首元素的地址,而&arr表示的则是arr这个数组总的地址,一共有十个整型变量,与整个数组+1,差了40个字节,都对arr取地址了,就不能再想当然的表示为首元素的地址。

sizeof是一个操作符,用来计算变量(类型)所占空间的大小,不关注内存中存放的具体内容;

strlen是一个库函数,是专门求字符串长度的,只能针对字符串,从参数给定的地址向后一直找\0,统计\0之前出现的字符的个数。

C语言数组_第6张图片

二维数组名的理解:

二维数组名本质上也表示首元素的地址,表示的是首行元素的地址,我们可以测试一下:

C语言数组_第7张图片

可见这是一个3行4列元素,一行有4个元素,占16个字节,所以二维数组表示的是首行元素的地址。

5,数组实例:

1.三子棋

2.扫雷

(我们将在后面章节单独讲解)

你可能感兴趣的:(c语言,算法,开发语言)