17.1 研究数据表示

让我们从考虑数据开始。假设您需要创建一个地址簿程序。您将使用何种数据形式来存储信息?因为与每个项目相关的信息有很多类别,所以用一个结构来表示每一个项目显得很适合。如何表示多个项目?是标准的结构数组、动态数组,还是其他形式?各个项目需要按字母顺序排列吗?需要能够按照邮政编码(或地区编码)来搜索项目吗?需要执行的动作将影响到您对如何存储信息的决定。简而言之,在开始编写代码之前,您需要做出许多设计上的决定。

如何表示想在内存中存储的一幅位图图形?在位图图形中,屏幕上的每一个像素都单独进行设置。在黑白显示屏的时代里,可以使用计算机中的1位(1或0)来表示一个像素(开或关),因而称为位图(bitmapped)。对于彩色显示器来说,描述一个像素需要不止一位。比如,如果每一个像素使用8位,可以得到256种颜色。现在,行业标准已经发展到65 536色(每像素16位)、16 777 216色(每像素24位)、2 147 483 648色(每像素32位),甚至更多。如果有1 600万种颜色,并且显示器的分辨率为1 024×768,将需要1 890万位(2.25MB)来表示一个屏幕大小的位图图形。就这样进行表示,还是开发一种压缩信息的方法?压缩应该是无损的(lossless,没有数据丢失),还是有损的(lossy,丢失相对次要的数据)?在开始编写代码之前,您再次需要做出许多设计决定。

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

让我们来看一个数据表示的实例。假设您想要写一个程序来输入您一年中看过的所有电影(包括录像带和DVD)的列表。对每一部电影,您想记录各种信息,比如片名、发行年份、导演、主演、片长、影片类别(喜剧、科幻、爱情、传奇,诸如此类),您的评价等。根据这种情况,可以对每一部电影使用一个结构,对电影列表使用结构数组。为了简化,我们将结构限制为只有两个成员:片名和您的评价(分为0到10十个等级)。程序清单17.1是使用这种方法的简单实现。

程序清单 17.1 filmsl.c程序

阅读 ‧ 电子书库

阅读 ‧ 电子书库

程序创建了一个结构数组,然后把用户输入的数据填充到这个数组中。直到数组满(FMAX判断),或者到达文件结尾(NULL判断),或者用户在行首按下回车键(‘\0’判断),输入才会终止。

这种方法有些问题。首先,程序很可能会浪费大量空间,因为大多数电影的片名并没有40个字符,但是有些电影片名的确很长,比如The Discreet Charm of the BourgeoisieWon Ton Ton,The Dog Who Saved Hollywood。第二,很多人会觉得每年5部电影的限制太严格了。当然,可以放宽这个限制,但是,多大的值比较合适呢?有些人每年看500部电影,所以可以将FMAX增加到500;但是,对于有的人来说,这可能仍然太小,但是对别人来说可能浪费大量的内存。同时,有些编译器对像movies这样的自动存储类变量可用的内存大小设置了一个默认的限制,如此之大的数组可能会超过那个值。这可以通过将数组声明为静态或外部数组,或者指示编译器使用更大的堆栈来解决,但这样并不能解决根本问题。

这里的根本问题是数据表示方法太不灵活。您必须在编译时做出决定,而事实上在运行时做这些决定会更好。这就表明您应该转向使用动态内存分配的数据表示。您可以尝试以下方法:

阅读 ‧ 电子书库

这里,正如在第12章“存储类、链接和内存管理”中描述的那样,您可以将指针movies当作一个数组名:

阅读 ‧ 电子书库

通过使用malloc(),可以将确定元素个数的时间延迟到程序运行时。所以如果只需要20个元素,程序就无须分配存放500个元素的空间。当然,这要求用户为元素个数提供正确的值。