总之,实际程序开发通常不可能采用一个文件写一个程序的方式(除非程序很小,就像 我们开始学习时遇到的例子,实际上那些例子也牵涉到多个文件,因为每个程序都用到系统 的头文件),因为存在许多无法解决的困难,为此人们考虑了采用多个源文件开发一个程序 的方式。C 语言的设计本身就考虑了这个问题,并提供了一些支持机制。这里我们将以前一 章的程序实例为例,介绍这方面的情况。
采用多个源程序文件开发一个程序的过程通常称为分块开发。分块开发得到 C 语言程 序加工过程的支持,因为 C 语言允许加工对象不是完整的程序,而是一个个的源程序文件。 分块开发出的各个源文件可以分别进行预处理和编译,得到一组程序目标文件;最后可以用 连接程序把这些目标文件和系统库函数程序开发、程序基本运行系统等连接起来,形成最后的可执行 文件。第五章的图 5.5 描述了这种开发过程的基本情况。
预处理的对象通常是一组源程序文件,得到的是一组新的源文件,其中不再包含任何预 处理命令(所有文件包含命令都用相应文件的内容取代,所有的宏都已替换掉,所有条件编 译的效果都已体现在作为预处理结果的源文件中,应该清除的代码段均已除去)。编译程序 处理的就是一组这样的源程序(人们通常将称它们为编译单位,translation units),将它们分 别编译为一组目标代码模块。只有到了连接时才需要一个程序的全部信息(程序的所有目标 代码模块)。连接系统将所有有关的目标代码模块装配到一起,解决这些模块里所有的定义 和使用之间的关联问题,并将必要的运行支持模块和系统库函数代码也连接到程序里,最终
一个可能的方法是把不关心的部分“注释”起来。但这一方法很难系统化地采用,因为 新的临时性注释可能与程序中原有的注释冲突,改起来常常需要做许多变动。大型源文件的 另一个缺点是,哪怕你只改动了其中的一个字符,为了后面的程序调试,也需要把整个文件 重新加工一次,这又会浪费许多时间。此外,这种做法也相当危险。由于许多东西都放在一 个大文件里,如果开发或调试新加入部分时无意改动了已经做好的部分,那就又会带来无穷 无尽的烦恼。另一方面,一个大的软件系统通常是几个、几十个甚至更多人共同工作的结果。 许多人怎样用一个源文件工作?我们根本无法想象许多人一起改动一个大地程序文件时会 发生什么事情。
这里用一个 StuRec 类型的全局数组存储程序里使用的公共数据。 下面给出程序里的一些主要部分,有些部分则给只出梗概。程序启动后进入交互状态,
本章是这本书实质性内容的最后一章,这里要通过一些程序实例,综合性地总结本书中 所讨论的各方面内容,包括 C 语言里的一些主要机制以及写程序的各种基本技术,讨论一 些在编写较大程序时需要考虑的问题,同时介绍一些有用的编程技术。
除成绩统计和直方图外,这里还增加了一个成绩排序输出的函数 sortoutput。 上面两个函数都用到前面背单词程序定义的函数 next。此外这里还需定义一个取得用
户命令的函数 getcmd,它显示一个信息串,要求读入一定范围里的一个数。该函数的实现 应该参考 getnstr 和前面几次定义的 getnumber,读入一个数之后应该丢掉整个行中其 余的东西。下面是几个函数的原型:
这里还用读者已熟悉的例子:学生成绩文件的处理。这个例子也作为本章后面许多讨论 的公用实例。我们对这个实例做一些扩充,假定成绩文件给出了每个学生一门课程的期中考 试成绩,平时成绩和期末考试成绩。程序需要按照一定比例计算出课程的最终成绩,并能在 此基础上做统计,画学生成绩分布直方图,做排序输出等。
在考虑分块开发问题之前,我们先给出一个在当前情况下的合理实现。首先为该工作起 一个名字,称之为 stu,这个名字也将作为程序主文件的名字。我们假定文件中的成绩数据 具有如下形式:
数据在文件里分行排列,每行给出一个学生的成绩数据。 为完成这一程序,我们先定义表示学生记录的结构类型作为程序里的基本数据表示。程
这里的 getnstr 是第 8 章单词练习程序里开发的读取一个字符串的函数,这里将读入的字 符串用作文件名,设法打开该文件。commander 是程序里的一个主要函数。对一个打开的 文件,commander 首先将文件里的学生成绩记录读入,而后转入交互命令的处理:
这几个简单函数的代码就不列在这里了。 完成统计和生成直方图的函数需要做少许修改,以处理目前所采用的结构数组:
得到一个可执行程序。 分块开发中最重要工作就是程序结构的“物理”组织。在 C 语言里做分块开发,需要
借助于 C 系统的预处理功能,以达到对源程序的适当物理划分,并设法保证组成同一个程 序的不同部分之间的一致性,以便使编译之后的目标代码模块能组合成一个具有内在一致性 的完整的可执行程序。
随着学习的不断深入,我们在编程序时要处理的问题变得越来越复杂,写出的程序也越 来越长了。应该看到,教科书里的问题都做了许多简化,任何实际问题通常都比书里的例子 和习题中提出的问题更复杂得多。随着程序变得越来越大,许多新问题也随之出现了。
最明显情况的是源程序文件越来越大。大文件处理起来很麻烦,屏幕只能显示其中很小 一部分,翻阅查找信息都更费精力,更费时间。大的源文件总是慢慢建立起来的,建立过程 中经常需要编译调试其中的某个或者某些小部分,做起来就非常麻烦。
其中调用了标准库函数 qsort,用到前一章定义的学生记录成绩比较函数:
*请认真填写需求信息,我们会在24小时内与您取得联系。