1. 数组的概念
2. ⼀维数组的创建和初始化
3. ⼀维数组的使⽤
4. ⼀维数组在内存中的存储
5. sizeof计算数组元素个数
6. ⼆维数组的创建
7. ⼆维数组的初始化
8. ⼆维数组的使⽤
9. ⼆维数组在内存中的存储
10. C99中的变⻓数组
11. 数组练习
一、数组的概念
接下来,我们来学另一个新的知识,数组。
从名字上我们可以看出这是一个数的集合,在我们平常的时候 ,储存数据只能用变量并且只能储存一个数字,那如果我们想要初存多个变量呢?这里我们就需要引入数组的概念
数组就是用来储存多个相同类型的数据
数组的分类:
1 、一维数组
2.多维数组(最常见的就是二维数组)
**二、**一维数组的创建和初始化
type name [ 常量值];
给常量赋值就能够指定数组的大小,存放在数组的值被称为数组的元素
type 指的是我们创建数组的类型是 int、char、double、等等
name的命名方式和标识符一样
[常量值]是用来指定数组的大小的一般是由实际情况来确定的
比如我们要储存某组20人的成绩
float score[20];
或者其它类型的
int age [10];
char ch [15];
2.2
数组的初始话,我们在创建一个变量的时候往往需要给变量赋一个初始值,那么作为变量的集合数组在创建的时候往往也是需要给其赋其初始值.
初始化:在数组创建的过程中给定数组一些初始值
3种常见的初始化的方法2
1、//完全初始化
int arr1[5] ={1,2,3,4,5}(数组大小为5个对应5个元素)
2、// 不完全初始化
int arr2[5] ={1,2,3} (剩下没有初始化的默认为0)
3 //错误的初始化(数组大小与数组元素不匹配)
int arr[3]= {1 2,3,4,5}
2.3 数组的类型
数组也是有类型的,数组算是一种自定义类型,去掉数组名,留下的就是类型
int arr[5]; 类型:int [5]
int arr2 10]; 类型:int [10]
char arr3[7];类型:char[7]
三、一维数组的使用
在上边,我们已经介绍了一维数组的基本概念,学会了基本概念我们就要学习如何使用。
3.1 数组的下标
c语言规定数组的下标是从0.开始的
int arr[5]={1,2,3,4,5}
所以我们不难发现数组的元素为n,那么数组的下标就为n-1,那么我们如何访问下标下标呢?
在C语言中我们引入了“[]”叫做下标引用操作符,用来访问下标
int main()
{
int arr[5] = { 1,2,3,4,5 };
printf("%d\n", arr[0]);//访问的就是下标为0对应的元素
printf("%d\n", arr[3]); //访问的就是下标为3对应的元素
return 0;
}
3.2 数组的打印
接下来如果我们要访问一个数组中所有的元素怎么办呢?
总不能一个一个打印出来吧(我们上边学的循环就要开始使用了)
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8};//不完全初始化
int i = 0; //作为下标
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);//通过循环找到数组0到9的下标通过下标引用操作符([])来得到每一个元素并且打印
}
return 0;
}
3.3
明白了数组的打印,那么我们是否可以自己在数组中输入自己想要的元素呢?答案是当然可以的。
#include<stdio.h>
int main()
{
int ch[10] = { 0 };
int i = 0;
for (i = 0; i < 10; i++)
{
scanf("%d", &ch[i]); //通过循环来给数组中的每个元素进行赋值
}
for (i = 0; i < 10; i++)
{ //通过循环来打印数组中的每个元素
printf("%d ", ch[i]);
}
return 0;
}
四、一维数组在内存中的存储
这里我们探究一维数组的储存主要是为了学指针与数组的关系进行铺垫的
打印数组中每个元素的地址
int main()
{
int arr[10] = { 1,2,3,4,5 };
for (int i = 0; i < 5; i++)
{
printf("%p\n", &arr[i]);//打印地址我们用的占位符是%p,通过循环我们可以把数组中
} //每个元素的地址都打印出来
return 0;
}
由小到大,由低到高,并且来连续储存
五、sizeof计算数组元素的个数.
在我们要想知道数组元素的个数,如果储存的元素过多我们不可能一个一个的来数。那么怎么来解决这种问题呢?
C语言提供给我们了一个关键字sizeof,sizeof可以计算类型或者变量的大小(单位是字节)
int main()
{
int arr[10] = { 1,2,3,4,5 };
printf("%d", sizeof(arr)); //计算数组总共的字节,可以得出是40
return 0;
}
int main()
{
int arr[10] = { 1,2,3,4,5 };
int sum = sizeof(arr);//40元钱
printf("%d\n", sizeof(arr));
//我们来举个例子:如果有40元钱,每个人提供4元,那么有多少人呢?
int single = sizeof(arr[0]); //每个人提供4元
printf("%d\n", sizeof(arr[0]));
int num = sum / single; //得到人数
printf("%d\n", num);
//在我们平常写的时候我们直接就可以综合的来写,我这里就是方便大家理解
int num2 = sizeof(arr) / sizeof(arr[0]);
printf("%d", num2);
return 0;
}
这样我们就可以在使用数组元素的时候就不用写的那么死板了,不管数组怎么变换我们都可以通过该计算得到数组元素的大小。
六、二维数组的创建
学会了一维数组,那么我们接下来来学二维数组
我们知道一维数组是相同类型数据的集合,那么我们不妨理解,一维数组的****集合不就是二维数组,依次类推…二维数组以上的数组统称为多维数组
6.2
二维数组的创建
我们上边知道了一维数组的创建,那么接下来我们来介绍如何创建二维数组
如下:
type name [常量值1] [常量值2] ;
例子:1.int arr1[5][3] —(三行五列)
2.char arr2 [3] [5] (五行三列)
这里我们来解读三点
1 type 指的是 我们所需要创建的变量的类型
2 常量值1指的是 行数
3常量值 2指的是列数
七、二维数组的初始化
在创建变量的时候,我们总会给变量赋一些值,这种叫做初始化。
二维数组和一维数组的一样,在初始化的时候也是需要用大括号来初始化的。
接下来我们来介绍几种初始化
7.1 不完全初始化
int arr1[3][5]={1,2}
int arr2[3][5]={0}
7.2,完全初始化
int arr3[3][5]={1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7}
7.3 按照行初始化
int arr4[3][5]={{1,2},{3,4},{5,6}}
7.4 在初始化的时候,可以省略行,不能省略列
八、二维数组的使用
在上边我们介绍了如何创建二维数组,以及二维数组的初始化,那么接下来我们介绍如何使用二维数组。
我们在一维数组中通过数组的下标来访问元素,那么我们在二维数组也可以通过下标来访问二维数组的元素。
c语言中规定 行的元素从0开始,列的元素也从0开始6
int Arr[3][5] ={1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7}
int main()
{
int arr1[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
printf("%d\n", arr1[2][4]);
printf("%d\n", arr1[0][0]);
printf("%d\n", arr1[2][3]);
return 0;
}
8.2 二维数组的输入和输出
通过上边我们可以访问一个元素,那么我们要访问所有的元素呢
行是到0到2,列是0到4,那么通过嵌套循环可以打印出来了
int main()
{
int arr[5][3] = { 0 };
int i = 0;
for (i = 0; i < 5; i++)
{
int j = 0;
for (j = 0; j < 3; j++)
{
scanf("%d",&arr[i][j]); //这个嵌套循环是用来给数组来输入值的
}
}
for (i = 0; i < 5; i++)
{
int j = 0;
for (j = 0; j < 3; j++)
{
printf("%d ", arr[i][j]); //这个嵌套循环是用来给数组来打印值的
}
printf("\n"); //打印完内层第一个循环后就换行
}
return 0;
}
九、二维数组在内存中的存储
int main()
{
int arr[3][5] = { 0 };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%p\n", &arr[i][j]);
}
return 0;
}
这里我们也可以发现二维数组在内存中的存储也是连续的,内存地址也是由低到高,也是相差四个字节。
了解其储存的本质,对我们之后学习指针有很大的作用的。
十、c99中的变长数组
在c99之前我们没有引入边长数组,此时数组指定大小只能用常量。而在c99之后引入了变长数组,此时我们就可以创建变量来命名,根据我们所需要的大小来创建变量这样就使其更加灵活。
c99之前
int arr[5]={1,2,3,4,5};
char arr2[]={0};
c99
变⻓数组(variable-lengtharray,简称VLA)的新特性,允许我们可以使⽤变量指定数组的大小。
int a = 0 ; a=10;
int arr3[a]={0};
上述代码我们要知道的是虽然是变长数组,但是并不是在使用中它就会自动根据数组存放的大小来变的,只要我们在创建变量的时候变量赋了值,那么其大小就已经确定了。
但是我们需要知道的是vs中并不支持变长数组,而gcc编译器是支持的
接下来我们来练习两个常见的数组题目
十一 、
练习1:多个字符从两端移动,向中间汇聚
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "wly sgdsd" ;
char arr2[] = "*********";
int right = strlen(arr1)-1; //拿出的是右边得最后一个下标
int left = 0; //拿出的首个元素的下标
while (left <= right) //条件,左边下标的值永远是小于或者等于右边下标的
{
Sleep(1000); //延迟的库函数,目的是为了看的更清楚
arr2[left] = arr1[left]; //arr1的数组首个元素赋给arr2(从左边开始)
arr2[right] = arr1[right];//arr1的数组末尾元素赋给arr2(从右边开始)
left++; //开始循环访问
right--;
printf("%s\n", arr2);
}
return 0;
}
练习2;二分查找
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int left = 0;
int right = sizeof(arr) / sizeof(arr[0]) - 1;
int mid = 0;
int find = 0;
printf(“请输入要查找的1到10的数\n”);
scanf(“%d”, &find);
while (left <= right)
{
mid = (left + right) / 2;
if (arr[mid] > find) //如果取的元素比我们要找的元素大的时候,就需要把mid下标-1给right
{
right = mid - 1;
}
else if (arr[mid] < find)
{
left = mid + 1;//如果取的元素比我们要找的元素小的时候,就需要把mid下标+1给left
}
else
{
break;
}
}
printf("找到的数为%d 下标为%d\n",arr[mid],mid);
return 0;
}