<C>.数组

目录

 

什么是数组?

数组的初始化:

 二维数组

如何访问?

二维数组在内存中又是如何存储呢?

数组越界

 冒泡排序:数组中两个相邻的元素进行比较,如果不满足条件就交换

数组名是什么?

思考与改进:

思考:


什么是数组?

数组是一组相同类型元素的集合。
例如:int arr [ 100 ] ;
          int arr [ 10 ]={ 1,2,3,4,5,6,7,8,9,10 };

数组的创建:watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16

 创建时可以用变量吗?
例如:

int n=10;
int arr[n];
//变长数组
//这个n是根据变量n而决定的

C99中引入了变长数组的概念,允许数组的大小用变量来指定,如果编译器不支持C99中的变长数组,那就不能使用
VS2019是不支持变长数组的
并且变长数组是不能初始化的。

const int n=10;
int arr[n];
//用const修饰的叫常变量,本质上还是变量。不能这样使用

数组的初始化:


1.int arr[10]={1,2,3,4};  这种是不完全初始化,他会把初始化1,2,3,4后,剩下六个默认初始化为0。
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16

2.当初始化了后,数组大小可以不写,他会自动根据内容识别的大小
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16

 3.字符默认就是以ascii码值存储的

char arr4[3] = {'a',98, 'c'};
char arr5[] = {'a','b','c'};

这样写也是可以的,这两种的效果都是一模一样的,b的ascii码值就是98

4.如果不初始化,将会是随机值。
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16

 5.局部变量的int a;实际上也是随机值。但是全局变量的int a,那么他就会自动初始化为0;
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_17,color_FFFFFF,t_70,g_se,x_16

 静态变量也是默认初始化为0

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16

 只要变量是在静态区上开辟的,这上面的变化会默认初始化为0。栈上开辟的变量,不初始化就会是随机值。
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_11,color_FFFFFF,t_70,g_se,x_16

 (4)
   char arr1[ ]="abc"             // a b c \0  放了四个字符
    char arr2[ ]={‘a','b','c'}     //只放了三个字符

但是如果我们这样写
char arr1[ 5 ]="abc"                 // a b c \0 \0
char arr2[ 5 ]={‘a','b','c'}           //默认初始化三个字符,后面放\0
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16

5.如果要存0-n个字符,可以用循环
下标引用操作符    [     ]    是从0开始的

int main()
{
	int arr[200] = {1,2,3,4,5,6};
	//printf("%d\n", sizeof(arr));//400
	//printf("%d\n", sizeof(arr[0]));//4
	int sz = sizeof(arr) / sizeof(arr[0]);//计算数组元素个数的写法
	//              0 1 2 3 4 5
	int i = 0;
	//赋值
	for (i = 0; i < sz; i++)
	{
		arr[i] = i + 1;
	}

	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
 
打印了0-200个数字

6.一维数组在内存中的存储:
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16

1. 1-10每个数都是4个字节,并且都是差4。
2.所以说一维数组在内存中是连续存放的!!!!
3.随着数组下标的增长,地址是由低到高变化的
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16 7.通过指针,该如何访问?
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16
由此可见,p+1实际上跳了四个字节。
所以,通过指针也是能正常访问的watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16
下标可以访问,指针也能访问,都没有问题。
%p是打印地址(十六进制)的。
char*的指针,+1,就是跳过一个字符一个指针

 二维数组

二维数组的创建:
int arr[3][4];  三行四列
char arr[3][5]; 三行五列
double arr[2][4]; 二行四列

第一行有五个元素,一共三行
int arr[3][5]={ 0 } //完全初始化,比较常用

int arr[3][5]={1,2,3,4,5,6}   //不完全初始化
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16
很明显,一行初始化完了,才会初始化第二行,其他的初始化为0

int arr[3][5]={ {1,2} , {4,5} , {5,6 } };
这种就是将1,2放到第一行,4,5放到第二行,5,6放到第三行,每一行未涉及的部分初始化为0watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16

 注意:
1.行可以省略,但列不能省略,他会根据初始化内容自动确定要多少行。
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16

如何访问?

**行和列,都是从0开始的**
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_18,color_FFFFFF,t_70,g_se,x_16
指定行和列,就可以锁定元素了
所以:
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16便可以访问

当然也可以这样写:

	int arr2[][5] = { {1,2}, {4,5},{5,6} };
	int  i = 0;
	for (i = 0; i < sizeof(arr2)/sizeof(arr2[0]); i++)//0 1 2 第一行是一维数组,确定了几行
	{
		int j = 0;
		for (j = 0; j < sizeof(arr2[0])/sizeof(arr2[0][0]); j++) //第一行的大小,除以第一行第一个元素的大小,确定了几列
		{
			printf("%d ", arr2[i][j]);
		}
		printf("\n");
	}

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16

二维数组在内存中又是如何存储呢?

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16二维数组也是一行一行放的,所以说列不能省,行可以。
二维数组其实也就类似于一类数组,第一个是arr[0][j],第二个是arr[1][j]等等

数组越界

下标都是从0开始的,最大的就是n-1。如果小于0,或者大于n-1,就是数组越界了。而且C语言本身是不检查数组越界的,编译器也不报错,语法也没问题,所以得靠我们自己去检查判断
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16
 

 冒泡排序:数组中两个相邻的元素进行比较,如果不满足条件就交换

先写个框架:

void bubble_sort(int arr[])
{

}
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	//写一个冒泡函数的函数,来排序arr[]
	bubble_sort(arr);
	return 0;
}

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16
第一趟,把9排到他该出现的地方,再第二趟排8,就这样继续往下走。每一趟搞定一个。10个元素,就需要9趟这样的排序。

数组名是什么?


在绝大情况下,数组名就是首元素的地址。有两个例外,
第一个例外是sizeof()里面单独放一个数组名时,数组名就不是数组首元素地址了,而是表示整个数组。
第二种情况就是 &数组名(取地址),这种时候的数组名表示整个数组,取出的是整个数组的地址。
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16

 &arr的地址怎么和第一个一样呢?我们来+1,试一试
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16

 前两个都是+4,最后一个却加了十六进制的28,也就是40.
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_20,color_FFFFFF,t_70,g_se,x_16
第二点,当数组传入函数时,传的虽说是地址,地址+1,和用下标引用符 arr[ i+1 ],效果是一样的,都能访问。
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAWXV1ZWtpIFhZMzk=,size_14,color_FFFFFF,t_70,g_se,x_16

 所以,最终我们可以写成:


void bubble_sort(int arr[],int kz)
{
	int i = 0;
	for (i = 0; i < kz-1; i++)//9趟
	{
		int p = 0;
		for (p = 0; p<kz-1-i; p++)  //当一个排完后,就可以少排一个,所以-i
		{
			if (arr[p] > arr[p+1])//9>8
			{
				int tmp = 0;
				tmp = arr[p];
				arr[p] = arr[p+1];
				arr[p+1] = tmp;
			}
		}
	}
}
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	//写一个冒泡函数的函数,来排序arr[]
	int kz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr,kz);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

思考与改进:

当我已经发现是顺序了,我还要一个一个去对比吗?这样效率就会很慢。
我可以在走第一趟的时候,发现有没有可以交换的地方,第一趟发现他已经是顺序了,我就可以直接跳出来了。

void bubble_sort(int arr[],int kz)
{
	int i = 0;
	for (i = 0; i < kz-1; i++)//9趟
	{
	    int flag = 1;
		int p = 0;
		for (p = 0; p<kz-1-i; p++)
		{
			if (arr[p] > arr[p+1])//9>8
			{
				flag = 0;
				int tmp = 0;
				tmp = arr[p];
				arr[p] = arr[p+1];
				arr[p+1] = tmp;
			}
		}
		if (1 == flag)
		{
			break;
		}
	}
}
int main()
{
	int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
	//写一个冒泡函数的函数,来排序arr[]
	int kz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr,kz);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 


思考:

三子棋&&扫雷

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值