9.2 结构体

假如所有东西都是由数字或名称组成的,那么用C语言表示起来就会相当容易。比方说,假如每个人都可以单靠名字或者一系列数字来表示,那么人就变得跟车一样了,因为每辆车都能够通过唯一的VIN(Vehicle Identification Number,车辆识别码)确定身份,这个VIN概括了这辆车的各种属性。

我们用C语言编写一些程序是想解决现实之中的问题,因此,必须给现实中的复杂对象建模。C语言允许我们对现实物体的各个方面做出抽象,并通过C语言中的结构体为其建模。上一章其实已经用一种相当简单的手法研究了两种实际的对象,一种是扑克,另一种是二维图形(或者说平面图形)。然而我们并没有把这些对象的每个方面都研究到。

我们当时所提到的只是这些对象里面的一小部分属性。比方说扑克,我们只表示了每张牌的花色,而没有表示它的点数,要想把一副扑克中的52张牌全都表示出来,只靠花色是不够的。另外,我们可能还得考虑牌与牌之间的大小问题(例如黑桃比红桃大,点数为A的牌可能比其他点数的牌要大或者要小)。笔者后面会告诉大家怎样把52张不同的牌放在同一个集合里面,让这个集合能够表示出一整副扑克。但是现在,我们先要学习如何准确地表示这些牌。

与扑克类似,我们在上一章表示二维图形时,也只考虑到了其中一个相当基本的方面,就是边的数量(或者说,角的数量)。其实我们可能还想对这种图形执行其他操作,因此,或许还得考虑每条边的长度与每个角的大小,另外可能还要考虑图形的其他方面,例如表面积。

如果要在二维平面中绘制图形,那么需要考虑每个图形的横坐标与纵坐标,还要考虑绘制时所用的线条宽度、线条颜色、填充颜色,以及这些图形之间的叠放顺序等,另外可能还要考虑其他一些因素。与绘制该图形有关的因素,可以合起来用一个结构体表示,然而这个结构体里面的某些属性本身可能又是一个小的结构体,例如表示位置与颜色的属性就是如此。位置本身可以设计成一种包含x值与y值的结构体,以便与平面坐标系中的点(x, y)相对应。颜色本身则可以设计成一种包含四个值的结构体,前三个值是该颜色的R(Red红)、G(Green,绿)、B(Blue,蓝)分量,后一个值是透明度(当然,这只是表示颜色的一种办法而已,此外还有其他许多种办法)。

第6章讲了怎样计算某个年份是否为闰年。如果把日期(date)当作一个结构体,那么年份信息只是该结构体中的一小部分,除此之外我们还需要设计其他一些数据,以完整地表示出某个日期。实际上,这种用来表示日期与时间的结构体有可能会实现得相当复杂,因为我们想要在世界上的各种历法与各种时区之间准确地换算。

最后要注意的是,我们在考虑结构体的各个方面时,还必须同时考虑到这种结构体所支持的操作。这就好比我们在使用基本的数据类型时也要考虑这些类型所支持的操作。然而,由于结构体是针对具体的程序与问题来定制的,因此,我们必须让这些结构体支持特定的操作,使得开发者能够通过这些操作来操控该结构体以实现程序的需求,例如我们要提供设置与获取结构体中某项信息的操作,要提供在两个结构体之间做比较的操作,或者其他一些必要的操作,例如把某个时间段与结构体所表示的时刻相加,用以表示另一个时刻,或者把两个结构体所表示的颜色相混合,以形成另一种颜色等。另外,我们还要考虑怎样操控一组结构体,例如给它们排序、从中寻找某个特定的结构体,或者对它们执行其他操作等。