数组详解之扫雷大战


强调:数组也是一种数据类型;

例如:
int arr[10];
它的数据类型表示为:int[10]

本篇博客代码: (点击文字即可进入)

一、一维数组的创建和初始化

1、数组的创建

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

数组的创建方式:

type_t arr_name [const_t];
//type_t 是指数组元素的类型
//arr_name 是指数组名
//const_t 是一个常量表达是,用来指定数组的大小

数组创建的实例:

//例1:
int arr1[10];

//例2:
int count = 10;
int arr2[count];    //这种创建数组的方式,叫创建变长数组,
					//是在c99标准以后加入的,
					//在gcc编译器下可以这样创建,vs下不支持这种方式

//例3:
char arr3[10];
float arr4[2];
double arr5[20];

注意:
数组创建,在c99标准之前,[]中要给一个常量才可以,不能使用变量。在c99标准支持了变长数组的概念,数组的大小可以使用变量指定,但是数组不能初始化。

2、数组的初始化

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

int arr1[10] = {1,2,3};
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";

数组在创建的时候如果想不指定数组的确定大小就得初始化。数组的元素个数根据初始化的内容来确定。
但是如下代码要区分,内存中是如何分配的。

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

对于arr1来说里面存放的是:‘a’ ‘b’ ‘c’ ‘\0’
对于arr2来说里面存放的是:‘a’ ‘b’ ‘c’

3、一维数组的使用

数组元素的访问可以使用下标访问符:[ ],下标引用操作符。它其实就是数组访问的操作符。

#include <stdio.h>

int main()
{
	int arr[10] = { 0 }; //数组的不完全初始化  ,数组内容全部初始化为0
	//计算数组中元素的个数
	int sz = sizeof(arr) / sizeof(arr[0]);
	//对数组内容赋值,数组的使用是通过小标来进行访问的,下标从0开始。所以:
	int i = 0; //做下标
	for (i = 0; i < sz; i++)
	{
		arr[i] = i;
	}
	//输出数组的内容
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

总结
1、数组是使用下标来访问的,下标是从0开始。
2、数组的大小可以通过计算得到。

4、一维数组再内存当中的存储方式

#include <stdio.h>

int main()
{
	int arr[10] = { 0 }; 
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0; 
	for (i = 0; i < sz; i++)
	{
		arr[i] = i;
	}
	
	for (i = 0; i < sz; i++)
	{
		printf("%p\n", &arr[i]);
	}
	return 0;
}

在这里插入图片描述
结论:
随着数组下标的增长,元素的地址,也在有规律的递增。
数组在内存中是连续存放的
在这里插入图片描述

二、二维数组的创建和初始化

1、二维数组的创建

#include <stdio.h>

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

2、二维数组的初始化

//二维数组的初始化
	int arr4[2][2] = { 1,2,3,4 };
	int arr5[2][2] = { {1,2},{3,4} };
	int arr6[][4] = { {2,3},{4,5} };   //二维数组如果有初始化,行可以省略,列不能省略

3、二维数组的使用

二维数组是通过两个下标进行访问数组元素,行下标和列下标

#include <stdio.h>

int main()
{
	//二维数组元素的访问
	int i = 0, j = 0;
	int arr[3][4] = { 0 };
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 4; j++)
		{
			arr[i][j] = i * 4 + j;
		}
	}

	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 4; j++)
		{
			printf("%d ",arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

在这里插入图片描述

4、二维数组在内存当中的存储方式

#include <stdio.h>

int main()
{
	//二维数组元素的访问
	int i = 0, j = 0;
	int arr[3][4] = { 0 };
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 4; j++)
		{
			printf("%p\n", &arr[i][j]);
		}
	}
	return 0;
}

输出结果:
在这里插入图片描述
二维数组在内存中也是连续存放的:
在这里插入图片描述

三、数组越界

数组的下标是有范围限制的。
数组的下标规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1.
所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的。
例如:

#include <stdio.h>

int main()
{

	int i = 0;
	int arr[10] = { 0 };
	for (i = 0; i < 12; i++)
	{
		arr[i] = i;
		printf("%d ", arr[i]);
	}
	return 0;
}

程序运行时会报出这样的错误
在这里插入图片描述

四、数组作为函数参数

1、什么是冒泡排序

冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。

  1. 算法步骤
    (1)比较相邻的元素。如果第一个比第二个大,就交换他们两个。
    (2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
    (3)针对所有的元素重复以上的步骤,除了最后一个。
    (4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

90 21 132 -58 34

第一轮:

  1. 90 和 21比,90>21,则它们互换位置:

21 90 132 -58 34

  1. 90 和 132 比,90<132,则不用交换位置。
  2. 132 和 –58 比,132>–58,则它们互换位置:

21 90 -58 132 34

4)132 和 34 比,132>34,则它们互换位置:

21 90 -58 34 132

到此第一轮就比较完了。第一轮的结果是找到了序列中最大的那个数,并浮到了最右边。

比较时,每轮中第 n 次比较是新序列中第 n 个元素和第 n+1 个元素的比较(假如 n 从 1 开始)。

第二轮:

  1. 21 和 90 比,21<90,则不用交换位置。
  2. 90 和 –58 比,90>–58,则它们互换位置:

21 -58 90 34 132

  1. 90 和 34 比,90>34,则它们互换位置:

21 -58 34 90 132

到此第二轮就比较完了。第二轮的结果是找到了序列中第二大的那个数,并浮到了最右边第二个位置。

第三轮:

  1. 21 和 –58 比,21>–58,则它们互换位置:

-58 21 34 90 132

  1. 21 和 34 比,21<34,则不用交换位置。

到此第三轮就比较完了。第三轮的结果是找到了序列中第三大的那个数,并浮到了最右边第三个位置。

第四轮:

  1. –58 和 21 比,–58<21,则不用交换位置。

至此,整个序列排序完毕。从小到大的序列就是“–58 21 34 90 132”。从这个例子中还可以总结出,如果有 n 个数据,那么只需要比较 n–1 轮。而且除了第一轮之外,每轮都不用全部比较。因为经过前面轮次的比较,已经比较过的轮次已经找到该轮次中最大的数并浮到右边了,所以右边的数不用比较也知道是大的。

2、冒泡排序函数的错误设计

//方法1:
#include <stdio.h>

void bubble_sort(int arr[])
{
	int sz = sizeof(arr) / sizeof(arr[0]);  //计算数组中元素的个数,这样可以吗?
	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 temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}

int main()
{
	int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
	bubble_sort(arr);  //对arr进行升序排序
	int i = 0;
	//打印排序后的数组
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

在这里插入图片描述
对程序进行调试后发现在bubble_sort()内部sz等于1
在这里插入图片描述
问题出现在数组传参上。下面介绍数组传参究竟传的是什么。

3、数组名是什么?

#include <stdio.h>

int main()
{
	int arr[4] = { 1,2,3,4 };
	printf("%p\n", arr);
	printf("%p\n", &arr[0]);
	printf("%d\n", *arr);
	printf("%d\n", sizeof(arr));
	return 0;
}

在这里插入图片描述
结论:

1.sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组。
2.&数组名,取出的是数组的地址。&数组名,表示整个数组
除此1、2两种情况之外,所有的数组名都表示数组首元素的地址。

4、冒泡排序函数的正确设计

//方法2:
#include <stdio.h>

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 temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}

int main()
{
	int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);  //对arr进行升序排序
	int i = 0;
	//打印排序后的数组
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

在这里插入图片描述

五、数组的实例

三子棋和扫雷,博主还在奋力赶稿中,完成第一时间告知大家,源码已经上传!!!

1、三子棋

三子棋链接: 请参照我的另一篇博客(点击文字即可进入)
三子棋链接: 源代码链接(点击文字即可进入)

2、扫雷

扫雷链接: 请参照我的另一篇博客(点击文字即可进入)
扫雷链接: 源代码链接(点击文字即可进入)

到这里这篇博客已经结束啦。
这份博客👍如果对你有帮助,给博主一个免费的点赞以示鼓励欢迎各位🔎点赞👍评论收藏⭐️,谢谢!!!
如果有什么疑问或不同的见解,欢迎评论区留言欧👀

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值