【C】940/bit1-5数组

【参考课程:B站  BV1cq4y1U7sg  BV1Vm4y1r7jY】

//数组-一组数        //数组:一组相同类型元素的集合

目录

1.一维数组

一维数组的创建与初始化

数组的创建

数组的初始化

完全初始化与不完全初始化

 字符型数组的两种初始化方式

*数组的结束标志

一维数组的使用

一维数组在内存中的储存

2.二维数组

二维数组的创建与初始化

二维数组的创建

二维数组的初始化

完全初始化

 不完全初始化

二维数组的使用

打印二维数组

二维数组在内存中的储存

3.数组作为函数参数

数组名是数组首元素地址,但有2个例外:

【冒泡排序法】


1.一维数组

一维数组的创建与初始化

数组的创建

	type_t arr_name[const_n];
	//type_t 数组元素类型
	//const_n 常量表达式,用于指定数组大小

E.g.

int main()
{
	//int整型类型的 含6个元素的 名称叫arr的数组
	int arr[6];
	//char字符型类型的 含7个元素的 名称叫ch的数组
	char ch[7];
//【注意】!!! 创建数组时 [ ] 内只能放常量表达式!
	//常变量也不行!!!
	int n = 8;
	int arr错误[n];   //这样是错误的!!!
  //*C99语法支持-变长数组 --数组的大小是变量
	return 0;
}

数组的初始化

//初始化:创建并赋值

int main()
{
/*完全初始化*/
  //整型数组的创建
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = { 1,2,3};  //没有给定数组大小时,数组根据初始化元素个数来确定大小
  //字符型有两种创建模式
	//①一个一个元素输入创建
	char ch1[7] = { 'm','e','t','t','r','i' };
	char ch2[] = { 'm','e','t','t','r','i','\0' }; 
	//②以字符串的形式输入创建  //!!!以字符串形式创建时,最后隐含了一个结束符 [\0]
	char ch3[7] = "mettri";  //[m][e][t][t][r][i][\0]  --7个元素
	char ch4[] = "mettri";   //[m][e][t][t][r][i][\0]  --7个元素 
/*不完全初始化*/
	int arr3[10] = { 1,2,3,4,5 };
	char ch5[6] = { 'm','e','t' };
	char ch6[6] = "met";  //[m][e][t][\0]  --4个元素 

	return 0;
}
完全初始化与不完全初始化

【整型数组】不完全初始化的空位用 [0] 填充

【字符型数组】不完全初始化的空位用 结束符[\0] 填充

 字符型数组的两种初始化方式
  1. 一个一个元素输入的创建  E.g. ch1、ch2、ch5
  2. 以字符串形式输入创建  E.g. ch3、ch4、ch6

//将ch2与ch4对比:

 *以字符串形式输入,在字符串末尾隐含一个 结束符[\0]

*数组的结束标志

  1. 通过看数组 [ ] 内定义的数组长度来及时结束数组
  2. 由数组末尾隐含的 结束符[\0] 来结束

当二者都缺少时:

#include<stdio.h>
#include<string.h>
int main()
{
	char test[] = { 'C','P','U' };
	printf("%s\n", test);
	printf("%d\n", strlen(test));
	return 0;
}

程序不知道数组在哪里结束,于是在打印我们初始化的内容后会继续打印随机乱码

字符串长度也会输出一个随机值:

//注意区分字符串与数组长度!此处数组长度是3:

一维数组的使用

下标引用操作符 [ ]:数组下标从0开始

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
    //数组的下标从0开始
	arr[5] = 6;  //此处[]为下标引用操作符
	int i = 0;
    //计算数组大小
	int sz = sizeof(arr) / sizeof(arr[0]); //数组占用的总空间/单个元素占用的空间
	for (i = 0; i < sz; i++)  //利用循环打印出完整的数组
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

  输出结果:

一维数组在内存中的储存

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("&arr[%d] = %p\n", i, &arr[i]);  //%p -按地址的格式打印 -十六进制的打印
	}
	return 0;
}

打印数组每一位元素的地址,输出结果如下:

依次+4是因为一个 整型变量在内存中占用 4字节的空间标题

*由以上结果得出结论:

  1. 一维数组在内存中是连续存放
  2. 随着数组下标的增长,地址是由低到高变化的
#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//数组名是数组首元素地址
	int* p = arr;  //创建整型指针p,把数组首元素地址交给p
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *p);
		p++;   
		//∵数组在内存中是连续储存的
		//∴把数组首元素地址交给p后能通过p++获取整个数组的元素
	}
	return 0;
}

   输出结果:


2.二维数组

二维数组的创建与初始化

二维数组的创建

int main()
{
	//创建3行4列的整型数组
	int arr[3][4];
	//创建5行7列的字符型数组
	char ch[5][7];
	return 0;
}

二维数组的初始化

//初始化:创建并赋值

在二维数组有初始化的前提下:行可省略,列不可省略

int main()
{
	//在数组初始化的情况下:
	int arr1_ok[][4] = { 1,2,3,4,5,6,7,8,9,10 };  //可以省略行数
	int arr_error[3][] = { 1,2,3,4,5,6,7,8,9,10 };  //不能省略列数
	return 0;
}
完全初始化
  1. 行一起初始化
    int main()
    {
    	int arr1[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
    	return 0;
    }

  2. 一行一行初始化(拆分为一维数组)
    int main()
    {
    	int arr1[3][4] = { { 1,2,3,4 },{ 5, 6, 7,8},{9,10,11,12} };
    	return 0;
    }

 不完全初始化
  1. 行一起初始化  //int 填充[0];char填充[\0]
    int main()
    {
    	int arr1[3][4] = {1,2,3,4,5,6,7};
    	return 0;
    }

  2. 拆分为一维数组初始化   //int 填充[0];char填充[\0]
    int main()
    {
    	int arr1[3][4] = { { 1,2 },{ 5 },{ 9,10,12 } };
    	return 0;
    }

二维数组的使用

二维数组的下标 行、列都是从0开始编号的:

[0][0][0][1][0][2]......
[1][0][1][1][1][2]......
[2][0][2][1][2][2]......

*二维数组:arr   //它的第一行一维数组:arr[0]  //第二行:arr[1]  //第三行:arr[2]

打印二维数组

#include<stdio.h>
int main()
{
	int arr[3][4] = { { 1,2,3,4 },{ 5, 6, 7,8},{9,10,11,12} };
	int i = 0;  //行号
	int j = 0;  //列号
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 4; j++)
		{
			printf("%d	", arr[i][j]);  //为使上下对齐 -%d后使用tab键代替空格
		}
		printf("\n");
	}
	return 0;
}

输出结果:

二维数组在内存中的储存

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

输出结果:

*由以上结果得出结论:

  1. 二维数组在内存中是连续存放的  //一行内部连续  //跨行也是连续的
  2. 随着数组下标的增长,地址是由低到高变化的

*二维数组在空间中的存放方式类似于一维数组

列数不可省略 →只有确定一行有多少个元素,才能知道下一行要存放在哪里

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

   输出结果:


3.数组作为函数参数

数组名是数组首元素地址,但有2个例外

  1. sizeof(数组名) -数组名表示整个数组 -计算的是整个数组的大小,单位是字节
  2. &数组名 -数组名表示整个数组 -取出的是整个数组的地址

【&数组名】 -数组名表示整个数组 -取出的是整个数组的地址:

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%p &arr取数组地址\n", &arr);
	printf("%p &arr[0]取下标0元素地址\n", &arr[0]);
	printf("%p arr -数组名表示数组首元素地址\n", arr);
	return 0;
}

 打印结果为:

//输出地址一样是因为数组地址与数组首元素地址相同

//为证明 &arr arr 具有不同的含义

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%p	&arr取数组地址\n", &arr);
	printf("%p	&arr+1 取数组后一位的地址\n", &arr + 1);
	printf("-----------------------------------------------------------------------------------------\n");
	printf("%p	arr数组名表示数组首元素地址\n", arr);
	printf("%p	arr+1 表示取数组首元素后一位地址,即数组第二位元素地址\n", arr + 1);
	return 0;
}

 打印结果为:

【冒泡排序法】
//【冒泡排序法】
//两两相邻的元素进行比较,并且可能的话需要交换顺序
void bubble_sort(int arr[],int sz)
{
	//确定趟数  //趟数 = 元素个数 - 1
	for (int i = 0; i < sz - 1; i++)
	{
		//一趟排序的过程
					  //一个数需要和原来在它后面的数比较  //原来在它前面的数已经排好序了
		for (int j = 0; j < sz - i - 1; j++)  //∴ 需要比较 sz - (i + 1) - 1 次   //-(i + 1) :数组下标从0开始  //再 -1:要减去自己
		{                                     // j <= sz - (i + 1) - 1  即: j < sz - i - 1
			if (arr[j] > arr[j + 1])  //按升序排 -当前一个元素大于后一个元素时交换
			{
				//交换元素
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}

}
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	//将数组排序为升序
	//采用【冒泡排序法】
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr,sz);
	return 0;
}

排序结果:

*冒泡排序的经典错误代码:

void bubble_sort(int arr[])  
//err:arr[] 的本质是数组第一个元素的指针,所以这里传递的形参实际上是指针
{
	int sz = sizeof(arr) / sizeof(arr[0]);  //∴在计算元素个数时,sz永远为 1
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - i - 1; j++)  
		{                                                
			if (arr[j] > arr[j + 1])  
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}

}
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	bubble_sort(arr);
	return 0;
}

 ∴实际上:

void bubble_sort(int arr[])
//实际上是:
void bubble_sort(int*arr)

形参传递的数组无法在其函数内部计算元素个数

∴要使用元素个数 -需要在函数外计算好后把元素个数传参到函数内部

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值