✨✨ 欢迎咱们来到贝蒂大讲堂✨✨
养成好习惯,先赞后看哦~
所属专栏:C言语学习
贝蒂的主页:Betty‘s blog
引言
前面贝蒂给咱们介绍了选择结构与循环结构,今日,贝蒂准备给咱们介绍C言语中一个非常重要的结构——数组
1. 数组的界说
数组究竟是什么呢,望文生义便是很多数的调集,其大致满意下面两个条件:
这些数的类型有必要相同。
这些数在内存中有必要是接连存储的。
- 换句话说,数组便是在内存中接连存储的具有相同类型的一组数据的调集。
- 数组分为⼀维数组和多维数组,多维数组⼀般⽐较多⻅的是⼆维数组。
2. 一维数组
2.1创立与初始化
(1) 创立
一维数组的界说方式如下:
类型说明符 数组名[常量表达式];
类型说明符便是咱们常用的存储类型(char int float double….),当然也能够自界说类型。
数组名便是咱们为其取的名字,最好简单易懂,方便别人阅读。
[] 中的常量值是⽤来指定数组的⼤⼩的,这个数组的⼤⼩是根据实际的需求指定就⾏
- 注意:在C99之后C言语语法是支撑变长数组的,即[]中可所以未知数,可是VS2022编译器是不支撑的。
例如:
int arr[5];//表明此刻数组arr中有 5 个元素,每个元素都是 int 型变量
char arr2[6];
float arr3[7];
double arr4[1 4];//也可所以一个表达式
(2) 初始化
有时分,数组在创立的时分,咱们需求给定⼀些初始值,这种就称为初始化。那数组怎么初始化呢?数组的初始化⼀般使⽤⼤括号,将需求初始化的数据放在⼤括号中。
初始化分为两种:彻底初始化和不彻底初始化
int arr1[4] = { 1,2,3,4 };//彻底初始化
int arr2[4] = { 1,2,3 };//不彻底初始化,剩余元素默许为0
char arr3[10] = "hello ";//初始化字符串
int arr4[];//过错初始化
- 假如进行初始化,能够不在[]声明有几个元素,数组会默许初始化几个元素,数组大小便是几个元素,可是不初始化就一定要声明有几个元素,不然就会报错。
2.2 数组输入和输出
(1) 数组下标
C语⾔规则数组是有下标的,下标是从0开端的(而不是1),假设数组有n个元素,最终⼀个元素的下标是n-1,例如:int arr[10]={1,2,3,4,5,6,7,8,9,10},其下标如下图所示:
arr | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
(2) 输入
其实数组输入和咱们平常输入差不多,只是输入目标换成了数组。
int main()
{
int arr[10];
int i = 0;
for (i = 0; i < 10; i )
{
scanf("%d", &arr[i]);//循环像数组中输入元素
}
return 0;
}
(3) 输出
输出也是同理,咱们能够使用循环输出其数组的每一个元素。
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i < 10; i )
{
printf("%d ", arr[i]);//循环输出
}
return 0;
}
2.3 数组的内存存储
(1) 数组名
C言语规则数组名表明首元素地址,也便是说arr==&arr[0],咱们能够经过以下代码来证明:
int main()
{
int arr[2] = { 1,2 };
if (arr == &arr[0])
{
printf("地址相同n");
}
else
{
printf("地址不相同");
}
return 0;
}
(2) 数组元素的存储
咱们知道了数组名表明首元素的地址之后,那么接下来咱们能够探究数组每个元素在内存中又是怎样存储的呢,咱们将其每个元素的地址打印出调查。
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i < 10; i )
{
printf(" &arr[%d] = %pn ", i, &arr[i]);
}
return 0;
}
输出结果:
从上述地址调查,地址是由⼩到⼤变化的,90,94,98……每次的增量是4,而且咱们发现每两个相邻的元素之间相差4(由于⼀个整型是4个字节),就能够很简单得出结论:数组在内存中存储是接连的,理解到这一点,就能为今后指针的学习打好基础。
arr | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
2.4 一维数组例题
标题:求恣意十个整数的和与平均数。
思路:咱们能够先将十个数输入一个数组中,然后循环求其和,在求平均数。
- 注意:虽然是是个整数,可是最终结果可能是浮点数。
代码参阅如下:
int main()
{
int arr[10];
int i = 0;
for (i = 0; i < 10; i )
{
scanf("%d", &arr[i]);//循环输入
}
int sum = 0;//和
for (i = 0; i < 10; i )
{
sum = arr[i];
}
float avr = sum / 10.0;
printf("这十个数和为%d平均数为%.1f", sum,avr);
return 0;
}
3. 二维数组
前⾯咱们学习的数组被称为⼀维数组,数组的元素都是内置类型的,假如咱们把⼀维数组做为数组的元素创立数组,这时分便是⼆维数组,⼆维数组作为数组元素的数组被称为三维数组,⼆维数组以上的数组统称为多维数组。
3.1 创立与初始化
(1) 创立
二维数组界说的一般形式为:
- 类型说明符 数组名[ 常量表达式][ 常量表达式];
- 类比一维数组的界说,只不过二维数组榜首个常量表达式表明行,第二个常量表达式表明列。
例如:
int arr[5][5];//创立五行五列的二维数组
char arr2[3][5];//字符型二维数组
float arr3[4][5];//浮点型二维数组
(2) 初始化
二维数组的初始化和一维数组的初始化相似,像⼀维数组⼀样,也是使⽤⼤括号初始化的。
int arr1[3][3] = { 1,2 };//不彻底初识化
示意图:
1 | 2 | 0 |
---|---|---|
0 | 0 | 0 |
0 | 0 | 0 |
- 不彻底初始化剩余元素默许初始化为0。
int arr2[3][3] = { 1,2,3,4,5,6,7,8,9 };//彻底初始化
示意图:
1 | 2 | 3 |
---|---|---|
4 | 5 | 6 |
7 | 8 | 9 |
int arr3[3][3] = { {1,2},{2,3} };//按照行初始化
示意图:
1 | 2 | 0 |
---|---|---|
2 | 3 | 0 |
0 | 0 | 0 |
- 按行初始化,剩余未初始化的元素默许为0.
int arr4[][3] = { 1,2,3 };//省掉行
示意图:
1 | 2 | 3 |
---|
int arr5[3][];//过错初始化
int arr6[][];//过错初始化
- 二维数组规则只能省掉行,不能省掉列。
3.2数组的输入和输出
(1) 数组下标
⼆维数组拜访和一维数组相似,也是使⽤下标的形式的,⼆维数组是有⾏和列的,只要锁定了⾏和列就能唯⼀锁定数组中的⼀个元素。C语⾔规则,⼆维数组的⾏是从0开端的,列也是从0开端的,例如:int arr[3][3]={1,2,3,4,5,6,7,8,9,10};
示意图:
行/列 | 0 | 1 | 2 |
---|---|---|---|
0 | 1 | 2 | 3 |
1 | 4 | 5 | 6 |
2 | 7 | 8 | 9 |
(2) 输入
别离循环输入行和列,思路大致和输入一维数组相同。
int main()
{
int arr[3][3] = {0};
int i = 0;
for (i = 0; i < 3; i )//输入行
{
int j = 0;
for (j = 0; j < 3; j )//输入列
{
scanf("%d", &arr[i][j]);
}
}
return 0;
}
(3) 输出
输出天然也与一维数组大致相同,使用循环顺次输出。
int main()
{
int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int i = 0;
for (i = 0; i < 3; i )
{
int j = 0;
for (j = 0; j < 3; j )
{
printf("%d ", arr[i][j]);
}
printf("n");//输出一行后换行
}
return 0;
}
3.3 二维数组的存储
(1) 数组名
二维数组的数组名也是一个地址,那和一维数组的数组名有何不同呢,其实二维数组的数组名表明的是榜首行的地址,但可能咱们仍是有下面的疑惑:
int main()
{
int arr[3][3] = { 0 };
printf("%p,%pn", arr,&arr[0][0]);
return 0;
}
为什么分明二维数组名代表的是榜首行的地址,那么为什么和榜首个元素的地址相同呢,其实和字符串的存储一样,假如将一切地址表明出来,太浪费内存,而数组在内存中是接连存储的,所以找到首元素的地址,就能找到一行中一切元素的地址。所以就以首元素地址代表榜首行的地址。
(2) 二维数组元素的存储
像⼀维数组⼀样,咱们假如想研讨⼆维数组在内存中的存储⽅式,咱们也是能够打印出数组一切元素的地址的。代码如下:
int main()
{
int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int i = 0;
for (i = 0; i < 3; i )
{
int j = 0;
for (j = 0; j < 3; j )
{
printf("arr[%d][%d]=%p ",i,j, &arr[i][j]);
}
printf("n");//输出一行后换行
}
return 0;
}
输出如下:
经过对上面地址的调查,咱们知道二维数组也是在内存中接连存储的,而且arr[0][2]和arr[1][0]的地址之间也差4个字节(byte),所以内存存储如下:
arr | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
下标 | 0,0 | 0,1 | 0,2 | 1,0 | 1,1 | 1,2 | 2,0 | 2,1 | 2,2 |
3.4 二维数组例题
标题:输入六个数到2行3列的二维数组arr中, 将二维数组arr1中的数组元素转置,即行列交换,存储到3行2列的二维数组arr2中,输出二维数组arr2中的数组元素。
思路:便是循环输入,在转置(行与列交换),最终输出。
代码如下:
int main()
{
int arr1[2][3];
int arr2[3][2];
int i = 0;
int j = 0;
for (i = 0; i < 2; i )
{
for (j = 0; j < 3; j )
{
scanf("%d", & arr1[i][j]);
}
}
for (i = 0; i < 2; i )
{
for (j = 0; j < 3; j )
{
arr2[j][i] = arr1[i][j];//转置
}
}
for (i = 0; i < 3; i )
{
for (j = 0; j < 2; j )
{
printf("%d ", arr2[i][j]);
}
printf("n");
}
return 0;
}
4. 变长数组
4.1概 念
在C99规范之前,C语⾔在创立数组的时分,数组⼤⼩的指定只能使⽤常量、常量表达式,或许假如咱们初始化数据的话,能够省掉数组⼤⼩。
例如:
int arr1[10];
char arr2[4];
int arr3[] = {1,2,3};
- 可是这样的语法约束,让咱们创立数组就不行灵敏,有时分数组⼤了浪费空间,有时分数组⼜⼩了不行⽤,所以在C99中给⼀个**变⻓数组(variable-length array,简称VLA)**的新特性,允许咱们能够使⽤变量指定数组⼤⼩。
4.2用法
例如:
int n;
scanf("%d",&n);
int arr1[n];
- 变⻓数组的底子特征,便是数组⻓度只要运⾏时才干确认,所以变⻓数组不能初始化。