在我们前面讲过的程序里,喊大家输入某些内容的时候都是输入两、三个很少的元素,比如说输入两个数比较它们的大小,或者输入三个数比较它们的大小。因为要求我们输入的元素少,所以我们可以需要用几个元素就定义几个变量,然后用一个输入语句直接对这些变量赋值就可以了。但在实际生活里、考试中,需要的元素不止两三个,比如在这一题中:
输入10个地区的面积(面积为整数),对它们由小到大排序,并输出排序后的结果。
当然,这一题也可以改为输入100个地区的面积,都是一样的。那么当这个时候,我们还用从前需要用几个元素就定义几个变量的方法,用输入语句一次性对它们赋值,那咱们这个程序会写的超级长。所以最理想的情况是我们只定义一个变量,而这个变量是好多变量的组合,那么也就引出我们今天要学习的内容:数组,以及由这道题辐射出的关于数组的一切。
(目录)
1.数组的概念
正如导语中所提到的,数组可以实现我们只定义一个变量,而这个变量却是好多变量的组合,即数组是一组相同类型元素的集合。从这个概念中我们就可以发现两个有价值的信息:
①数组中存放的是一个或者多个数组,但是数组元素个数不能为零。
②数组中存放的多个数据,类型是相同的。
数组分为一维数组和多维数组,多维数组一般比较多见的是二维数组。
2.一维数组
⑴数组创建
一维数组创建的基本语法如下:
type arr_name[常量值];
存放在数组的值被称为数组的元素,数组在创建的时候可以指定数组的大小和数组的元素类型。
- type指定的是数组中存放数据的类型,可以是:char,short,int,float等,也可以是自定义的类型
- arr_name指的是数组名的名字,这个名字根据实际情况,起的有意义就行。
- [ ]中的常量是用来指定数组的大小的,这个数组的大小是根据实际的需求指定就行。
比如,现在我们想存储十个地区的面积,我们就可以创建一个数组如下:
int arr[10];
当然,我们也可以根据需要创建其他类型和大小的数组:
1 char ch[8];
2 double score[10];
⑵数组初始化
有时候,数组在创建的时候,我们需要给定一些初始数值,这种就称为初始化。
那数组如何初始化呢?数组的初始化一般使用大括号将数据放在大括号中。
//完全初始化
int arr[10]={2,1,3,4,6,5,7,8,9,10};
//不完全初始化
int arr2[10]={2};//第一个元素初始化为2,剩余的元素默认初始化为0
//错误的初始化-初始化项数太多
int arr3[10]={2,1,3,4,6,5,7,8,9,10,11};
⑶数组下标
C语言规定数组是有下标的,下标是从0开始的,假设数组有n个元素,最后一个元素的下标是n- 1,下标就相当于数组元素的编号,如下:
int arr[10]={2,1,3,4,6,5,7,8,9,10};
数组 | 2 | 1 | 3 | 4 | 6 | 5 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
在C语言中数组的访问提供了一个操作符[],这个操作符叫:下标引用操作符。
有了下标访问操作符,我们就可以轻松的访问到数组的元素了,比如我们访问下标为6的元素,我们就可以使用arr[6],想要访问下标是2的元素,就可以使用arr[2],代码如下:
⑷数组元素打印
接下来,如果想要访问整个数组的内容怎么办?只要我们产生数组所有元素的下标就可以了,那我们使用for循环产生0到9的下标,接下来使用下标访问,代码如下:
⑸数组输入
明白了数组的访问,当然我们也根据需求,自己给数组输入想要的数据,代码如下:
⑹数组类型
数组也是有类型的,数组算是一种自定义类型,去掉数组名,留下的就是数组的类型。如下:
数组的类型是
1 int arr[10];//数组的类型是int [10]
2 int arr2[20];//数组的类型是int [20]
3 char ch[5];//数组的类型是char [5]
⑺sizeof计算数组元素个数
在遍历数组的时候,我们经常想知道数组的元素个数,那C语言中有办法使用程序计算数组元素个数吗?答案是sizeof。
sizeof是C语言中的一个关键字,可以计算类型或者变量大小,其实也可以计算数组的大小。代码如下:
这里输出的结果是40,计算的是数组所占内存空间的总大小,单位是字节。
我们又知道,数组中所有元素的类型都是相同的,那只要计算出一个元素所占字节的个数,数组的元素个数就能算出来。这里我们选择第一个元素算大小即可。
接下来就能计算出数组的元素个数
这里的结果是10,表示数组有10个元素。
⑻冒泡法与选择法
①冒泡法(沉底法)
两个数不断比较,把大的放在后面。比较第1个数和第2个数把相对大的放在第2位,比较第2位数和第3位数把相对大的放在第3位……以此类推,这样比较完一圈可以确定保证最后面的数是最大的;比较第1个数和第2个数把相对大的放第2位,以此类推至上一轮确定的最大数之前的那个数。
导语中的那道题目“输入10个地区的面积(面积为整数),对它们由大到小排序,并输出排序后的结果”示例解答中使用的就是冒泡法。
②选择法
两个数不断比较,把小的放前面。拿第1位和第2位比较把小的放到第1位,再拿第1位和第3位比较把小的放在第1位,在拿第1位和第4位比较,把小的放在第1位……不断比较两个数字,把小的那一个放在第1位上,接着再拿第1位数字和没比较过的数字比较,这样比较完一圈之后可以确定第1个是最小的;拿第2位和后面的比较,小的放在第2位……以此类推,拿第n位和其后的数比较,小的放第n位,成为所有数中第n小的。
⑼数组在内存中的存储
有了前面的知识,我们其实使用数组基本没有什么阻碍了,如果我们要深入了解数组,我们最好能了解一下数组在内存中的存储。
依次打印数组元素的地址,输出结果我们看看:
从输出的结果,我们分析数组随着下标的增大,地址是由小到大变化的。并且我们发现每两个相邻的元素之间相差4(因为一个整形是4个字节)。所以我们得出结论:数组在内存中是连续存放的。这就为后期我们使用指针访问数组奠定了基础。
数组 | 2 | 1 | 3 | 4 | 6 | 5 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
3.二维数组
前面学习的数组被称为一维数组,数组的元素都是内置类型的,如果我们把一维数组作为数组的元素,这时候就是二维数组,二维数组作为数组元素的数组被称为三维数组……二维数组以上的数组统称为多维数组。
1 | 1 | 2 | 3 | |
int | int | int | int | |
数组元素 | 一维数组 | |||
1 | 2 | 3 | 4 | 5 |
2 | 3 | 4 | 5 | 6 |
3 | 4 | 5 | 6 | 7 |
int | int | int | int | int |
二维数组 |
⑴二维数组创建
type arr_name[常量1][常量2];
例如:
1 int arr[3][5];
2 double data[2][5];
-
3表示数组有3行;
-
5表示每一行有5个元素;
-
int表示数组的每个元素是整形类型;
-
arr是数组名,可以根据自己的需要指定名字;data数组意思基本一致。
⑵二维数组初始化
①不完全初始化
1 int arr1[3][5]={1,2};
0 | 1 | 2 | 3 | 4 | |
0 | 1 | 2 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 |
arr1数组
2 int arr2[3][5]={0};
0 | 1 | 2 | 3 | 4 | |
0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 |
arr2数组
②完全初始化
int arr3[3][5]={1,2,3,4,5,2,3,4,5,6,3,4,5,6,7};
0 | 1 | 2 | 3 | 4 | |
0 | 1 | 2 | 3 | 4 | 5 |
1 | 2 | 3 | 4 | 5 | 6 |
2 | 3 | 4 | 5 | 6 | 7 |
③按照行初始化
int arr4[3][5]={{1,2,3},{3,4,5},{5,6,7}};
0 | 1 | 2 | 3 | 4 | |
0 | 1 | 2 | 3 | 0 | 0 |
1 | 2 | 3 | 4 | 0 | 0 |
2 | 3 | 4 | 5 | 0 | 0 |
④初始化时省略行,但不能省略列
1 int arr5[][5]={1,2,3};
2 int arr6[][5]={1,2,3,4,5,6,7};
3 int arr7[][5]={{1,2},{3,4},{5,6}};
0 | 1 | 2 | 3 | 4 | |
0 | 1 | 2 | 3 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 |
arr5数组
0 | 1 | 2 | 3 | 4 | |
0 | 1 | 2 | 3 | 4 | 5 |
1 | 2 | 3 | 0 | 0 | 0 |
arr6数组
0 | 1 | 2 | 3 | 4 | |
0 | 1 | 2 | 0 | 0 | 0 |
1 | 2 | 3 | 0 | 0 | 0 |
2 | 3 | 4 | 0 | 0 | 0 |
arr7数组
⑶二维数组下标
从二维数组的初始化可以看出,其实二维数组的访问也是使用下标形式,二维数组是有行和列的,只要锁定了行和列就能唯一锁定数组中的一个元素。C语言规定,二维数组的行是从0开始的列,也是从0开始的。
0 | 1 | 2 | 3 | 4 | |
0 | 1 | 2 | 3 | 4 | 5 |
1 | 2 | 3 | 4 | 5 | 6 |
2 | 3 | 4 | 5 | 6 | 7 |
图中最右侧绿色的数字表示行号,第一行红色的数字表示列号,都是从0开始的。比如我们说第2行,第4列就能快速定位出7。
⑷二维数组的输入和输出
访问二维数组的单个元素,我们知道了,那如何访问整个二维数组呢?其实我们只要能够按照一定的规律产生所有的行和列的数字就行;以arr[3][5]为例,行的取值范围是0~2,列的取值范围是0~4,所以我们可以借助循环生成所有的下标。
⑸二维数组在内存中的存储
4.字符数组
5.C99中的变长数组
6.数组练习