平地起C楼—第四层《C语言数组》

在这里插入图片描述

📺.前言

在这里插入图片描述

欢迎来到C语言数组内容章节,通过前面三层的了解,我们知道了C语言中各种数据类型关键字、以及结构化语句的了解,通过了解各种数据类型创建不同类型的变量来表示生活中的数据,但是现在我们想一下表示1000个生活中的数据(比如1000种物品的价格),我们还是用1000个不同的变量名来存储它吗?

int a=10,b=20,c=3…………num=1000;写1000次吗?😵😵😵😵显然不可能吧,这样的效率惨不忍睹啊。要把这一组数据存起来,就得用到这一章节的数组了。

🎈🎈.数组基本概念

在这里插入图片描述

数组是一个啥子东西呢?其实啊,数组是一组具有相同类型元素的集合.

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

【数组】可以分为一维数组多维数组,多维数组常见的就是二维数组

👇👇👇👇👇

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

  • 我们来看看这一维数组吧!👀👀👀

在这里插入图片描述

🍭🍭.基本语法格式

  • 一维数组创建的格式如下:👀👀👀
type  array_name[常量值];
  • type 表示数组中存放数据的类型,可以是int、short、char、double、float 等,也可以是自定义数据类型。
  • array_name 表示数组的名字,取名字作到见名知意就欧克。
  • [ ] 中的常量值是⽤来指定数组的⼤⼩的,这个数组的⼤⼩是根据实际的需求指定就⾏。
  1. 存放在数组里面的值称之为数组的元素。同时数组在创建的时候可以指定数组的大小和数组元素的数据类型

在这里插入图片描述

  1. 比如存储一个班级上20个人的英语成绩(取整),我们可以写出以下的数组形式:

int English[20];

【在定义数组的时候,需要特别注意中括号里面必须是常量,不能是变量。】

在这里插入图片描述

🍭🍭.一维数组的初始化

我们有些时候在创建数组的时候,需要给它赋予初始值,就叫作初始化。
那数组如何初始化呢?数组的初始化⼀般使⽤⼤括号,将数据放在⼤括号中。

`//完全初始化数组

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

//不完全初始化数组
int array[10]={1,2 3};第一个、第二个、第三个元素对应的值为1,2,3;后面的系统默认初始化为0。

//错误初始化数组
int array[5]={1,2,3,4,5,6,7};初始化的个数大于数组中括号的数字.

在这里插入图片描述

🍭🍭.一维数组的类型

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

int arr1[10];//它的类型是 int [10]

char arr2[20];//它的类型是 int  [20]
char ch[5]; //它的类型是 char  [5]

🍭🍭.一维数组元素的类型

上面是数组的类型,也就是把数组名字去掉,剩下的就是数组的类型。再进一步说,数组元素的类型,就是前面的类型。比如:int arr[10]; //数组元素有10个数,每个数组元素的类型就是int类型。

🎈🎈.一维数组的使用

在这里插入图片描述

学习了⼀维数组的基本语法,⼀维数组可以存放数据,存放数据的⽬的是对数据的操作,那我们如何使⽤⼀维数组呢?接下来我们先去看看数组下标👀👇👇👇

🍭🍭.一维数组下标

  • C语⾔规定数组是有下标的,下标是从0开始的,假设数组有n个元素,最后⼀个元素的下标是n-1,下标就相当于数组元素的编号,示例如下:

int array[10]={1,2,3,4,5,6,7,8,9,10};//下面用图展示:

在这里插入图片描述

在C语言中,访问数组下标,提供了一个操作符 [ ],叫作下标引用操作符

有了下标访问操作符,我们就可以轻松的访问到数组的元素了,⽐如我们访问下标为2的元素,我们使⽤ arr[2] ,想要访问下标是5的元素,就可以使⽤ arr[5] ,如下代码:

#include<stdio.h>
int main()
{
	int array[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", array[2]);//3
	printf("%d\n", array[5]);//6
	return 0;
}
  • 结果输出:

在这里插入图片描述

🍭🍭.一维数组打印

学了数组的下标,紧接着就是访问数组下标,把存入在数组里面的数据打印出来。看一看数组里面到底是什么?
在这里插入图片描述

#include<stdio.h>
int main()
{
	int array[10] = { 1,2,3,4,5,6,7,8,9,10 };
	for (int i = 0; i < 10; i++)//通过for循环来输出所有元素。
	{
		printf("%d ",array[i]);
	}
	printf("\n");
	return 0;
}

- 输出结果:

在这里插入图片描述

🍭🍭.一维数组的输入

上面是通过直接初始化的,从而数组存储数据元素。那么我们需要自己随意输入数据给数组该咋整呢?如下操作:👇👇👇👇

#include<stdio.h>
int main()
{
	int array[10] = { 0 };//直接初始化为0
	printf("请输入10个整数:\n");
	for (int i = 0; i < 10; i++)
	{
		scanf_s("%d", &array[i]);//取地址符号 & 别忘了
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d ",array[i]);
	}
	printf("\n");
	return 0;
}

在这里插入图片描述

🍭🍭.一维数组的存储地址

我们了解了一维数组的基本操作以后,现在来看看这一维数组在系统里到底是怎样存储的呢?是如何把数据放进去的呢?不妨我们把一个一维数组的数组元素的地址打印出来看一看:👀👀👀👀

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

在这里插入图片描述

我们可以看到,随着数组下标不断地增加,数组中元素的地址是不断增加的,相邻的两个元素的地址相差4个,因为一个整型的大小是4个字节。因此,得出结论就是:数组在内存中是连续存储的。

在这里插入图片描述

  • 从VS调试中,观察数组元素内存也可以看出地址的变化,以及数组的元素存储的下标。

🍭🍭.sizeof计算一维数组大小

数组大小就是数组名中括号里面的数字,但是有些创数组可以省略不写,所以在使用的时候就需要数初始化的个数,比较麻烦。我们可以通过sizeof 来求解数组大小。

#include<stdio.h>
int main()
{
	int arr[] = { 1,5,9,4,3,6,45,6,8,2,855,89,5,8,9,56,2,6,9,552,6,4,565,4,55 };
	printf("%zd\n", sizeof(arr));//整个数组所占内存的空间的总大小,单位为字节。
	printf("%zd\n", sizeof(arr[0]));//一个元素所占内存空间大小,单位也是字节。
	int ret = sizeof(arr) / sizeof(arr[0]);//总的除以单个的就是数组大小。
	printf("%d\n", ret);//可以理解为单价(单个元素所占内存空间)乘以数量(数组元素个数)等于总价(总的内存空间)。
	return 0;
}

在这里插入图片描述

🎈🎈.二维数组的创建和初始化

通过介绍一维数组的内容后,再来看二维数组其实很好理解。二维:表示有行有列,也就是在数学中说到的直接坐标,就属于二维。其实,二维是由一维数组变化而来的,一维数组是由相同类型的多个元素组成的,而二维数组的元素就是由多个一维数组的组成的。我们先看二维数组的形式:

在这里插入图片描述

🍭🍭.基本语法格式

  • 下面是二维数组的基本语法格式:👇👇👇👇
type  array_nme[常量值1][常量值2];

//比如下面的二维数组创建:
int arr1[4][5];//表示该二维数组是4行5列的。【一行有5个元素,总共4行,int 表示每个元素是整型,arr1为数组的名字】

🍭🍭.二维数组的初始化

二维数组的初始化和一维数组差不多,可以分为完全初始化和不完全初始化,只是多了注意项!来看一看吧👀👀👀👀

完全初始化:
//完全初始化
int  arr1[3][4]={1,2,3,4, 2,3,4,5, 3,4,5,6};//图解arr1二维数组如下:

在这里插入图片描述

通过vs2022调试可以看到各个元素:

在这里插入图片描述

不完全初始化:
//不完全初始化
int arr1[3][4]={1,2,3};//图解如下:
int arr2[3][4]={0};

在这里插入图片描述

可以看到不完全初始化的默认为0:

在这里插入图片描述
【在定义二维数组的时候,初始化时省略行,但是不能省略列

int arr[][4]={1,2,3,4};
int arr1[][5]={2,3,4,5,6};

🍭🍭.二维数组的类型和元素类型

二维数组的类型和元素类型的判断,与前面一维数组一样的,去掉数组名字就是二维数组的类型,而前面的定义类型就是数组元素的类型。

🎈🎈.二维数组的使用

我们了解了二维数组的创建和初始化,接下来该如何使用它呢?🏃‍♀️🏃‍♀️🏃‍♀️🏃‍♀️
二维数组和一维数组是差不多的,也是使用下标访问,只是一维数组下标只有一个数,而二维数组在用下标访问的时候是需要包括行和列的,所以有2个数字。只要锁定了行和列就能唯⼀锁定二维数组中的⼀个元素。我们就来看看二维数组的访问吧!👇👇👇👇

在这里插入图片描述

🍭🍭.二维数组的下标

C语言规定,二维数组的行是从0开始的,列也是从0开始的,我们用上面的例子,如下所⽰👀👀👀👀:

int  arr1[3][4]={1,2,3,4, 2,3,4,5, 3,4,5,6};

在这里插入图片描述

竖起的代表行号,横起的代表列号;都是从0开始访问的。例如:我们访问2行3列的数组元素,代码如下:

#include<stdio.h>
int main()
{
	int  arr1[3][4] = { 1,2,3,4, 2,3,4,5, 3,4,5,6 };
	printf("arr1[%d][%d]=%d\n", 2,3,arr1[2][3]);
	return 0;
}

在这里插入图片描述

🍭🍭.二维数组的输入和输出

既然了解了二维数组的下标访问,接下来用代码演示数组的输入和输出:👇👇👇👇

#include<stdio.h>
int main()
{
	int  arr1[3][4] = {0};
	printf("请输入二维数组数据:\n");
	//循环输入
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			scanf_s("%d", &arr1[i][j]);
		}
	}

	//循环打印
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			printf("arr1[%d][%d]=%d ", i, j, arr1[i][j]);
		}
		//打印完一行后,换行处理
		printf("\n");
	}
	return 0;
}

在这里插入图片描述

🍭🍭.二维数组的存储地址

和查看一维数组的地址一样,我们也把二维数组的地址打印出来瞧一瞧:

#include<stdio.h>

int main()
{
	int arr1[3][4] = { 0 };//直接全部初始化为0.
	//打印出地址看一看
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			printf("arr1[%d][%d] = %p\n", i, j, &arr1[i][j]);
		}
	}
	return 0;
}

通过vs2022调试来看和打印出来的来看,每⼀行内部的每个元素都是相邻的,地址之间相差4个字节,跨行位置处的两个元素之间也是差4个字节,所以二维数组中的每个元素都是连续存放的

在这里插入图片描述

在这里插入图片描述

把上面的地址拆开看就是像下面对应的那样,每4个地址就是每一行的。

在这里插入图片描述

🧨🧨.C99标准之后的变长数组

在C99标准之前,C语言在创建数组的时候,数组⼤⼩的指定只能使用常量、常量表达式,或者如果我们初始化数据的话,可以省略数组⼤⼩。

int arr1[5];
int arr2[5+6];
int arr3[]={10,20,30};
  • 如上所示的数组大小创建就不灵活。有时候会出现不够或者浪费空间等问题。因此,在C99标准中给⼀个变⻓数组(variable-length array,简称 VLA)的新特性,允许我们可以使用变量指定数组⼤⼩。但是,在我们常用的 vs 平台上是不支持变长数组的,在gcc编译器、刷题网站上一般是支持的,以变长数组不能初始化。比如:小熊猫C++ 是支持的这样写的
int  x=0;
scanf(%d“,&n);
int arr[n];//变长数组

✨✨✨即学即用【数组练习代码】

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

#include<stdio.h>
#include<string.h>//strlen()库函数的头文件
#include<windows.h>//sleep()库函数的头文件
int main()
{
	char str1[] = { "Welcome to the programming world!" };
	char str2[] = { "#################################" };

	int left = 0;
	int right = strlen(str1) - 1;//因为下标是从0开始的
	while (left <= right)
	{
		
			str2[left] = str1[left];//把str1中的第一个放入str2中的第一个
			str2[right] = str1[right];//把str1中的最后一个放到str2中的最后一个
			printf("%s\n", str2);
			Sleep(1000);//单位为毫秒
			system("cls");
			left++;//改变大小,往后移动一位
			right--;//往前移动一位
		
	}
	printf("%s\n",str2);
	return 0;
}
  • 结果如下:从两边间隔1秒,向中间汇聚。

在这里插入图片描述

练习2:二分查找
在⼀个升序的数组中查找指定的数字n,很容易想到的方法就是遍历数组,但是这种方法效率比较低。
比如我买了⼀双鞋,你好奇问我多少钱,我说不超过300元。你还是好奇,你想知道到底多少,我就让你猜,你会怎么猜?你会1,2,3,4…这样猜吗?显然很慢;⼀般你都会猜中间数字,比如:150,然后看大了还是⼩了,这就是二分查找,也叫折半查找。

  • 暴力求解:
//暴力求解:从第一个数开始遍历,每遍历一个数字就与要查找的数字相比较,看是否相等。
#include<stdio.h>
#include<string.h>
int main()
{
	int arr[] = { 10,22,35,56,67,85,95,100,130,180 };
	int number = 0;//存储需要查找的数字
	printf("请输入要查找的数字:\n");
	scanf_s("%d", &number); 
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < sz; i++)
	{
		if (number == arr[i])
		{
			printf("%d在arr数组中的位置在%d处\n", number, i);
		}
	}
	printf("没找到!\n");
	return 0;
}
  • 结果展示:

在这里插入图片描述

  • 二分查找

上面的解法不够快,要是需要找的数字在最后,那么需要遍历整个数组,才能找到。
然而,在一个有序数组中,我们可以用二分查找,代码如下:

//二分查找
#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
	//计算大小
	size_t len = sizeof(arr) / sizeof(arr[0]);
	int number = 0;
	printf("请输入要查找的数字:\n");
	scanf_s("%d", &number);
	int left = 0;
	int right = len - 1;
	int mid = 0;
	int flag = 0;
	while (left <= right)
	{
		mid = (left + right) / 2;
		if (arr[mid] == number)
		{
			flag = 1;
			break;
		}
		if (arr[mid] > number)//说明要找的数字在中间的数的左边
			right = mid - 1;
		if (arr[mid]< number)//说明在中间的数字的右边
			left = mid + 1;
	}
	if (flag == 1)
		printf("找到了,下标是%d\n",mid);
	else
		printf("没找到!\n");
	return 0;
}
  • 结果展示:

在这里插入图片描述

求中间元素的下标,使⽤ mid = (left+right)/2 ,如果left和right⽐较⼤的时候可能存在问题,可以使⽤下⾯的⽅式:

mid = left+(right-left)/2;
  • 有问题的,希望各位大佬多多评论提出。谢谢,下期再见!

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值