第5讲:数组

第一部分

1. 数组的概念

一维数组是文件夹,二维数组是书架
指针是存放地址信息的文件

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

• 数组中存放的是1个或者多个数据,数组元素个数不能为0。
• 数组中存放的多个数据,类型是相同的。

2. 一维数组的创建和初始化

01-数组的创建

存放在数组的值被称为数组的元素,数组在创建的时候可以指定数组的大小和数组的元素类型。

02-数组的初始化

数组在创建的时候,我们需要给定⼀些初始值,这种就称为初始化。

03-数组的类型

数组也是有类型的,数组算是⼀种自定义类型,去掉数组名留下的就是数组的类型。

3. 一维数组的使用【核心】

⼀维数组可以存放数据,存放数据的目的是对数据的操作

01-数组下标【下标引用操作符】

C语言规定数组是有下标的,下标是从0开始的,
假设数组有n个元素,最后⼀个元素的下标是n-1,下标就相当于数组元素的编号。
在C语言中数组的访问提供了⼀个操作符 [ ] ,这个操作符叫:下标引用操作符

02-数组元素的打印

使用for循环产生元素的下标,使用下标访问即可

03-数组的输入

使用for循环产生元素的下标,使用下标访问即可

4. 一维数组在内存中的存储

从输出的结果我们分析,数组随着下标的增长,地址是由小到大变化的,
并且我们发现每两个相邻的元素之间相差4(因为⼀个整型是4个字节)。
所以我们得出结论:数组在内存中是连续存放的。

5. sizeof 计算数组元素个数

sizeof 中C语言是⼀个关键字,是可以计算类型或者变量大小的,
其实 sizeof 也可以计算数组的大小。
这里输出的结果是40,计算的是数组所占内存空间的总大小,单位是字节。

【一维数组的综合应用】

#include <stdio.h>
int main()
{
	int score[10] = { 0 };//创建并初始化数组
	printf("请存入数据:");
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		scanf("%d", &score[i]);
		//变量前面必须加上& 运算符(指针变量除外),因为 scanf() 传递的不是值,而是地址
	    //[]是下标引用操作符,说明数组元素的地址,即存储空间所在位置
	}
	printf("存入的数据为:\n");
	for (i = 0; i < 10; i++)
	{
		printf("score[%d]=%d  &score[%d]=%p\n", i, score[i], i, &score[i]);
		//数组的访问,score[i]访问数组中的值
		//%p为地址
	}
	int sz = sizeof(score) / sizeof(score[0]);//求数组中元素的个数
	printf("存入的数据有%d个", sz);
	return 0;
}

第二部分

6. 二维数组的创建

二维数组的数组元素是一维数组
三维数组的数组元素是二维数组
n维数组的数组元素是(n-1)维数组

7. 二维数组的初始化

在创建变量或者数组的时候,给定⼀些初始值,被称为初始化。
那二维数组如何初始化呢?像⼀维数组⼀样,也是使用大括号初始化的。

对于数组的初始化部分 ‘= {0}’,它将数组的所有元素初始化为 ‘0’。这是一种常见的初始化方法,用于确保数组中的所有元素都从一个已知的值开始,避免任何未定义的行为,因为未初始化的数组可能包含垃圾值。

01-按照行初始化【使用大括号,而不是小括号】

02-初始化时省略行,但是不能省略列

关于省略行数的问题:

  • 静态分配的数组:在静态或全局数组中,你不能省略行数。编译时必须知道数组的完整大小,以便为其分配内存。因此,行数和列数都是必需的。

  • 局部自动数组:在函数内部声明的自动数组同样需要行数和列数的完整定义。

  • 动态分配的数组:只有在使用动态内存分配(例如使用指针和 ‘malloc’)时,你才能在某种意义上“省略”行数。但实际上,你是在创建一个指针数组,每个指针指向一行。

  • 特殊情况:在某些特殊情况下,比如初始化时,你可以省略第一维度的大小(行数),因为编译器可以根据初始化的元素数量自动推断出来。例如:- int Arr[][max_column] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}};在这种情况下,编译器可以从提供的初始化值中推断出行数。

总之,在大多数情况下,二维数组在声明时需要指定行数和列数。省略行数通常是不允许的,除非在某些特定的上下文中(例如具体的初始化场景)。

8. 二维数组的使用【核心】

C语言规定,二维数组的行是从0开始的,列也是从0开始的
核心:使用for循环,产生二维数组的行列下标,使用下标访问二维数组

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

二维数组中的每个元素都是连续存放
注意:二维数组的数组元素是一维数组

【二维数组的综合应用】

#include <stdio.h>

enum Array_2D//枚举必须在最前面,且不能以数字开头
{
	max_row = 4,
	max_column = 3
};

void StoreDate(int (*xy)[max_column])
{
	int i = 0;
	for (i = 0; i < max_row; i++)
	{
		int j = 0;
		for (j = 0; j < max_column; j++)
		{
			if (scanf("%d", *(xy + i) + j) != 1)
			{
				printf("error\n");
				return;
			}
			//编程习惯,检查scanf返回值的有效性
		}
	}
}

void PrintDate(int (*xy)[max_column])
{
	int i = 0;
	for (i = 0; i < max_row; i++)
	{
		int j = 0;
		for (j = 0; j < max_column; j++)
		{
			//printf("xy[%d][%d]=%d  &xy[%d][%d]=%p \n", i,j,xy[i][j],i,j,&xy[i][j]);
			//printf("%d ", xy[i][j]);
			printf("%d ", *(*(xy + i) + j));

		}
		printf("\n");
	}
}

int main()
{
	int Arr[max_row][max_column] = { 0 };//不可省略行列,否则栈堆将被破坏

	printf("存入数据:");
	StoreDate(Arr);
	//数组名一般情况下是数组首元素的地址,除去sizeof()与&arr
	//二维数组的数组元素是一维数组,故Arr在传参时,传递的是一维数组整个数组的地址
	//数组的地址需要使用数组指针来接收

	printf("存入的数据为:\n");
	PrintDate(Arr);
	
	return 0;
}

第三部分

存储器 int mid=0
计数器int count =0
状态器int flag=1

10. C99中的变长数组

在后面的“动态内存管理”会具体学习为数据分配内存空间

#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);//根据输⼊数值确定数组的⼤⼩
int arr[n];
int i = 0;
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
for (i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
return 0;
}

11. 数组练习

练习1:多个字符从两端移动,向中间汇聚

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
	//定义两个字符数组,存放显示的数据
	// 关键:使用下标访问
	char show[]="My wife will win CET-6";
	char cover[]="######################";
	int left = 0;
	size_t right = strlen(cover) - 1;//减去字符串的结束标识符
	while (left <= right)
	{
		cover[left] = show[left];
		cover[right] = show[right];
		printf("%s\n", cover);
		Sleep(1000);
		system("cls");
		left++;
		right--;
	}
	printf("%s\n", cover);
	return 0;
}

练习2:二分查找/折半查找【原生态数据库】(注意区分于“猜数字游戏”)

将杂乱无章的数据使用冒泡排序好,然后使用二分查找

#include <stdio.h>
int main()
{
	int store[10] = { 12,56,89,112,664,998,1235,1237,8523,9654 };
	int left = 0;
	int right = sizeof(store)/sizeof(store[0]) - 1;
	int key = 0;
	int found = 0;//状态标识符
	
    if (scanf("%d", &key) != 1)
	{
		printf("error\n");
	    return;
	}
	while (left <= right)
	{
		int mid = (left + right) / 2;

		if (store[mid] == key)
		{
			printf("找到了,下标是%d\n",mid);
			found = 1;;
			break;//不可使用return,否则程序不会停止
		}
		else if (store[mid] < key)
		{
			left = mid + 1;
		}
		else 
		{
			right = mid - 1;
		}
	}
	if (!found)
	{
		printf("找不到\n");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟空阿瞒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值