在了解一维数组和二维数组之前,我们首先要知道,数组是什么?
数组是一组相同元素的集合,它包括一维数组和二维数组。
(1)数组中存放的是1个或多个数据,但数据元素的个数不能为0。
(2)数组中存放的多个数据,类型是相同的。
03【手把手教你入门C语言】数组的创建、初始化和使用
一、一维数组
1. 一维数组的创建和初始化
1.1一维数组的创建
一维数组创建语法:
type arr_name[常量值];
//type:数组中存放数据的类型,char、int、short、flaot等,或者自己定义的类型
//arr_name:数组名
//[]中的常量值:数组的元素个数
一维数组创建举例:
int math[20];//利用一维数组存放班级里20个学生的数学成绩
char ch[5];//存5个字符
float num[10];//存10个浮点数
注:数组创建, [ ] 中要给一个常量才可以,不能使用变量。
1.2 一维数组的初始化
在创建变量或者数组的时候,需要给定⼀些初始值,被称为数组的初始化。
数组的初始化⼀般使⽤大括号,将数据放在⼤括号中。
#include <stdio.h>
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };//完全初始化:给10个元素,初始化10个元素
int arr2[10] = { 1,2,3 };//不完全初始化:给几个初始化几个,剩余的默认初始化为0
//int arr3[3] = { 1,2,3,4};//错误的初始化:初始化的值不能比数组的元素更多
char arr4[10] = { 'a','b','c'};//字符数组的不完全初始化:剩余的也初始化为0
return 0;
}
数组的初始化要求初始化的值不能比数组的元素更多。
如果字符数组不完全初始化,那么剩下的内容将会被自动初始化为0,char类型的自动初始化为\0。
#include <stdio.h>
int main()
{
char arr4[10] = { 'a','b','c'};//字符数组的不完全初始化:剩余的也初始化为0
return 0;
}
数组在创建的时候如果想不指定数组的确定的大小就初始化。数组的元素个数根据初始化的内容来确定。
#include <stdio.h>
int main()
{
int arr1[10] = { 1,2,3 };
int arr2[] = { 1,2,3 };//数组如果初始化了,就可以省略掉数组的大小,
//那么编译器会根据初始化内容来自动推算数组的元素的个数
return 0;
}
1.3 数组类型
数组也是有类型的,数组算是⼀种⾃定义类型,去掉数组名留下的就是数组的类型。
#include <stdio.h>
int main()
{
//int num;//num的类型为int
//char c;//c的类型为char
int arr1[10];//arr这个数组有没有类型?类型是什么?
//int是数组元素的类型
//arr数组类型:int [10]
int arr2[5];//arr2数组类型:int [5]
sizeof计算变量a的长度(a占几个字节)
//int a = 10;
//printf("%zd\n", sizeof(a));//a:4Byte
printf("%zd\n", sizeof(arr1));//数组名计算arr数组大小:40
printf("%zd\n", sizeof(int[10]));//用类型计算数组大小:40
printf("%zd\n", sizeof(arr2));//arr数组大小:20
//%zd -- sizeof的返回值类型为size_t,占位符%zd用来打印size_t类型的值
return 0;
}
2.一维数组的使用
利用下标访问操作符[ ],访问数组元素:
(1)数组下标:
C语⾔规定数组是有下标的,下标是从0开始的,假设数组有n个元素,最后⼀个元素的下标是n-1,下标就相当于数组元素的编号。
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
(2)⽐如下面的例子:访问下标为6的元素,我们就可以使⽤ arr[6] ,想要访问下标是3的元素,就可以使⽤ arr[6] ,执行结果为7; 给arr[6]重新赋值,输出赋值的数字为70。
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d\n", arr[6]);//[]--下标引用操作符,下标也称索引,6就是索引值
arr[6] = 70;
printf("%d\n", arr[6]);
return 0;
}
2.1 数组元素的打印
我们可以通过下标的方式访问和使用一维数组。
//数组元素的打印
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//arr[10]数组完全初始化
// 下标:0 1 2 3 4 5 6 7 8 9
int i = 0;//初始化数组下标i = 0
for (i = 0; i < 10; i++)//for循环产生数组下标0~9
{
printf("%d ", arr[i]);//printf函数和arr[i]打印数组元素
}
return 0;
}
2.2 数组元素的输入
学会了数组的访问,我们也可以根据自己的需要,⾃⼰给数组输⼊想要的数据。
#include <stdio.h>
int main()
{
int arr[10] = { 0 };//初始化10个元素的arr数组元素为0
int i = 0;//初始化数组下标i = 0
for (i = 0; i < 10; i++)
{
scanf("%d", &arr[i]);//for循环输入10个元素
//&arr[i]:arr数组名是地址,arr[i]数组元素不是地址,所以需要取地址
}
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);//for循环输出想要的元素
}
return 0;
}
另:printf("%d", arr);
无法打印数组内容:
若不用for循环+下标访问输出数组元素,直接 printf(“%d”, arr);输出就是错误的。因为arr是数组名,数组名是数组的起始地址。
执行结果的-737150648是arr数组的起始地址。
3.一维数组在内存中的存储:一维数组在内存中是连续存放的。
内存会被划分为一个个的内存单元,一个单元的大小是1个字节;每个内存单元都有一个编号,这个编号就是地址。
下面的代码依次打印数组元素的地址:
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9 };
int i = 0;
for (i = 0; i < 10; i++)
{
printf("&arr[%d]=%p\n", i, &arr[i]);//%p -- 打印地址
}
return 0;
}
运行代码时,选择跟上图一样的X86(32位的环境,地址较短)。
观察输出的地址(地址打印出来的时候,是按照16进制形式显示),发现:
(1)随着下标的增长,地址是由小到大变化的;
(2)两个相邻的元素之间相差4(因为⼀个整型是4个字节),
所以可以得出结论:数组在内存中是连续存放的。这为后期我们使⽤指针访问数组奠定了基础
二、sizeof 计算数组元素个数
(1)下面的代码,当遍历数组元素时,若数组元素个数变化 ( i 由10—>20),for 循环判断条件需要修改(由 i < 10变成 i —>20),很麻烦。
(2)我们可以通过sizeof关键字计算数组元素个数,遍历数组元素。
(sizeof 是C语言中的关键字,用来计算类型大小、变量大小和数组大小。)
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
int sz = sizeof(arr) / sizeof(arr[0]);//元素个数=总长度/一个元素长度
printf("%zd\n", sizeof(arr));//数组大小:40字节
printf("%zd\n", sizeof(arr[0]));//数组中一个元素的大小:4字节
printf("%zd", sz);//数组元素个数:10个
return 0;
}
(3)通过(2)的sizeof 我们就可以修改(1)的遍历数组元素代码。
以后在代码中需要数组元素个数的地⽅就不⽤固定写死了,使用上面的计算,不管数组怎么变化,计算出的大小也就随着变化了。
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ",arr[i]);
}
return 0;
}
三、二维数组
前⾯学习的数组称为⼀维数组,数组的元素都是内置类型的,如果我们把⼀维数组做为数组的元素,这时候就是⼆维数组,⼆维数组作为数组元素的数组被称为三维数组,⼆维数组以上的数组统称为多维数组。
1. 二维数组的创建和初始化
1.1 二维数组的创建
二维数组创建语法:
type arr_name[常量值1][常量值2];//常量值1:行;常量值2:列
举例:
int arr[3][5];//定义一个int类型、3行5列的数组(数组元素有3行,每行有5个)
double data[2][8];
1.2 二维数组的初始化(4种)
二维数组的初始化与一维数组类似。
1.2.1 不完全初始化
int arr1[3][5] = {1,2};
int arr2[3][5] = {0};
1.2.2 完全初始化
int arr3[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
键盘按下F10,在调试–窗口–监视,可以观察到arr1、arr2、arr3里面的元素。
1.2.3 按照行初始化
二维数组一行是一个一维数组,一维数组初始化用{ },所以二维数组按行初始化{{ },{ },{ }}
#include <stdio.h>
int main()
{
int arr[3][5] = { {1,2},{3,4},{5,6} };
return 0;
}
1.2.4 初始化时省略行,但是不能省略列
一维数组初始化可以省略数组元素大小,二维数组初始化可以省略行。
#include <stdio.h>
int main()
{
int arr[][5] = { 1,2,3,4,5,6 };
//给出5:一行放5个元素,至少有两行
return 0;
}
举例:
int arr5[][5] = {1,2,3};
int arr6[][5] = {1,2,3,4,5,6,7};
int arr7[][5] = {{1,2}, {3,4}, {5,6}};
2.二维数组的使用
⼆维数组的下标:维数组访问也是使⽤下标的形式的,⼆维数组是有⾏和列的,只要锁定了⾏和列就能唯⼀锁定数组中的⼀个元素。
C语⾔规定,⼆维数组的⾏是从0开始的,列也是从0开始的,如下所⽰:
int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
arr[2][4] 定位7:
#include <stdio.h>
int main()
{
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
printf("%d\n", arr[2][4]);//第2行,第4列,就能定位出7
return 0;
}
2.1 ⼆维数组的输入和输出
借助循环⽣成所有的下标,访问整个⼆维数组。
#include <stdio.h>
int main()
{
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
int i = 0;//行:0 1 2
//输入
for (i = 0; i < 3; i++)//产生行号
{
int j = 0;//列: 0 1 2 3 4
for (j = 0; j < 5; j++)//产生列号
{
scanf("%d", &arr[i][j]);//输入数据
}
}
//输出(打印)
for (i = 0; i < 3; i++)//产生行号
{
int j = 0;//列
for (j = 0; j < 5; j++)//产生列号
{
printf("%d ", arr[i][j]);//输出数据
}
printf("\n");
}
return 0;
}
3. 二维数组在内存中的存储:二维数组中的每个元素都是连续存放的。
(1)像⼀维数组⼀样,如果想研究⼆维数组在内存中的存储⽅式,也可以打印出数组所有元素的地址的。代码如下:
#include <stdio.h>
int main()
{
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
int i = 0;//行:0 1 2
//输出(打印)
for (i = 0; i < 3; i++)//产生行号
{
int j = 0;//列
for (j = 0; j < 5; j++)//产生列号
{
printf("arr[i][j]=%p\n", &arr[i][j]);
}
}
return 0;
}
从输出的结果来看:
(1) 每⼀⾏内部的每个元素都是相邻的,地址之间相差4个字节;
(2) 跨⾏位置处的两个元素(如:arr[0][4]和arr[1][0])之间也是差4个字节,所以⼆维数组中的每个元素都是连续存放的。
(2)二维数组的一行是一个一维数组int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
上面的二维数组数组名分别为:
第一行数组名:arr[0][j] j : 0~4
arr[0][1] arr[0][2] arr[0][3] arr[0][4]
第二行数组名:arr[1][j] j : 0~4
arr[1][1] arr[1][2] arr[3][3] arr[4][4]
第三行数组名:arr[2][j] j : 0~4
arr[2][1] arr[2][2] arr[2][3] arr[2][4]
如果把二维数组的一行看做是一个一维数组,那么
第一行这个一维数组的数组名为:arr[ 0 ];
第二行这个一维数组的数组名为:arr[ 1 ];
依此类推~
四、C99中的变长数组(变长数组:用变量来指定数组的长度)
(1)C99中引入了变长数组的概念,数组的大小可以使用变量来指定,但是VS默认是不支持C99中的变长数组的。
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);//根据输⼊数值确定数组的⼤⼩
int arr[n];
int i = 0;
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
for (i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
在devC++中输入n的值,就可以确定数组元素的值为1 2 3 4 5。
(2)变⻓数组不能初始化。
变⻓数组的根本特征,就是数组⻓度只有运⾏时才能确定,所以变⻓数组不能初始化。