6.11 数组

在很多程序中数组都是重要的性能。它们使您可以用一种便利的方式来存储一些相关的信息项。我们将在第10章“数组和指针”中详细讨论数组,但是由于数组经常被用在循环中,所以现在先简单介绍一下。

一个数组就是线性存储的一系列相同类型的值,例如10个字符或15个整数。整个数组有一个单一的名字,单独的项或元素可以使用一个整数索引来进行访问。例如,下列声明:

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

阅读 ‧ 电子书库

声明debts是一个具有20个元素的数组,其中的每个元素都是一个类型为float的值。这个数组的第一个元素称为debts[0],第二个元素称为debts[1],这样直到debts[19]。注意数组元素的编号是从0而不是1开始的。每个元素都可以被赋予一个float类型的值。例如,您可以使用以下代码:

阅读 ‧ 电子书库

实际上,您可以像使用相同类型的变量那样使用一个数组元素。例如,您可以把一个值读入一个特定的元素:

阅读 ‧ 电子书库

一个潜在的易犯错误是:出于执行速度的考虑,C并不检查您是否使用了正确的下标。例如,以下都是错误的代码:

阅读 ‧ 电子书库

但是编译器并不会发现这样的错误。当程序运行时,这些语句把数据放在可能由其他数据使用的位置上,因而可能破坏程序的结果甚至使程序崩溃。

数组可以是任意数据类型的数组。

阅读 ‧ 电子书库

例如,我们先前提到过的字符串就是一个特别的例子,它被存储在一个字符数组中。一般说来,字符数组就是元素都被赋予字符值的数组。如果字符数组包含了空字符\0,那么字符数组的内容就构成一个字符串,其中空字符标志着字符串的结尾(请参见图6.6)。

阅读 ‧ 电子书库

图6.6 字符数组和字符串

用于标识数组元素的数字称为下标(subscript)、索引(index)或偏移量(offset)。下标必须是整数,而且像前面提到的那样,下标从0开始。数组中的元素在内存中是顺序存储的,如图6.7所示的那样。

阅读 ‧ 电子书库

图6.7 内存中的char和int数组

在for循环中使用数组

有很多很多的地方要用到数组。程序清单6.19是一个相对简单的例子。这个程序读入10个高尔夫分数然后进行处理。通过使用数组就可以避免使用10个用于存储分数的不同的变量名。您也可以使用for循环进行读入。这个程序接下来报告分数的总和、平均值、差点(handicap,它是平均值与标准分之间的差)。

程序清单6.19 scores_in.c程序

阅读 ‧ 电子书库

现在我们看看程序清单6.19是否能工作,接着我们再进行一些解释。下面是输出:

阅读 ‧ 电子书库

它确实工作了,我们来看一些细节。首先,注意到尽管这个例子显示您输入了11个数,但只有10个被读入了,因为读取循环只读入10个值。因为scanf()跳过空白字符,所以您可以在一行之内输入所有的10个数,也可以在每一行只输入一个数,或者您也可以像这个例子一样混合使用新行与空格来分隔输入(因为要对输入进行缓冲,所以只有当您键入回车键的时候这些数字才被发送给程序)。

其次,使用数组和循环要比使用10个单独的scanf()语句和10.个单独的printf()语句来读入并验证这10个分数更方便。for循环提供了一种简单而直接的方法来使用数组下标。注意到int数组的每个元素都被作为一个int变量进行处理。要读入int变量fue,您可以使用scanf(“%d”,&fue)。程序清单6.19要读入int元素score[ index],所以它使用了scanf(“%d”,& score[ index])。

这个例子说明了一些风格的问题。首先,使用#define指令创建一个指定数组大小的明显常量(SIZE)是一个好主意,您可以在定义数组和设置循环限制时使用这个常量。如果您以后需要把程序扩展为处理20个分数,简单地把SIZE重新定义为20就可以了,不需要改变程序中使用了数组大小的每个地方。C99允许您使用常量值指定数组大小,但是C90不允许,而#define在两种情况下都可以使用。

其次,下面的代码可以很方便地处理一个大小为SIZE的数组:

阅读 ‧ 电子书库

获得正确的数组边界是很重要的。第一个元素具有索引值0,循环从把index设为0开始。因为编号是从0开始的,所以最后一个元素的索引值为SIZE-1。也就是说,第10个元素为score[9]。使用判断条件index<SIZE可以实现这一点,它使得循环中使用的最后一个index的值为SIZE-1。

第三,一个好的编程习惯是使程序重复输出或“回显”刚刚读入的值。这有助于确保程序处理了您所期望的数据。

最后,注意程序清单6.19使用了三个独立的for循环。您可能想知道这是否是真正必需的,是否可以在一个循环中合并多个操作?答案是肯定的,您可以做到这一点,那会使程序更加紧凑。但是您应该根据模块化(modularity)的原则进行调整。这个术语所蕴涵的思想是程序应该被分为一些单独的单元,每个单元执行一个任务,这会使程序更容易阅读。也许更重要的一点是:如果程序的不同部分不混合在一起,那么模块化可以使程序更容易升级或修改。当您了解了函数之后,就可以把每个单元放入一个函数中来增强程序的模块性。