文章目录
一、数组的概念
- 概念:数组是⼀组相同类型元素的集合
- 特点:
(1)数组中存放的是1个或者多个数据,但是数组元素个数不能为0
(2)数组中存放的多个数据,类型是相同的 - 分类:数组分为⼀维数组和多维数组,多维数组⼀般⽐较多⻅的是⼆维数组
二、⼀维数组的创建和初始化
- 基本语法是:类型 数组名 [常量],存放在数组的值被称为数组的元素,数组在创建的时候可以指定数组的⼤⼩和数组的元素类型,例如: int arr[10],作用是创建一个可以存储10个整型元素的数组,这个数组的名称是 arr
- 基本结构解读:
(1)类型:可以是int、float、double 、char 、short等等内置的数据类型,还可以是自定义的数据类型,以后会出专题讲解
(2)数组名:可以任意指定,但是最好取有意义的名字,增加可读性
(3)[]:里面放一个常量值用来代表数组中存放元素的个数,可以根据实际情况指定 - 例如:
int math[50];//存放某个班级50个同学的数学成绩,数据类型为整型
- 数组的初始化:
(1)完全初始化:
int arr[5] = {1,2,3,4,5};//将数组的所有元素初始化就叫
//完全初始化
(2)不完全初始化:
int arr[6] = {1};//将数组第一个元素初始化为1
//其余元素默认初始化为0
(3)错误示范:
int arr[3] = {1,2,3,4,5};//数组原本就只定义了三个元素
//此时输入了五个元素,初始化项太多了
//容易产生数组越界访问的情况
三、⼀维数组的类型及使⽤
1.一维数组的类型:
数组也是有类型的,数组算是⼀种⾃定义类型,去掉数组名留下的就是数组的类型,比如:
int arr[10];//类型为int [10]
char ch[5];//类型是char [5]
2.一维数组的使用:
(1)数组下标:
数组的每一个元素都有一个下标,下标是从0开始的,通过下标可以访问数组中的每一个元素,比如以下数组:
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
它的下标如图:
(2)[]操作符:
在C语⾔中数组的访问提供了⼀个操作符 [] ,这个操作符叫:下标引⽤操作符。有了下标引用操作符,我们就可以轻松的访问到数组的元素了,⽐如我们访问下标为7的元素,我们就可以使⽤ arr[7] ,在上面那个数组中arr[7]所代表的元素是8,想要访问下标是3的元素,就可以使⽤ arr[3],在上面那个数组中arr[3]代表的元素就是4,比如:
(3)数组的打印:
现在有如下数组:
int arr[10]={1,2,3,4,5,6,7,8,9,10};
我们如何将数组的每一个元素打印出来呢?就要用到我们学过的循环语句,将变量i初始化为0,使用i当做数组的下标,将数组的元素一一打印,如图:
(4)数组的输入:
假设有如下数组:
int arr[10] = { 0 };
同打印数组一样,要使用循环,用i表示数组下标,如图先对数组进行挨个输入,再打印出来:
四、⼀维数组在内存中的存储
为了直观的观察数组在内存中的存储,我们将数组中每一个元素的地址打印出来,使用的方法就是上面打印数组元素的方法,如图:
这里的地址使用的是16进制表达,可以看出每一个元素的地址之间隔了4个字节,而刚好数组中存放的是整形元素,大小为4个字节,由此可以看出,数组在内存中的存储是连续的,是由低到高的,了解之后对我们以后学习指针帮助,这里暂且记住就行
五、sizeof计算数组元素个数
1.计算一维数组总大小:
在遍历数组时,我们通常需要知道数组元素的个数,那么怎么求呢?我们可以用数组总大小除以数组单个元素的大小求到,求数组总大小就需要用到我们的sizeof操作符,具体方法如下:
可以看到sizeof成功帮我们算出数组的总大小,为10*4==40个字节
2.计算一维数组的元素个数
有了数组的总大小,求元素个数就很轻松了,如图:
不要认为求元素个数没有用,在后面许多地方需要用到,最好掌握好
六、C99中的变⻓数组
在C99标准之前,C语⾔在创建数组的时候,数组⼤⼩的指定只能使⽤常量、常量表达式,或者如果我们初始化数据的话,可以省略数组⼤⼩,如:
int arr[]={1,2,3,3};//编译器自动识别出元素个数为4
这样的语法限制,让我们创建数组就不够灵活,有时候数组⼤了浪费空间,有时候数组⼜⼩了不够⽤,于是C99中给了⼀个变⻓数组的新特性,允许我们可以使⽤变量指定数组⼤⼩,比如:
int n = a+b;
int arr[n];
上⾯⽰例中,数组 arr 就是变⻓数组,因为它的⻓度取决于变量 n 的值,编译器没法事先确定,只有运⾏时才能知道 n 是多少
变⻓数组的根本特征,就是数组⻓度只有运⾏时才能确定,所以变⻓数组不能初始化。它的好处是程序员不必在开发时,随意为数组指定⼀个估计的⻓度,程序可以在运⾏时为数组分配精确的⻓度。有⼀个⽐较迷惑的点,变⻓数组的意思是数组的⼤⼩是可以使⽤变量来指定的,在程序运⾏的时候,根据变量的⼤⼩来指定数组的元素个数,⽽不是说数组的⼤⼩是可变的。数组的⼤⼩⼀旦确定就不能再变化了
遗憾的是在VS2022上,虽然⽀持⼤部分C99的语法,但是默认没有⽀持C99中的变⻓数组,没法测,后面会专门写博客教大家如何在VS2022上使用变长数组,现在了解一下就可以了
七、数组练习
练习1.将字符串从两端移动,向中间汇聚(附源码)
例如:实现以下效果:
将我们要显示的字符串一步一步显现出来
1. 分析:
(1)我们可以创建两个数组,一个数组存放字符串“hello fanfan”,一个数组存放对应的* 号,如“************”,创建代码为:
char arr1[] = "hello fanfan";
char arr2[] = "************";
printf("%s\n",arr2);
(2)先打印*号数组,然后创建一个循环,每循环一次,就拿字符串数组“hello fanfan”最左边和最右边的字符替换 *数组最左边和最右边的字符,我们设最左边下标为left,右下标为right,访问最左边的字符可以用0下标表示,访问最右边的字符可以用元素长度减1的下标表示,如:
int left = 0;
int sz =sizeof(arr1)/sizeof(arr1[0]);
int right = sz-1;
while(left<=right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
left++;
right--;
printf("%s\n", arr2);
}
(3)为了提升视觉效果,我们可以让它们每替换一个字符就暂停一秒,一秒之后再进行下一组替换,这样就更加好看了。我们需要引进一个函数,Sleep(),它的参数是一个无符号整型,单位是毫秒,想要暂停1秒,就是1000毫秒,要使用这个函数要包含头文件<windows.h>,如:
#include <windows.h>
Sleep(1000)
2.答案源码:
#include <stdio.h>
#include <windows.h>
int main()
{
char arr1[] = "hello fanfan";
char arr2[] = "************";
int left = 0;
int right = strlen(arr1) - 1;
printf("%s\n", arr2);
while (left<=right)
{
Sleep(1000);
arr2[left] = arr1[left];
arr2[right] = arr1[right];
left++;
right--;
printf("%s\n", arr2);
}
return 0;
}
练习2.二分查找
1.二分查找介绍:
在⼀个升序的数组中查找指定的数字n,很容易想到的⽅法就是遍历数组,但是这种⽅法效率⽐较低。
比如我们之前写的猜数字游戏,会生成一个随机数来让玩家猜,范围是1~100,那玩家会从1开始一个一个猜吗,不会吧,那样就太慢了,我们一般会从整体的一半开始猜,比如猜50,告诉你大了还是小了,这样只需要一步就可以排除庞大数字中的一半,比如假设猜1 ~ 10000,猜5000后就可以知道猜大了还是小了,直接排除了5000个数字,效率很快,这就是⼆分查找,也叫折半查找
2.要求:
创建一个数组arr,里面包含1,2,3,4,5,6,7,8,9,10 共十个元素,用户输入一个值,然后通过二分查找快速查询用户输入的值是否在数组中,如果在就输出找到了,如果不在就输出找不到:
3.分析:
(1)根据二分查找我们需要找到中间元素,就可以用最左下标和最右下标的中间值,也就是它们的平均数,上例子我们介绍了最左下标和最右下标如何求,这里不再赘述,主要看看如何求中间下标:
int left = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int left = 0;//左下标
int right = sizeof(arr)/sizeof(arr[0])-1;//右下标
int mid = (left + right)/2;//中间下标
//为了避免left和right加起来的值大于了int能接受的最大值
//可使用这样的方式:mid = left+ (right -left)/2
(2)随后我们用中间下标对应的元素与用户输入的值进行对比,看看是大了还是小了,如果大了那么就让right=min -1,如果小了就让left = mid +1,然后再用新的right或者left算出新的left,循环往复就可以找到对应的元素,找到后就在屏幕打印“找到了”,所以我们需要创建一个循环,具体实现如下:
while (1)
{
mid = left+ (right -left)/2;
if (arr[mid] > num)
{
right = mid - 1;
}
else if (arr[mid] < num)
{
left = mid + 1;
}
else
{
printf("找到了\n");
break;
}
(3)当然,如果用户输入的值不在我们的数组中,我们就输出找不到,如:
if (left > right)
{
printf("找不到\n");
break;
}
4.答案源码:
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int mid = 0;//中间下标
int left = 0;//左下标
int right = sizeof(arr)/sizeof(arr[0])-1;//右下标
int num = 0;//用于用户输入值
printf("请输入:");
scanf("%d", &num);
while (1)
{
mid = (left + right) / 2;
//为了避免left和right加起来的值大于了int能接受的最大值
//可使用这样的方式:mid = left+ (right -left)/2
if (arr[mid] > num)
{
right = mid - 1;
}
else if (arr[mid] < num)
{
left = mid + 1;
}
else
{
printf("找到了\n");
break;
}
if (left > right)
{
printf("找不到\n");
break;
}
}
return 0;
}