✏️ 本章所有提供代码均已测试,读万卷书不如行万里路,一定要把代码都自己敲一遍并测试
💬 努力战胜自己,比赢了任何人都可贵。每个人的成长,都需要时间沉淀。不要因为短时间看不到回报,就拒绝付出。最艰难的成功,不是超越别人,而是战胜自己。
【在本篇文章中,你会学习到的内容如下】
1.八个老婆引出数组 - 为什么需要数组
我们都知道,爱岳绮罗的张显宗有八个老婆,她们的体重分别是50kg,49kg,40kg,55kg,60kg,48kg,49kg,46kg,那请问她们的平均体重是多少呢?请用程序来计算。
按照我们之前学过的知识,应当如此来:
#include<stdio.h> int main() { double a1 = 50; double a2 = 49; double a3 = 40; double a4 = 55; double a5 = 60; double a6 = 48; double a7 = 49; double a8 = 46; double avg = (a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8) / 8; printf("八个老婆的平均体重是:%.3lf",avg); return 0; }
❗️ 其实你会发现有这样几个问题:
- 起名很麻烦且我们不建议在给变量名取名是带有数字。
- 定义变量是个繁琐的过程,在这里我们需要定义八个毫无技术含量的变量,浪费时间。
- 在做求平均时要从a1加到a8,也是一个很繁琐的过程。
其实现在还好,张显宗只有八个老婆,我们还只需要定义八个变量,从a1加到a8。如果我们现在需要计算班级所有学生的平均体重,那我们得定义几十个变量,求总体重的过程也会很繁琐,那怎么办呢?
这就引出了我们现在要讲的知识 —— 用数组来解决该类问题。
2.初识:什么是数组
除了基本数据类型,C语言还提供了构造类型的数据,构造类型的数据包括数组类型、结构体类型和共用体类型。
在程序中,经常需要对一批数据进行操作,例如,统计某个公司100个员工的平均工资。如果使用变量来存放这些数据,就需要定义100个变量,显然这样做很麻烦,而且很容易出错。这时,可以使用x[0]、x[1]、x[2]……x[99]表示这100个变量,并通过方括号中的数字来对这100个变量进行区分。
在程序设计中,使用x[0]、x[1]、x[2]……x[n]表示的一组具有相同数据类型的变量集合称为数组x,数组中的每一项称为数组的元素,每个元素都有对应的下标(n),用于表示元素在数组中的位置序号,该下标是从0开始的。
为了大家更好地理解数组,我们通过一张图来描述数组x[10]的元素分配情况:
从图中可以看出,数组x包含10个元素,并且这些元素是按照下标的顺序进行排列的。由于数组元素的下标是从0开始的,因此,数组x的最后一个元素为x[9]。
需要注意的是,根据数据的复杂度,数组下标的个数是不确定的。通常情况下,数组元素下标的个数也称为维数,根据维数的不同,可将数组分为一维数组、二维数组、三维数组、四维数组等。通常情况下,我们将二维及以上的数组称为多维数组。
📍 一句话说明什么是数组:
数组可以存放多个同一类型的数据。数组也是一种数据类型,是构造类型。即:数(数据)组(一组)就是一组数据。
💬 也可以这样理解:数组相当于一个班级,数组中的每一个元素相当于班级中的每一个学生。
3.一维数组
3.1 一维数组的定义
3.1.1 定义详解
一维数组指的是只有一个下标的数组,它用来表示一组具有相同类型的数据。
📍 定义:
类型说明符 数组名[常量表达式];
- 类型说明符:表示数组中所有元素的类型
- 常量表达式:指的是数组的长度,也就是数组中最多可以存放元素的个数。方括号中必须是常量,不能是变量。
📝 示例:
/* 定义了一个数组: - int 是数组的类型,即数组中每一个元素的类型都是int类型。 - arr 是数组的名称,方括号中的5是数组的长度。 - []中的数字 10 就是数组的 长度,表示该arr数组中最多可以存放10个int类型的数据放在10个位置上 */ int arr[10]; char brr1[10]; float brr2[1]; double brr3[20];
3.1.2 注意事项和细节说明
- 数组的下标是用
方括号
括起来的,而不是圆括号。 - 数组名的命名同变量名的命名规则相同。
- 数组定义中,数组从长度必须是常量表达式,常量表达式的值可以是符号常量,例如下面的定义是合法的:
//预编译命令,定义一个常量LENGTH,常量值为4 #define LENGTH 4 //定义一个数组 a ,数组长度为常量LENGTH,即长度为4 int a[LENGTH];
- ❗️ 反例:
/* 错误定义 */ int count = 10; int arr1[count];//数组不可以正常创建
3.2 一维数组初始化
数组的初始化是指,在创建数组的同时给数组的内容一些合理的初始值(初始化)
初始化是与数组定义是放在一条语句的。
完成数组的定义后,只是对数组中的元素开辟了一块内存空间,数组中还未存放任何数据。这时,如果想使用数组操作数据,还需要对数组进行初始化。数组初始化的常见的方式有三种,具体如下:
3.2.1 直接对数组中的所有元素赋值
int arr[5]={1,2,3,4,5};
上述代码定义了一个长度为5的数组arr,并且数组中元素的值依次为1、2、3、4、5。
📝 更多示例:
char arr1[3] = {'a',98,'c'};
3.2.2 只对数组中的一部分元素赋值
int brr[5]={1,2,3};
在上述代码中,定义了一个int类型的数组,但在初始化时,只对数组中的前三个元素进行了赋值,其它元素的值会被默认设置为0。
📝 更多示例:
char brr1[4] = {'a','b','c'}; //不完全初始化,剩余元素初始化为0 char brr2[10] = "abcdef"; //不完全初始化,剩余元素初始化为0,注意第一个剩余元素是'\0',表现形式为0。
3.2.3 对数组全部元素赋值,但不指定长度
int crr[]={1,2,3,4};
在上述代码中,等式右侧括号内有4个元素,在等式左侧的 []
内并未指定元素个数,但编译器是很聪明的,系统会根据给定初始化元素的个数定义数组的长度,因此数组crr的长度为4。
📝 更多示例:
char crr1[] = "abcdef";
📝 扩展(后面再讲):
strlen
和sizeof
没有任何关系- strlen:求字符串长度,只能针对字符串求长度,属于【库函数】,使用需要引头文件。
- sizeof:计算变量、数组、类型的大小,单位是字节,属于【操作符】,可直接使用。
char crr1[] = "abcdef"; /* sizeof 计算 arr所占空间的大小 crr1一共有7个元素:abcdef这六个元素加上一个字符串结束符 '\0' 所以占用空间: sizeof(char) * 7 = 1 * 7 = 7 */ printf("%d", sizeof(arr1); /* strlen求字符串的有效长度(长度就是个数,不是占用空间大小),即'\0'之前的字符个数 —— 6 */ printf("%d", strlen(arr1));
3.3 一维数组引用&使用
3.3.1 引用方式
下标引用操作符:
[]
。它其实就是数组访问的操作符。
在程序中,经常需要访问数组中的一些元素,这时可以通过数组名
+ 下标引用操作符
+ 下标(下标也叫做索引)
来引用数组中的元素。一维数组元素的引用方式如下所示:
数组名[下标];
在上述方式中,下标指的是数组元素的位置,数组元素的下标是从0开始的。例如,引用数组x的第三个元素的方式x[2]。
3.3.2 注意事项和细节说明
- 数组是使用
下标
/索引
来访问的,下标是从0
开始。 - 对于一个数组而言,数组中的每一个元素占用的空间大小都是相同的。
- 数组的大小可以通过计算得到。
int arr[10]; /* 对于一个数组而言,数组中的每一个元素占用的空间大小都是相同的 sizeof(arr):求得 arr 的内存空间,即十个元素占用的总空间大小 sizeof(arr[0]):求得 arr[0] 的内存空间,即一个元素占用的空间大小 */ int sz = sizeof(arr)/sizeof(arr[0]);
- 数组的下标都有一个范围,即 0~[数组长度-1],假设数组的长度为6,其下标范围为0~5。当访问数组中的元素时,下标不能超出这个范围,否则程序会报错。
3.4 一维数组的常见操作
数组在编写程序时应用非常广泛,如经常需要对数组进行遍历、获取最值、排序等操作,灵活地使用数组对实际开发很重要。接下来针对一维数组的常见操作进行详细地讲解。
3.4.1 一维数组的遍历
操作数组时,经常需要依次访问数组中的每个元素,这种操作称作数组的遍历。
3.4.1.1 解决我的八个老婆平均体重问题
接下来使用for循环依次遍历数组中的元素来解决计算我八个老婆平均体重的问题。
#include<stdio.h> int main() { /* 数组定义: - 数组名为 arr - 数组中元素类型都是double - 数组长度为8 - 下标/索引 范围是 [0,7] 数组初始化: - 由于在定义时规定了数组长度为8 - 即可以容纳的最多元素个数为8 - 因此初始化时写的元素的个数必须小于8(全部初始化)或 等于8(部分初始化) 注意: - 可以看到我们写的元素都是整型 - 但定义数组时规定类型是double - 这是没有问题的 - 这里就存在了一个 自动类型转换 - 将每一个int类型的元素转为 double 类型 */ double arr[8] = { 50,49,40,55,60,48,49,46 }; //求全部体重 double sum = 0; for (int i = 0; i < 8; i++) { //这里使用了复合赋值运算法,依次加上数组的每一元素的值 sum += arr[i]; } //求平均体重 printf("我的八个老婆的平均体重为:%.3lf", sum / 8); return 0; }
这样的话,如果是求一个班级的平均体重,是不是也就只用一个 for 循环就能搞定累加的问题了呢?✌️我真棒!
3.4.1.2 数组元素的打印输出
一维数组的打印输出方式和普通元素打印输出的方式是一样的。
#include<stdio.h> int main() { int x[5] = { 1, 2, 3, 4, 5 }; int i = 0; for (i = 0; i < 5; i++) { printf("x[%d]:%d\n", i, x[i]); } return 0; }
3.4.2 一维数组的最值
在操作数组时,经常需要获取数组中元素的最值。接下来通过一个案例来演示如何获得数组中的最大值。
#include <stdio.h> int main() { //定义一个数组并初始化 int x[5] = { 1,2,3,4,5 }; //先假设最大值为数组的第一个元素 int nMax = x[0]; //再拿数组的每一个元素去与这个最大值进行比较 for (int i = 1; i < 5; i++) { //如果该元素值大于我们当前的最大值nMax if (x[i] > nMax) { //就将最大值nMax设置为这个元素的值 nMax = x[i]; } } //这样就能得到最大值了 printf("max:%d\n", nMax); return 0; }