一、数组的定义
C语言作为一门编程语言,其中也不乏很多的计算数据题,而对于这些计算题,有的数据很少只需要定义几个变量即可,但有些问题就需要用到很多的数据。比如一道非常经典的基础练习题:
输入10个同学的成绩,分别计算总分和平均分,并输出。
这题应该怎么写呢?要输入十个变量这么多,我们总不能int a,int b,int c,int......吧,这时候就体现出数组的重要性了,数组是一个为了方便储存各种类型的数据而创造的,是一组相同类型元素的集合。
数组的创造方法格式是:
type name [num];
如:int a[10];
char arr[20];
其中,type所指代的是数组的元素类型,如int,char,float,double等。
name是数组的名字,这个并没有什么标准要求,自己起就好。
num代表一个常量,而这个常量就代表数组中能存放多少数据。
此时需要存储10名同学的成绩,那么我们就可以定义一个数组int score[10]来专门存放这十个数据,并且用for循环将其输入并且计算出总分和平均分。
#include<stdio.h>
int main()
{
int score[10] = { 0 };
int i = 0;
int sum = 0;
for (i = 0; i < 10; i++)
{
scanf("%d", &score[i]);
sum = sum + score[i];
}
printf("总分为%d 平均分为%.2f", sum, sum / 10.0);
return 0;
}
这样就成功的利用数组知识来解题啦!!!
二、数组的初始化
数组在被创建时,需要有一些与生俱来的初始值,这就是数组的初始化。
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//在想要数组被填充满的时候,可以不指定数组大小。
//输入多少元素,数组就自动定义相应的大小。
(注意,虽然是十个数,但数组中元素的排序起始是从[0]开始的)
而我们初始化的元素不足以填满整个数组时,其余的元素就会被0所填充。
int arr[10] = { 1,2,3,4,5 };
而除了int类型的数组初始化,字符类型的数组初始化也有不同的需要注意的地方,比如数组对于char类型的初始化,就有两种不同的写法,虽然看起来大同小异但却差之毫厘失之千里!
char arr[] = "asdfgh";
虽然说有些时候可以不指定数组大小,但像这种写法会导致数组里的元素比我们想要得到的还要多出一个,因为我们要知道'\0'是打印字符的结束标志而不指定数组大小且不用大括号形式存储元素时,数组会自动在字符串最后填充一个'\0'。而有些时候还会有人特意写上arr[6],在这种情况下这个行为更是错误的,我们要注意,此时存储'\0'的是arr[6](第七个元素)这是一种错误,如果定义了[6]就是只存储六个元素,那么就没有'\0'这个打印字符的结束标志了。
三、一维数组
其实我们上面举例子用到的都是一维数组,而想要使用一维数组,我们首先需要知道数组的下标是什么,是如何规定的,与元素之间又有着怎样的关系。
1.数组的下标
下标就是代表着各种元素的序号,像牧场里的牛有编号,羊有编号,数组里的元素也有编号。还用刚刚的arr[10]={1,2,3,4,5,6,7,8,9,10}为例可以看到,元素1对应的下标是0,2对应的下标是1,那么我们就能知道,按顺序来查看,第n个元素的下标就是n-1。
我们用代码来更直观的查看一下这种情况。
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d\n", arr[4]);//5
printf("%d\n", arr[6]);//7
printf("%d\n", arr[9]);//10
return 0;
}
2.数组的长度(sizeof)
有些时候会需要在循环,分支或者各种语句中用到数组的长度,但是一个个统计又太慢,于是有了sizeof来求数组的长度。
int sz = sizeof(arr) / sizeof(arr[0]);
sizeof求的是字节长度,sizeof(arr)代表整个数组的字节,sizeof(arr[0])代表的是其中一个元素的字节,两数相除就能知道数组的长度了(就是元素数量)。
3.数组的地址存放
我们知道大部分时候,地址的存放都是由高地址存向低地址的,而数组是相反的,数组的存放是又低地址向高地址存放的。每一个元素之间相差4(因为⼀个整型是4个字节),由这几个地址可以看出:数组在内存中是连续存放的。
那么我们已经了解了一维数组的各种知识,来趁热打铁做一道例题,让知识点记忆更加牢固吧!
练习题:将两个字符串连接起来,不使用strcat函数。
(strcat函数是让一个字符串儿追加到另一个字符串儿的结尾)
让两个字符串相连,需要分别将两个字符串放到两个数组当中,再通过遍历的方式找到第一个字符串的长度,从第一个字符串的末尾开始添加第二个字符串,最后将整合好的字符串打印出来!有思路了,敲代码吧。
#include<stdio.h>
int main()
{
char arr1[100];//数组的初始化,大小最大为100
char arr2[100];
int i = 0;
int j = 0;
printf("输入位于前方的字符串:>");
scanf("%s", arr1);//因为是输入整个数组的字符串,不用带&地址符。
printf("\n输入位于后方的字符串:>");
scanf("%s", arr2);
while (arr1[i] != '\0')
{
i++;//使i的值变成第一个字符串的长度
}
while (arr2[j] != '\0')
{
arr1[i] = arr2[j];//字符串一的尾项与字符串二的首项相连了
i++;
j++;
}
printf("\n两个字符串连接后:%s \n", arr1);
return 0;
}
看似和我们的思路完全一致了,但运行起来却变成了这样
怎么就烫了呢?是运算过度让计算机发烧了吗???再仔细看看呢?其实就是之前说到的一个知识点,打印字符的结束标志识'\0'忘记添加啦!如果不添加的话,我们定义的大小最大为100的数组输出是不会停止的!像这样就没有问题啦!!
四、二维数组
1.二维数组的概念
二维数组顾名思义,写法上就是在一维数组的基础上添加了一个[],比如arr[10][10],这就是一个能够存放十行,每一行有十个元素的数组(一百个元素)。一维数组是由单个的元素组成所以叫做一维数组,如果将一维数组当作元素,那就是二维数组,以此类推还有更高维的数组,在这里就不给大家一一讲解了。
由图可以清晰的看出数组元素,一维数组,以及二维数组的关系。
而代码运行时,二维数组的顺序是从左到右,从上到下的,地址也一样是连续存放的,光说可能大家还不太懂,用这个代码给大家来讲解。
#include<stdio.h>
int main()
{
int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int i;
int j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
由图我们可以看到,地址仍然是连续的,并且打印出的1对应arr[0][0],2对应arr[0][1],3对应arr[0][2]......以此类推。
2.二维数组的初始化
相较于一维数组的初始化,二维数组也有相同之处,比如二维数组同样可以省略行(但是不能省略列)。
int arr1[3][5] = {1,2};
int arr2[3][5] = {0};
这样就是不完全的初始化,用图片的方式观看更加易懂。
直接写元素的时候,它是只会按照顺序一个个填充的,但其实除了这样初始化,还有一种方法
int arr4[3][5] = {{1,2},{3,4},{5,6}};
这样也可以切换到不同的行为元素初始化。
3.二维数组的输入与输出
既然知道了二维数组的基本知识,那也要了解它的输入输出才能算真正学会它,二维数组存放行和列的数值,而行和列同时切换,所以用for就非常合适。让我们来尝试一下输入并输出。
#include<stdio.h>
int main()
{
int arr[3][3];
int i;
int j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
scanf("%d", &arr[i][j]);
}
}
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
练习题:二分查找。
写一个二分查找函数,二分查找函数就是在一个升序数组中查找指定的数值,找到了就返回下标,找不到就返回-1。
我们先来看一看什么叫做二分查找函数。比如你想在一个数组中寻找一个你想找到的元素,应该怎么办的?一般都会想到遍历的方法,但在数据很多的时候,遍历既慢,效率又低。而为了提高查找效率,便有了二分查找。
如图所示,比如我想在数组中找数字10,那么我们就用left和right的平均值mid来与10进行比较,此时发现10大于平均值mid,那么就证明mid及他之前的数字都比10要小了,那么就将left调整到mid的下一个数字,再求平均值,再比大小,直到找到元素,或者left==right,退出二分查找。
(效率虽高但只适用于有序数据集合)
思路有了,让我们开始敲代码吧!
#include <stdio.h>
int bin_search(int arr[], int left, int right, int key)
{
//arr 是查找的数组
//left 数组的左下标
//right 数组的右下标
//key 要查找的数字
int k = -1;
while (left <= right)
{
int m = (left + right) / 2;
if (arr[m] < key)
{
left = m + 1;//mid及其左边都小于,所以不用再比
}
else if (arr[m] > key)
{
right = m - 1;//mid及其右边都大于,所以不用再比
}
else
{
k = m;
break;
}
}
return k;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
int left = 0;
int right = sz - 1;
int key;
scanf("%d", &key);
int biao = bin_search(arr, left, right, key);
if (biao >= 0)
{
printf("找到了,下标为%d", biao);
}
else
printf("%d", biao);
return 0;
}
运行结果:
好了,那这次关于数组的分享就到这里啦,我们下次再见!!!