C

C 知识量:16 - 74 - 317

10.2 多维数组><

创建多维数组- 10.2.1 -

如果要研究5年内每个月的降水量数据,可以使用60个变量存储每个月的数据,而更好的方式是使用数组,而且不是一般的数组,而是使用二维数组,即数组的数组。主数组有5个元素,每个元素表示一年,而每个元素又是内含12个元素的数组,其每个元素表示一个月。该数组声明如下:

float rain[5][12];

以上数组可以借助一个表格来理解:

0,00,10,20,30,40,50,60,70,80,90,100,11
1,01,11,21,31,41,51,61,71,81,91,101,11
2,02,12,22,32,42,52,62,72,82,92,102,11
3,03,13,23,33,43,53,63,73,83,93,103,11
4,04,14,24,34,44,54,64,74,84,94,104,11

每一行表示一年,每一列表示一年中的每一个月。其中,rain[0]是一个内含12个float类型值的数组,即表格的第一行,表示一年的数据。rain[1]、rain[2]等也是如此。rain[0][0]表示第1年的第1个月的数据,如果要访问第2年第5个月的数据,应当使用rain[1][4],注意数组元素的编号从0开始。

在计算机内部,这样的数组是按顺序存储的,从第1个内含12个元素的数组开始,然后是第2个内含12个元素的数组,以此类推。

进行气象分析时,要计算每年的总降水量、5年来的年平均降水量和月平均降水量。计算每年总降水量,必须对一行数据求和;计算某月份平均降水量,必须对一列数据求和。具体程序如下:

#include <stdio.h>
#define MONTHS 12
#define YEARS 5

int main(void) {
    //创建和初始化2014年以来5年的降水数据
    float rain[YEARS][MONTHS] = {
        {5.2, 1.2, 0.2, 6.5, 8.5, 4.5, 3.2, 6.8, 9.5, 1.0, 5.1, 2.1},
        {1.2, 4.2, 1.2, 4.5, 3.7, 4.1, 2.2, 8.8, 7.0, 1.5, 5.2, 5.7},
        {2.2, 0.2, 1.2, 5.4, 8.8, 4.7, 3.0, 4.8, 3.5, 2.0, 4.1, 4.1},
        {3.2, 1.3, 0.6, 3.5, 4.2, 4.1, 3.6, 6.1, 4.5, 6.0, 2.1, 7.1},
        {1.2, 1.7, 0.3, 2.5, 6.9, 9.5, 6.1, 4.4, 6.5, 1.3, 3.1, 1.1}
    };
    int year, month;
    float subtot, total;
    
    /******处理每年的总降水量******/
    printf(" Year            rainfall (inches)\n");
    for (year = 0, total = 0; year < YEARS; year++) {
        //计算每年降水量总和
        for (month = 0, subtot = 0; month < MONTHS; month++)
            subtot += rain[year][month];
        printf("%5d %15.1f\n", 2014 + year, subtot);
        total += subtot; //计算5年的总降水量
    }
    
    /******处理5年来的年平均降水量******/
    printf("\n The yearly average is %.1f inches.\n\n", total / YEARS);
    
    /******处理5年来的月平均降水量******/
    printf(" Monthly averages:\n\n");
    printf(" Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec\n");
    for (month = 0; month < MONTHS; month++) {
        //计算每个月份,5年的总降水量
        for (year = 0, subtot = 0; year < YEARS; year++)
            subtot += rain[year][month];
        printf("%4.1f ", subtot / YEARS);
    }
    printf('\n');
    system("pause");
    return 0;
}

运行结果为:

 Year            rainfall (inches)
 2014            53.8
 2015            49.3
 2016            44.0
 2017            46.3
 2018            44.6

 The yearly average is 47.6 inches.

 Monthly averages:

 Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec
 2.6  1.7  0.7  4.5  6.4  5.4  3.6  6.2  6.2  2.4  3.9  4.0

以上程序中使用了两个嵌套的for循环。第1个嵌套for循环的内层循环,在year不变的情况下,遍历month计算某年的总降水量;而外层循环,改变year的值,重复遍历month,计算5年的总降水量。这种嵌套循环结构常用于处理二维数组,一个循环处理数组的第1个下标,另一个循环处理数组的第2个下标:

for (year = 0, total = 0; year < YEARS; year++) {
    //循环每一年的数据
    for (month = 0, subtot = 0; month < MONTHS; month++)
        ...//循环和处理每月的数据
    ...//处理每一年的数据
}

第2个嵌套for循环和第1个的结构相同,但是内层循环遍历year,外层循环遍历month:

for (month = 0; month < MONTHS; month++) {
    //循环每个月的数据
    for (year = 0, subtot = 0; year < YEARS; year++)
        ...//循环和处理每年的数据
    ...//处理每个月的数据
}

注意:每执行一次外层循环,就完整遍历一次内层循环。

初始化二维数组- 10.2.2 -

在以上示例的代码中已经演示了二维数组的初始化形式。对于二维数组rain[YEARS][MONTHS]来说,一维YEARS有5个元素,二维MONTHS有12个元素,因此总共有60(即5*12)个元素需要初始化。可以使用示例中的方式,在初始化时使用5个数值列表,每个数值列表都用花括号括起来。形式如下:

float rain[5][12] = {
    {...},
    {...},
    {...},
    {...},
    {...}
};

此外,初始化时也可以省略内部的花括号,只保留最外面的一对花括号,只要保证初始化的数值个数正确即可。如果初始化的数值不够,则会按照先后顺序逐行初始化,直到用完所有的值。形式如下:

float rain[5][12] = {...};

其他多维数组- 10.2.3 -

二维数组的有关内容同样适用于三维或更多维数组,以下声明了一个三维数组:

int box[10][20][30];

可以把一维数组想象成一行数据,把二维数组想象成数据表,把三维数组想象成一叠数据表。此外,还可以把三维数组看作是数组的数组。即box内含10个元素,每个元素是内含20个元素的数组,这20个元素中的每一个元素又是内含30个元素的数组。或者干脆简单的根据下标值来理解数组。

一般情况下,处理三维数组需要3重嵌套循环,处理四维数组需要4重嵌套循环,以此类推。