【C++学习】第七章 数组 7.5-7.8节

网友投稿 2019-04-09 10:59

《信息学奥赛C++培训教程》共计八章,主要用于编程语言C++的基础学习,适用于C++初学者。
第7章 数组7.5  将数组传递给函数

要将数组参数传递给函数,需指定不带方括号的数组名。例如,如果数组hourlyTemperatures声明如下:

int hourlyTemperatures[24];

则下列函数调用语句:

modifyArray(hourlyTemperatutes,24);

将数组hourlyTemperatures及其长度传递给函数modifyArray。

将数组传递给函数时,通常也将其长度传递给函数,使函数能处理数组中特定的元素个数(否则要在被调用函数中建立这些信息,甚至要把数组长度放在全局变量中)。

第7章介绍Array类时,将把数组长度设计在用户自定义类型中,每个Array对象生成时都“知道”自己的长度。这样,将Array对象传递给函数时,就不用把数组长度作为参数一起传递。

C++使用模拟的按引用调用,自动将数组传递绐函数,被调用函数可以修改调用者原数组中的元素值。数组名的值为数组中第一个元素的地址。由于传递数组的开始地址,因此被调用函数知道数组的准确存放位置。因此,被调用函数在函数体中修改数组元素时.实际上是修改原内存地址中的数组元素。

尽管模拟按引用调用传递整个数组,但各个数组元素和简单变量一样是按值传递。这种简单的单个数据称为标量(scalar 或scalar quanity)。要将数组元素传递给函数,用数组元素的下标名作为函数调用中的参数。第5章将介绍标量(即各个变量和数组元素)的模拟按引用调用。

要让函数通过函数调用接收数组,函数的参数表应指定接收数组。例如,函数modifyArray的函数苜部可能如下所示:

void modifyArray(int b[],int arraySize)

表示modifyArray要在参数b中接收整型数组并在参数arraySize中接收数组元素个数。

数组方括号中的数组长度不是必需的,如果包括,则编译器将其忽略。由于模拟按引用调用传递数组,因此被调用函数使用数组名b时,实际上引用调用者的实际数组(上例中为数组hourlyTemperatures)。

第4章介绍表示函数接收数组的其他符号,这些符号基于数组与指针之间的密切关系。

注意modlfyArray函数原型的表示方法:

void modifyArray(int[],int);

这个原型也可以改写成:

void modifyArray( int anyArrayName[],int( anyVariableName )

但第2章曾介绍过,C++编译器忽略函数原型中的变量名。

图7.14的程序演示了传递整个数组与传递数组元素之间的差别。

程序首先打印整型数组a的五个元素,然后将a及其长度传递给函数modifyArray,其中将a数组中的元素乘以2,然后在main中重新打印a。从输出可以看出,实际由modifyAnay修改a的元素。现在程序打印a[3]的值并将其传递给函数modifyElement。函数modifyElement将参数乘以2。然后打印新值。注意在main中重新打印a[3]时,它没有修改,因为各个数组元素是按值调用传递。

1 // Fig. 7.14: fig07_14.cpp

2 // Passing arrays and individual arrayelements to functions

3 #include

4 #include

5

6 void modifyArray( int [], int );  // appears strange

7 void modifyElement( int );

8

9 int main()

10 {

11   const int arraySize = 5;

12   iht i, a[ arraySize ] = { 0, 1, 2, 3, 4 };

13

14    cout << "Effects of passing entirearray call-by-reference:"

15       << "nnThe values of the original array are:n";

16

17 for( i=0;i< arraySize; i++ )

18     cout(<< setw( 3 ) << a[ i ];

19

20   cout << endl;

21

22   // array a passed call-by-reference

23   modifyArray( a, arraySize );

24

25   cout << "The values of the modified array are:n";

26

27   for ( i = 0; i < arraySize; i++ )

28     cout << setw( 3 ) << a[ i ] ;

29

30   cout << "nnn"

31       << "Effects of passing array element call-by-value:"

32   <<"nnThe value of a[3] is "<< a[3] <<'n';

33

34    modifyElement( a[ 3 ] );

35

36    cout << "The value of a[ 3 ] is "<< a[ 3 ]<< endl;

37

38    return 0;

39 }

4O

41 void modifyArray( int b[ ], intsizeofArray )

42 {

43    for ( int j = 0; j < sizeofArray; j++ )

44       b[ j ] *= 2;

45 }

46

47 void modifyElement( int e )

48 {

49    cout << "Value in modifyElement is"

50       <<(e *= 2 ) << endl;

51 }

输出结果:

Effects of passing entire arraycall-by-Value:

The values of the original array are:

    0 1 2 3 4

The values of the modified array are:

    0 2 4 6 8

Effects of passing array elementcall-by-value:

The value of a[3] is 6

Value in modifyElement is 12

The value of a[3] is 6

图7.14  向函数传递数组和数组元素

有时程序中的函数不能修改数组元素。由于总是模拟按引用调用传递数组.因此数组中数值的修改很难控制。C++提供类型限定符const,可以防止修改函数中的数组值。数组参数前面加上const限定符时,数组元素成为函数体中的常量,要在函数体中修改数组元素会造成语法错误。这样,程序员就可以纠正程序,使其不修改数组元素。

图7.15演示了const限定符。

函数tryToModifyArray定义参数const int b[],指定数组b为常量,不能修改。函数想修改数组元素会造成语法错误“Canot modify const object”。

const限定符将在第6章再次介绍。

1 // Fig. 7.15: fig07_15.cpp

2 // Demonstrating the const type qualifier

3 #include

4

5 void tryToModifyArray( const int [] );

6

7 int main()

8 {

9    int a[] = {10,20,30};

10

11   tryToModifyArray( a );

12   cout << a[ 0 ] << ' ' << a[ 1 ] << ' ' <<a[ 2="" ]="" <<="" 'n';<="" p="">

13   return 0;

14 }

15

16 void tryToModifyArray( const int b[] )

17 {

18   b[ 0 ] /= 2;   // error

19   b[ 1 ] /= 2;   // error

20   b[ 2 ] /= 2;   // error

21 }

输出结果:

Compiling FIG07_15.CPP:

Error FIG07_15.CPP 18: Canot modify a constobject

Error FIG07_15.CPP 19: Canot modify a constobject

Error FIG07_15.CPP 20: Canot modify a constobject

Warning FIG07_15.CPP 21: Parameter 'b' isnever used

图7.15  演示const限定符

7.6  排序数组 排序(sort)数组(即将数据排成特定顺序,如升序或降序)是一个重要的计算应用。银行按账号排序所有支票,使每个月末可以准备各个银行报表。电话公司按姓氏排序账号清单并在同一姓氏中按名字排序,以便于找到电话号码。几乎每个公司都要排序一些数据,有时要排序大量数据。排序数据是个复杂问题,是计算机科学中大量研究的课题。

图7.16的程序排列10个元素数组a的值,按升序排列。我们使用冒泡排序(bubble sortsinkingsort)方法,较少的数值慢慢从下往上“冒”,就像水中的气泡一样,而较大的值则慢慢往下沉。这个方法在数组中多次操作,每一次都比较一对相邻元素。如果某一对为升序(或数值相等),则将数值保持不变。如果某一对为降序,则将数值交换。

1 // Fig. 7.16:fig07_16.cpp

2 // This program sorts an array's valuesinto

3 // ascending order

4 #include

5 #include

6

7 int main{)

8 {

9  const int arraySize = 10;

10 int a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };

11 int i, hold;

12

13 cout << "Data items in original ordern";

14

15 for ( i = 0; i < arraySize; i++ )

16    cout << setw( 4 ) << a[i ] ;

17

18 for (int pass = 0; pass < arraySize - 1; pass++ ) // passes

19

20    for ( i = 0; i < arraySize - 1; i++ )     // one pass

21

22       if ( a[i ] > a[i + 1 ] ) {    // one comparison

23         hold  a[i ];              // one swap

24         a[i ] = a[i + 1 ];

25         a[i + 1 ] = hold;

26       }

27

28  cout << "nData items in ascending ordern";

29

30  for ( i = 0; i < arraySize; i++ )

31    cout << setw( 4 ) << a[ i ];

32

33  cout << endl;

34  return 0;

35 }

输出结果:

 Data  items  in  oriqinal  order

   2    6   4    8    10   12    89    68   45    37

   Data  items  in ascendinq  order

   2    4    6   8    10    12   37    45    68   89

图7.16用冒泡法排序数组

程序首先比较a[0]与a[1],然后比较a[1]与a[2],接着是a[2]与a[3],一直到比较a[8]与a[9]。尽管有10个元素,但只进行9次比较。由于连续进行比较,因此一次即可能将大值向下移动多位,但小值只能向上移动一位。第1遍,即可把最大的值移到数组底部,变为a[9]。第2遍,即可将第2大的值移到a[8]第9遍,将第9大的值移到a[1]。最小值即为a[0],因此,只进行9次比较即可排序10个元素的数组。

排序是用嵌套for循环完成的。如果需要交换,则用三条赋值语句完成:

   hold = a[ i ];;

   a[i] = a[ i+1 ];

   a[ i+1 ] = hold;

其中附加的变量hold临时保存要交换的两个值之一。只有两个赋值语句是无法进行交换的:

   a[ i ] = a [ i+1 ];

   a[ i+l] =a[ i];

例如,如果a[i]为7而a[i+1]为5.则第一条赋值语句之后,两个值均为5,数值7丢失,因此要先用变量ho1d临时保存要交换的两个值之一。

冒泡排序的主要优点是易于编程。但冒泡排序的速度很慢,这在排序大数组时更明显。练习中要开发更有效的冒泡排序程序,介绍一些比冒泡排序更有效的方法。高级课题中将介绍更深入的排序与查找问题。

7.7  查找数组:线性查找与折半查找

程序员经常要处理数组中存放的大量数据,可能需要确定数组是否包含符合某关键值(key value)的值。寻找数组中某个元素的过程称为查找(searching)。本节介绍两个查找方法:简单的线性查找(liner search)方法和更复杂的折半查找(binary search)方法。

图7.19的线性查找比较数组中每个元素与查找键(search key)。

由于数组没有特定的顺序,很可能第一个就找到,也可能要到最后一个才找到。因此,平均起来,程序要比较数组中一半的元素才能找到查找键值。要确定哪个值不在数组中,则程序要比较查找键与数组中每一个元素。

1 // Fig. 7.19: fig07_19.cpp

2 // Linear search of an array

3 #include

4

5 int linearSearch( const int [], int, int);

6

7 int main()

8 {

9   const int arraySize = 100;

10  int a[ arraySize ], searchKey, element;

11

12  for(int x = 0; X < arraySize; x++ ) // create some data

13      a[ x ] = 2 * x;

14

15  cout << "Enter integer search key:" << endl;

16  cin >> searchKey;

17  element = linearSearch( a, searchKey, arraySize );

18

19  if ( element != -1 )

20    cout << "Found value in element " << element<< endl;

21  else

22    cout << "Value not found" << endl;

23

24  return 0;

25 }

26

27 int linearsearch( const int arraay[],int key, int sizeofArray )

28 {

29   for (int n = 0; n < sizeofArray; n++ )

30    if(  arraay[ n ] == key )

31       return n;

32

33   return -1;

34 }

输出结果:

Enter integer search key:

36

found value in element 18

Enter integer search key:

 37

Value not found

图7.19数组的线性查找

线性查找方法适用于小数组或未排序数组。但是,对于大数组,线性查找是低效的。如果是排序数组,则可以用高速折半查找。折半查找算法在每次比较之后排除所查找数组的一半元素。这个算法找到数组的中间位置,将其与查找键比较。如果相等,则已找到查找键,返回该元素的数组下标。否则将问题简化为查找—半数组。如果查找键小于数组中间元素,则查找数组的前半部分,否则查找数组的后半部分。如果查找键不是指定子数组(原始数组的一部分)中的中间元素,则对原数组的四分之—重复这个算法。查找一直继续,直到查找键等于指定子数组中的中间元素或子数组只剩一个元素且不等于查找键(表示找不到这个查找键)为止。

在最糟糕的情况下,查找1024个元素的数组只要用折半查找进行十次比较。重复将1024除2(因为折半查找算法在每次比较之后排除所查找效组的一半元素)得到值512、256、128、64、32、16、8、4、1和1。数值1024(210)除2十次之后即变成1。除以1就是折半查找算法的一次比较。1048576(220)个元素的数组最多只要20次比较就可以取得查找键。十亿个元素的数组最多只要30次比较就可以取得查找键。这比线性查找的性能大有提高,后者平均要求比较数组元素个数一半的次数。对于十亿个元素的数组,这是5亿次比较与30次比较的差别。折半查找所需的最大比较次数可以通过大于数组元素个数的第一个2的次幂的指数确定。

图7.20显示了函数binarySearch的迭代版本。

函数取4个参数,一个整数数组b、一个整数searehKey、low数组下标和high数组下标。如果查找键不符合于数组的中间元素,则调整low数组下标和high数组下标,以便查找更小的子数组。如果查找键小于中间元素,则high数组的下标设置为middle-1,继续查找low到middle-1的元素。如果查找健大于中间元素,则low数组的下标设置为middle+1,继续查找middle+1到high的元素。程序使用15个元素的数组。大于数组元素个数的第一个2的次幂是16(24),因此寻找查找健最多只要四次比较。函数printHeader输出数组下标,函数printRow输出折半查找过程中的每个子数组。每个子数组的中间元素标上星号(*),表示用这个元素与查找键比较。

1 // Fig. 7.20: fig07_20.cpp

2 // Binary search of an array

3 #include

4 #include

5

6 int binarySeareh( int [], int, int, int,int );

7 void printHeader( iht ,

8 void printRow( int [], int, int, int, int);

9

10 int main()

11 {

12    const iht arraySize = 15;

13    int a[ arraySize ], key, result;

14

15    for ( int i = 0; i < arraySize; i++ )

16       a[ i ]= 2 * i;     // place somedata in array

17

18    cout << "Enter a number between 0 and 28: ";

19    cin >> key;

20

21    printHeader( arraySize );

22    result = binarySearsh( a, key, 0, arraySize - 1, arraySize );

23

24             if ( result != -1 )

25      cout << 'n' << key << "found in arrayelement"

26            << result << endl;

27             else

28                  cout << 'n' <<key <<="" "not="" found"="" endl;<="" p="">

29

30             return 0;

31 }

32

33 //

34 int binarysearch( int b[ ], intsearchKey, int low, int high,

35                                   int size )

36 {

37   int middle;

38

39     while ( low <= high ) {

40       middle = ( low + high ) / 2;

41

42       printRow( b, low, middle, high, size );

43

44     if ( searchKey == b[ middle ] ) // match

45         return middle;

46     else if ( searchKey < b[ middle ] )

47         high = middle - 1;      // searchlow end of array

48     else

49        low = middle + 1;       // searchhigh end of array

50    }

51

52   return -1;  // searchKey not found

54

55 // Print a header for the output

56 void printHeader( int size )

57 {

58   cout << "nSubscripts:n";

59   for (int i = 0; i < size; i++ )

60       cout << setw( 3 ) << i << ' ';

61

62    cout << 'n';

63

64    for ( i = 1; i <= 4 * size; i++ )

65        cout << '-';

66

67    cout << endl;

68 }

69

70 // Print one row of output showing thecurrent

71 // part of the array being processed.

72 void printRow( int b[ ], int low, intmid, int high, int size )

73 {

74     for ( int i = 0; i < size; i++ )

75        if ( i < low || i > high )

76            cout << "   ";

77        else if ( i == mid )         //mark middle value

78             cout << setw( 3 ) <<b[ i="" ]="" <<="" '*';<="" p="">

79        else

80             cout << setw( 3 ) <<b[ i="" ]="" <<="" '="" ';<="" p="">

81

82     cout << endl;

83 }

输出结果:

Enter a number between 0 and 28:25

Subscripts:

    0    1   2    3    4   5    6    7   8    9    10   11    12    13   14

  -------------------------------------------------------------------

    0    2   4    6    8   10   12   14* 16  18   20   22    24    26   29

                                          16   18   20   22*   24    26   28

                                                                  24    26*  28

                                                                24*

25 not found

Enter a number between 0 and 28: 8

   Subscripts:

    0    1   2    3    4   5    6    7   8    9    l0   ll    12    13   14

   ------------------------------------------------------------------

    0    2   4    6    8   l0   12   14* 16   18   20   22    24    26   28

    0    2   4    6*   8   10   12

                       8    l0* 12

                        8*

8 found  in  array element  4

Enter a  number  between 0  and  28:  6

Subscrlpts:

    0    l   2    3    4   5    6    7   8    9    10   11    12    13   14

  -------------------------------------------------------------------

    0   2    4    6   8   10   12  14*  16  18  20    22    24   26    28

    0    2   4    6*   8  10   12

6 found  ln  array element  3

图7.20排序数组的折半查找过程

7.8  多维数组

C++中有多维数组。多维数组常用于表示由行和列组成的表格。要表示表格中的元素,就要指定两个下标:习惯上第一个表示元素的行,第二个表示元素的列。

 用两个下标表示特定的表格或数组称为二维数组(double-subscriptedarray)。注意,多维数组可以有多于两个的下标,C++编译器支持至少12个数组下标。

图7.21演示了二维数组a。

数组包含三行四列,因此是3 x 4数组。一般来说,m行和n列的数组称为m x n数组。

数组a中的每个元素如图7.21所示,元素名字表示为a[i][j],i和j是数组名,i和j是惟一标识a中每个元素的下标。注意第一行元素名的第一个下标均为0,第四列的元素名的第二个下标均为3。

把二维数组元素a[x][y]误写成a[x,Y]。实际上,a[x,y]等于a[y],因为C++将包含返号运算符的表达式(x,y)求值为y(逗号分隔的表达式中最后一个项目)。

多维数组可以在声明中初始化,就像一维数组一样。例如,二维数组b[2][2]可以声明和初始化如下:

int b[2][2] = { { l, 2 },  { 3,4 } };

数值用花括号按行分组,因此1和2初始化b[0][0]和b[0][1],3和4初始化b[1][0]和b[1][1]。

如果指定行没有足够的初始化值,则该行的其余元素初始化为0。这样,下列声明:

int b[2][2] = { { 1 },{  3,4 } };

初始化b[0][0]为1、b[0][1]为0、b[1][0)]为3、b[1][1]为4。

图7.22演示了声明中初始化二维数组。

程序声明三个数组,各有两行三列。array1的声明在两个子列表中提供六个初始化值。第一个子列表初始化数组第一行为1、2、3,第二个子列表初始化数组第二行为4、5、6。如果从array1初始化值列表中删除每个子列表的花括号,则编译器自动先初始化第一行元素,然后初始化第二行元素。

array2声明提供六个初始化值。初始化值先赋给第一行,再赋给第二行。任何没有显式初始化值的元素都自动初始化为0,因此array2[1][2]自动初始化为0。

1 // Fig. 7.22: fig07_22.cpp

2 // Initializing multidimensional arrays

3 #include

4

5 void printArray( int [][ 3 ] );

6

7 int main()

8 {

9  int arrayl[ 2 ][ 3 ] = { { 1, 2, 3 }, { 4, 5, 6 } },

10    array2[ 2][ 3]   { 1, 2, 3, 4, 5},

11    array3[ 2][ 3] ={ { 1, 2 }, { 4 } };

12

13 cout << "Values in arrayl by row are:" << endl;

14 printArray( array1 );

15

16 cout << "Values in array2 by row are:" << endl;

17 printArray( array2);

18

19 cout << "Values in array3 by row are:" << endl;

20 printArray( array3 );

21

22 return 0;

23 }

24

25 void printArray( int a[][ 3 ] )

26 {

27   for (int i = 0; i < 2; i++ ) {

28

29     for ( int j = 0; j < 3; j++ )

30        cout << a[ i ][ j ] << ' ';

31

32     cout << endl;

33   }

34 }

输出结果:

Values in array1 by row are:

1 2 3

4 5 6

Values in array2 by row are:

1 2 3

4 5 0

Values in array3 by row are:

1 2 0

4 0 0

图7.22初始化多维数组

array3的声明在两个子列表中提供3个初始化。第一行的子列表显式地将第一行的前两个元素初始化为1和2,第3个元素自动初始化为0。第二行的子列表显式地将第一个元素初始化为4,最后两个元素自动初始化为0。

程序调用函数printArray输出每个数组的元素。注意函数定义指定数组参数为int a[][3]。函数参数中收到单下标数组时,函数参数表中的数组括号是空的。多下标数组第一个下标的长度也不需要,但随后的所有下标长度都是必须的。编译器用这些长度确定多下标数组中元素在内存中的地址。不管下标数是多少,所有数组元素都是在内存中顺序存放。在双下标数组中,第一行后面的内存地址存放第二行。

在参数声明中提供下标使编译器能告诉函数如何找到数组中的元素。在二维数组中,每行是一个一维数组。要找到特定行中的元素,函数要知道每一行有多少元素,以便在访问数组时跳过适当数量的内存地址。这样,访问a[1][2]时,函数知道跳过内存中第一行的3个元素以访问第二行(行1),然后访问这一行的第3个元素(元素2)。

许多常见数组操作用for重复结构。例如,下列for结构(见图7.21)将数组a第三行的所有元素设置为0:

for(column=0;coulumn<4;column++)

   a[2][Column] =0;

我们指定第三行,因此知道第一个下标总是2 (0是第一行的下标,1是第二行的下标)。for循环只改变第二个下标(即列下标)。上述for结构等同于下列赋值语句:

   a[2][0]=0;

   a[2][1]=0;

   a[2][2]=0;

   a[2][3]=0;

下列嵌套for结构确定数组a中所有元素的总和:

total = 0;

for ( row = 0; row < 3; row++ )

     for( column = 0; column < 4; column++ )

         total += a [ row ] [ column ] ;

for结构一次一行地求数组中所有元素的和。外层for结构首先设置row(即行下标)为0,使第一行的元素可以用内层for结构求和。然后外层for结构将row递增为1,使第二行的元素可以用内层for结构求和。然后外层for结构将mw递增为2,使第三行的元素可以用内层for结构求和。结束嵌套br结构之后,打印结果。

    图7.23的程序对3 x 4数组studentCrades进行几个其他常见数组操作。

每行数组表示一个学生,每列表示学生期末考试中4门成绩中的一门成绩。数组操作用4个函数进行。函数mimimum确定该学期所有学生考试成绩中的最低成绩。函数maximum确定该学期所有学生考试成绩中的最高成绩。函数average确定每个学生该学期的平均成绩。函数printArray以整齐的表格形式输出二维数组。

1 // Fig. 7.23: fig07_23.cpp

2 // Double-subscripted array example

3 #include

4 #include

5

6 const iht students = 3;  // number of students

7 const iht exams = 4;     // number of exams

8

9 int minimum( int [][ exams ], int, int );

10 int maximum(int [][ exams ], int, int };

11 float average( int [], int );

12 void printArray( int [][ exams ], int,int );

13

14 int main()

I5 {

16   int studentGrades[ students ][ exams ] =

17        { { 77, 68, 86, 73 },

18          { 96, 87, 89, 78 },

19          { 70, 90, 86, 81 } };

20

21   cout << "The array is:n";

22   printArray( studentGrades, students, exams );

23   cout << "nnLowest grade: "

24       << minimum( studentGrades, students, exams )

25       << "nHighest grade:"

26       << maximum( studentGrades, students, exams ) << 'n';

27

28   for ( int person = 0; person < students; person++ }

29    cout << "The average grade for student" << person<< "is"

3O

31   <<  setprecision(  2  )

32        << average( studentGrades[ person ], exams ) << endl;

33

34      return 0;

35

36

37 // Find the minimum grade

38 int minimum( int grades[][ exams ], intpupils, int tests )

39 {

40  int lowGrade = 100;

41

42  for ( int i = 0; i < pupils; i++ )

44     for ( int j = 0; j < tests; j++ )

45

46        if ( grades[ i ][ j ] < lowGrade )

47            lowGrade = grades[ i ] [ j ];

48

49         return lowGrade;

50 }

51

52 // Find the maximum grade

53 int maximum( int grades[][ exams ], ihtpupils, iht tests )

54 {

55  int highgrade = 0;

56

57  for ( int i = 0; i < pupils; i++ )

58

59    for (int j = 0; j < tests; j++ )

60

61  if ( grades[ i ][ j ] > highgrade )

62     highgrade = grades[ i ][ j ];

63

64  return highgrade;

65 }

66

67 // Determine the average grade for aparticular student

68 float average(int setofGrades[],int tests)

69 {

70    int total = 0;

71

72    for ( int i = 0; i < tests; i++ )

73       total += setofGrades[ i ];

74

75    return ( float ) total / tests;

76 }

77

78 // Print the array

80 {

8I    cout <<"             [0 ]  [ 1 ]  [ 2 ] [ 3 ]";

83    for (int i = 0; i < pupils; i++ ) {

84        cout << "nstudentGrades[ "<< i << "]";

85

86        for(int j=0; j< p="">

87        cout << setiosflags( ios::left ) << setw( 5 )

88                    << grades[  i ][  j];

89  }

90

输出结果:

The array is:

                   [0] [1] [2] [3]

StudentGrades[ 0 ]  77 68  86  73

StudentGrades[ 1 ]  96 87 98 78

StudentGrades[ 2 ]  70 90   86  81

Lowest grade: 68

Highest grade: 96

The average grade for student 0 is 76.00

The average grade for student 1 is 87.50

The average grade for student 2 is 81.75

图 7.23 使用二维数组举例

函数minimum、maximum和printArray取得三个参数——studentGrades数组(在每个函数中调用grades)、学生数(数组行)、考试门数(数组列)。每个函数用嵌套for结构对grades数组循环。下列嵌套for结构来自函数mlmmum的定义:

   for(i = 0;i< p="">

       for(j = 0;j< p="">

           if(grades[i][j] < lowGrade)

               lowGrade = grades[i][i];

外层for结构首先将i(行下标)设置为0,使第一行的元素可以和内层for结构体中的变量lowGrade比较。内层for结构比较lowGrade与4个成绩中的每一门成绩。如果成绩小于lowGrade,则lowGrade设置为该门成绩。然后外层for结构将行下标加到1,第二行的元素与变量lowGrade比较。接着外层for结行下标加到2,第三行的元素与变量lowGrade比较。嵌套for结构执行完成后,lowGrade包含双下标数组中的最小值。函数maximum的执行过程与函数minimum相似。

函数average取两个参数:一个单下标数组为某个学生的考试成绩,一个数字表示数组中有几个考试成绩。调用average时,第一个参数studentGrades[student]指定将双下标数组studentGrades的特定行传递给average。例如,参数studentGrad[1]表示双下标数组studentGrades第二行中存放的4个值(成绩的单下标数组)。双下标数组可以看作元素是单下标数组的数组。函数average计算数组元素的和,将总和除以考试成绩的个数,并返回一个浮点数结果。

--end--

声明:本文章由网友投稿作为教育分享用途,如有侵权原作者可通过邮件及时和我们联系删除:freemanzk@qq.com