现在我们看完整的程序
我们要同学们写一个程序
随机成生8个10到99之间的整数
然后保存到我们的数组里边
然后我们把这些元素给它倒过来
我们怎么实现这段代码呢
定义一个数组操纵库
这个库就叫arrmanip
像这样一个库
它对应一个“.h”、 一个“.cpp”这两个文件
在“.h”里边我们将写的
数组操纵库所提供的这一系列接口
因为我们这里边
没有什么数据类型需要公开
我们只有简单的四个函数原型：
GenerateIntegers、ReverseIntegers、
SwapIntegers、PrintIntegers
第一个我要能够生成8个整数
放到这个数组里
第二个我能够把这个数组
给我逆过来 怎么逆呢
这就要涉及到
其中两个数组元素的颠倒
所以我们有一个SwapIntegers
来颠倒数组里边的a[i]和a[j]这两个元素
还有一个PrintIntegers
要能够把这个数组完全打印出来
GenerateIntegers这个我们就不解释了
ReverseIntegers就是要逆这个数组
这个时候它需要双参数
其它附加参数我们不需要的
就int a[], unsigned int n
然后PrintIntegers一样
也是双参数
SwapIntegers呢
因为我们操作的不是这个数组的整体
其实只操作这个数组的
第i号元和第j号元
所以我要传这个数组
另外呢 我传两个
要操纵的元素的下标
i和j
我还要传这个数组元素个数n吗
其实不需要
这就是arrmanip这个库的头文件
也就是它的接口
有了这个接口
我们其实就可以设计主程序
我们要包含arrmanip
我们包含的是自己的头文件 自己的库
所以使用双引号 而不是使用尖括号
然后我们定义了一个宏NUMBER_OF_ELEMENTS
八个元素 然后是
const int lower_bound, const int upper_bound
初始化成10和99
在main函数里边定义一个数组
int a[NUMBER_OF_ELEMENTS]
然后我们生成这个数组的8个元素
生成以后我们就cout
把这个数组输出出来
看看我们实际生成的那8个元素
是什么样子
然后调用ReverseIntegers
把这个数组逆过来 在此之后
我又继续调用PrintIntegers
把这个数组再输出一遍
看看这个数组是不是真地
被我们逆过来了 然后return 0
我们主程序就结束了
这个程序实际上非常清楚
因为接口已经有了
按照接口的格式调用
就能够完成我们的“main.cpp”的主框架
现在难的问题在哪里呢
难就难在这四个函数
到底应该怎么去实现
第一个函数GenerateIntegers
我们已经介绍过了
第二个函数就是ReverseIntegers
我们把a[i]和a[j]这两个元素逆过来
0号元、7号元逆
1号元、6号元逆
2号元、5号元逆
按照这个方式去操作
那我这个程序应该怎么写呢
我要写一个for循环
我颠倒的这俩元素之间
到底有啥规律呢
0号元和7号元 1号元和6号元……
简单一观察你就知道
我要颠倒是这两个元素下标之和
刚好等于我们的元素个数减1
不是八个元素吗
所以要颠倒0号元和7号元
0加7是7
要颠倒是1号元和6号元
1加6是7
所以如果我们要颠倒a[i]这个元素
那么它的相对应的那个元素就是a[n-1-i]
我们找到这个规律
完成这个颠倒就行了
问题在于什么呢
这个for循环呢 i从0开始没问题
中间那个条件表达式你不能写i<n
你只能写什么呢 i<n/2
你如果真写i<n
我跟你说你这个程序 压根就没颠倒
它真没颠倒吗 不是
它不仅颠倒了
实际上给你颠倒了两遍
它把0号元和7号元颠倒
1号元和6号元颠倒……
它最终还会把6号元和1号元颠倒
7号元和0号元颠倒
也就是说 它倒腾一遍逆过来了
它又倒腾了一遍又逆回去了
做了两次 整个这个数组压根就没变
所以我们在逆的时候
只要到它的数组的一半的位置就OK了
i<n/2就可以了
因为这个n/2是整数除法
出来的结果就是一个整数
对于这个八个元素的数组
i<n/2 结果就是i<4
所以它操作下标0、1、2、3
正好是前四个元素
一点问题都没有的
我们这一颠倒
所有元素就全部颠倒完成了
如果这个数组很不幸 它是奇数个数
你比如9个元素数组
你9/2的话结果还是4
也就是说它只能完成0、1、2、3
和对应的8、7、6、5完成对调
中间几号元呢 四号元哪
它就没有被对调 那个少一个
一点关系都没有
因为它正好是正中间那个元素
如果对调的话 也是和它自己对调
所以操不操作它 一点关系都没有
至于这个a[i]和a[j]这两个元素怎么对调
我们就完成这个标准的三步互换就完了嘛
然后PrintIntegers打印数组
还是刚才那个样子 双参数
写一个for循环
输出这个数组每一个元素就完了
接下来一个概念就是多维数组
有了刚才那个单维数组的定义
我们可以很自然地把这个数组
给扩充到多维 数学上来讲
它就相当于一个一维的一个向量
那么我们很自然地
就给它扩充到一个平面
它是二维的一个矩阵
然后你还可以很自然地扩充到三维
那就相当于什么
相当于立体的一个数据
更高维的话 我们就只能凭借想象
在现实生活中就很难对应了
多维数组的定义
在我们C++代码里边它就用了
中括号、中括号、中括号
就按照这个方式来定义就完了
你看int a[2][2]
就表示我定义一个2乘2的
一个二维数组
int b[2][3][4]
就定义2乘3乘4的三维的一个数组
多维数组进行初始化的时候
要特别记得 它有两种初始化的方式
像int a[2][3]
你就认为它就是一个6个元素的数组
两行三列 总共是6个元素
像一维数组一样写它
还有一种呢 就是第二种数组化方案
int a[2][3]
这个数组包含几个元素呢
包含两个元素
每个元素是包含三个元素的整数数组
所以第一个元素写{1,2,3}
第二个元素写{4,5,6}
我建议同学们按照第二种方式写
它有什么好处呢
你事实上可以通过一个巧妙的排版
让这个书写的格式
就像数学上的一个矩阵一样
当在计算机内部
保存我们这个多维数组的时候
同学们一定要记得
它同单维数组一样
前边没有任何控制标志
后边没有任何结束标志 都没有
中间绝不会有空格
它就是一个元素 一个元素顺序放
但是我们这是两维呀
所以它就要先行后列
这是一个数组a[0]
它是两个元素的一个数组
所以是a[0][0]、a[0][1]
放完a[0]行放a[1]行
a[0][0]、a[0][1]、a[1][0]、a[1][1]
就按照这个顺序放
我们看这样一个例子
就是测量湖泊的水深
正常情况下我们要在湖泊上面
等距离地打上网格
分别测量每个网格的这个水深
然后就可以描述这个湖泊真实的情况
你看到02号这个网格
它的水深是一米深
然后03号这个网格 水深是2米
我们知道每一个小网格是25平方米
那么我们就数
这个二维数组里边到底有多少个网格
水深是大于0的
它不是湖岸
数出来乘上25平方米
我们就算出来这个湖泊的面积了
然后我们要算出什么呢
就是它的平均水深是多少米
第一 我要知道这个湖泊的面积
第二个呢 我得要算这个湖泊的水深
也就是我们要算这个总水深
累加总水深 除以网格数
我们就能够算出来它的平均的水深
那么我们怎么去实现这段代码呢
对于这道题啊
我们就要定义这个二维的数组
我们刚才x轴的网格数是9个
y轴的网格数是4个
我们定义这两个宏
然后我们定义了这个浮点数的数组
然后是湖的网格的宽度
一开始初始化的时候
湖的这个网格数是0.0
湖区的面积是0.0
然后是整个的湖的总深度是0.0
平均水深是0.0
我定义两个循环变量i、j
然后写for循环
因为我们是二维数组嘛
我要一个一个网格算
对于多维的数组
一定要用一个多重的for循环
两维数组我们往往要用两重的for循环
有时甚至需要三重的for循环去做处理
我们这里面两重就够了
一个for循环 i下标从0开始
i<NUM_OF_Y_GRIDS 然后i++
我去算网格数
这就是每一行的网格 我要算
y是行 x是列
我们算i这一行所有网格数
我要写一个for循环 看它的每一列
j从0开始
j< NUM_OF_X_GRIDS
如果它的湖区的深度
是大于0的（其实我们这里面应该写大于0.0）
那么网格数累加1
第二 整个湖每一个网格的深度
一个一个地累加上去
这个二重的for循环一做完
我就数出来了
这个湖面总共有多少个网格
第二个
在这些网格中所有的水深之和是多少
每个网格的宽度和长度是固定的
五米乘五米嘛
那么有了这个网格数
我立即乘上25平方米
就能得到湖的面积
然后立即就能够得到湖的平均水深
这个水深就是总水深除以网格数
这个就是二维数组处理的方案