logo资料库

从问题到程序——程序设计与C语言引论_裘宗燕 PDF清晰版.pdf

第1页 / 共312页
第2页 / 共312页
第3页 / 共312页
第4页 / 共312页
第5页 / 共312页
第6页 / 共312页
第7页 / 共312页
第8页 / 共312页
资料共312页,剩余部分请下载后查看
ch00[1].pdf
ch01[2].pdf
ch02[1].pdf
ch03[2].pdf
ch04[1].pdf
第四章 基本程序设计技术
4.1 循环程序设计
4.1.1 基本循环方式
4.1.2 求出一系列完全平方数
第一种方法
第二种方法
4.1.3 判断素数(谓词函数)
4.1.4 艰难旅程(浮点误差)
求立方根(迭代和逼进)
4.1.6 求sin函数值(通项计算)
4.2 循环程序的问题
4.2.1 从循环中退出
break语句
4.2.2 循环中的几种变量
4.3 循环与递归
4.3.1 阶乘和乘幂(循环,递归)
递归和循环
4.3.2 斐波那契序列(计算与时间)
问题分析
4.3.3 为计算过程计时
4.3.4 Fibonacci序列的迭代计算(程序正确性与循环不变式)
4.3.4 最大公约数
解法1
解法2
4.3.5 河内塔(梵塔)问题
4.4 基本输入输出
4.4.1 字符输入输出函数
4.4.2 字符输入中的问题
输入一系列字符
缓冲式输入
处理所有可输入字符
4.4.3 格式输入函数scanf
4.4.4 输入函数的返回值及其作用
标准输入与文件
4.4.5 输入循环
通过计数器控制循环
用结束标志控制的循环
输入流和输入操作
4.5 控制结构和控制语句
4.5.1 do-while循环结构
4.5.2 流程控制语句
continue语句
goto语句
4.5.3 开关语句
4.6 程序设计实例
4.6.2 一个简单计算器
4.6.3 定义枚举常量
4.6.4 单词计数问题
4.7 程序测试和排错
4.7.1 测试
4.7.2 白箱测试
4.7.3 黑箱测试
4.7.4 排除程序里的错误
文中问题的解释
本章讨论的重要概念
练习
ch05[1].pdf
第五章 C程序结构
5.1 数值类型
实数类型和整数类型
字符类型
整数类型
基本数据类型的选择
5.2 函数和标准库函数
5.2.1 C语言的库函数
5.2.2 字符分类函数
5.2.3 随机数生成函数
5.3 函数定义和程序的函数分解
5.3.1 主函数
5.3.2 程序的函数分解
5.3.4 对函数的两种观点
一个实例:字符图形
函数封装和两种观点
函数定义
函数调用
5.3.5 函数原型
函数原型
过时的函数定义形式与原型形式
不写函数原型
5.4 C程序结构与变量
5.4.1 外部定义的变量
5.4.2 作用域与生存期
5.4.3 外部变量和自动变量
5.4.4 变量定义的嵌套
5.4.5 静态局部变量
5.4.6 变量的几个问题
寄存器变量
外部静态变量
变量的初始化
默认初始化
常变量
5.4.7 一个实例
5.5 预处理
5.5.1 文件包含命令
5.5.2 宏定义与宏替换
简单宏定义
带参宏定义
5.5.3 条件编译命令
5.6 定义常量
5.7 字位运算符*
5.8 编程实例
5.8.1 一个简单猜数游戏
5.8.2 加密与解密
本章讨论的重要概念
练习
ch06[1].pdf
第六章 数据对象的顺序组合:数组
6.1 数组的概念、定义和使用
6.1.1 数组变量定义
6.1.2 数组的使用
6.1.3 数组的初始化
6.1.4 数组的存储实现
6.2 数组程序实例
6.2.1 从字符到下标
6.2.2 筛法求素数
6.2.3 成绩分类
6.2.5 多项式求值
6.2.6 定义数组的问题
6.3 数组作为函数参数
6.3.1 一个例子
6.3.2 修改实参数组的元素
6.4 字符数组与字符串
6.4.1 字符数组
6.4.2 字符串
6.4.3 程序实例
6.4.4 标准库字符串处理函数
6.4.5 输出文本里的最长行
6.5 两维和多维数组
6.5.1 多维数组的初始化
6.5.2 多维数组的表示和使用
程序示例
6.5.3 多维数组作为函数的参数
编程实例
6.6.1 成绩直方图
问题分解
实现
分析和改进
6.6.2 一个通用带检查的整数输入函数
6.2.4 计算数组变量的大小
6.6.3 统计C程序里的关键字
6.6.4 数组划分*
问题解释
本章讨论的重要概念
练习
ch07[1].pdf
ch08[1].pdf
第八章 文件和输入输出
8.1 文件的概念
8.1.1 流和文件指针
8.1.2 缓冲式输入输出
8.2 文件的使用
8.2.1 文件的打开和关闭
8.2.2 输入输出函数
字符输入和输出函数
格式化输入输出函数
行式输入和输出函数
8.2.3 程序实例
8.2.4 直接输入输出函数
8.3 标准流输入输出与格式控制
8.3.1 行式输入和输出
8.3.2 输入格式控制
8.3.3 输出格式控制
8.3.4 以字符串作为格式化输入输出对象
8.3.5 标准错误流
8.4 程序实例
8.4.1 求文件数据的平均值
8.4.2 一个背单词程序
8.4.3 资金账目系统
练习
ch09[1].pdf
ch10[1].pdf
第十章程序开发技术
10.1 分别编译和C程序的分块开发
10.1.1 分块开发的问题和方法
10.1.2 程序实例:学生成绩处理
10.1.3 分块重整
10.1.4 其他安排和考虑
10.1.5 一般性原则
物理组织的合理原则
程序物理组织的具体考虑
集成开发环境中的程序组织和开发
10.1.6 单一头文件结构和多个头文件结构
10.1.7 功能模块和程序库
复数模块
目标文件和库
10.1.7 防止重复包含
10.2 错误报告和处理
10.2.1 建立统一的错误报告机制
10.2.2 定义变参数的错误报告函数
10.2.3 运行中错误的检查和处理
两种有问题的处理方法
两种常见处理方案
条件检查、断言和防御式程序设计
10.3 程序的初始化
10.3.1 程序行为和启动时初始化
10.3.2 交互式初始化
10.3.3 通过命令行参数
10.3.4 采用初始化文件
10.4 程序开发过程
10.4.1自上而下的开发
10.4.2 自下而上的开发
10.4.3 实际开发过程
10.5 进一步学习的建议
算法和数据结构:
C++语言及面向对象的程序设计
程序设计的实践性问题:
程序设计的理论和严格方法
练习
ch11[1].pdf
第十一章 标准库
11.1 标准库结构
11.1.1 标准定义(
11.1.2 错误信息(
11.2 几个已经介绍过的头文件
11.2.2 数学函数(
11.2.2 字符处理函数(
11.3 字符串函数(
11.3.1 一些字符串函数
字符串长度
字符和子串查找
特定的最长前缀
单词分解
11.3.2 存储区操作
11.4 功能函数(
11.4.1 几个整数函数
11.4.2 数值转换
11.4.3 执行控制
11.4.4 与执行环境交互
11.4.5 常用函数bsearch和qsort
11.5 日期和时间(
11.6 实现特征(
11.6.1 整数类型特征
11.6.2 浮点数类型特征
11.7 定义变长度参数表(
11.8 其他与输入输出有关的函数(
11.8.1 符号常量和类型
11.8.2 文件操作函数
11.8.3 流缓冲区操作函数
11.8.4 文件定位及定位函数
11.8.5 其他有关函数
11.8.6 采用va_list参数的输出函数
程序实例
11.9 非局部控制转移(
11.10 调试断言和异常处理(
11.11 标准库的其他功能
11.11.1 本地化
11.11.2多字节字符
本章讨论的重要概念
练习
append[1].pdf
附录A C语言运算符表
附录B C语言速查
1,关键字
2,基本类型(2.3,5.1,7)
3,字面量的书写形式(2.3,5.1)
4,运算符与表达式
5,基本控制结构
6,变量的定义与说明
7,数组、结构、联合、枚举的描述和类型说明
8,函数定义、调用和原型说明
9,预处理命令
10,标准函数库
前言 程序设计课程在计算机科学教育中的重要性是无庸置疑的。人们一直在思考第一门程序 设计课应该教授什么,其教材应该是怎样的?在用 C 作为第一门程序设计课教学语言的过 程中,我编写了这个教材,是对于自己教学经验的总结。 教学过程中学生们提出的问题使我看到,教材(或适合自学者的书籍)中需要对可能的 问题做出合理而充分的解释,无论是关于 C 语言本身,还是关于程序设计过程,使读者在 阅读时能了解问题实质,而不是在模糊中去设法感悟。这对于帮助初学者尽快进入程序领域 非常重要,也使教师有更大自由度,灵活选择实例和教学方式。由于程序设计的性质,这里 的实例不应采用“提出问题,给出解答,再加点解释”的简单三步形式,而应着重帮助读者 认识程序设计活动的实质,理解从问题到程序的思考过程。本书在这些方面做了些努力。 本书的一个基本想法是希望反映程序设计的两个重要特征,科学性和工程性。科学性指 程序构造过程应有充分科学依据:分解弄清问题各部分的意义和互相联系,需要人对程序实 现过程有科学认识。有关研究的发展形成了程序的理论。入门书不可能去讨论这些理论成果, 但也必须反映其精神实质,使初学者从开始就接触程序的一些本质性问题。这无论对于提高 读者对计算机科学技术认识水平,还是对他们的进一步深入学习,都是非常重要的。 随着计算机的日益普及,不少人在进大学前就有了计算机经验,有的已将计算机玩得很 熟,甚至写过许多程序。但也应看到另一面:在学习大学课程前,学生中对程序及程序设计 已建立起正确认识的人很少。即使那些很熟悉计算机的学生,也有许多观点需要建立,或有 一些错误观点需要纠正。这也是本课程中应该特别强调科学性的原因。 我们常发现学生有些对计算机实质的不正确认识。例如有些学生在头脑深处把计算机看 成很不驯服的东西,觉得程序设计就是设计一些计谋,“骗”计算机干活。有些学生把程序 设计看成玩计算机游戏,到处是陷阱和妖魔,需要在试探和失败中找一条绕过障碍的路。 日益完善的程序开发环境也可能成为学习的障碍。很好的环境造就出一类学生:遇到编 程工作时不细致分析和设计,粗一想就动手,很快写出一堆代码,随后进入运行、追踪、打 补丁改错的三步循环。简单程序可能这样做出来了,但质量很差,很简单问题常常写出一大 篇,自己也说不清解决问题的过程。即使很熟悉程序的人,不花些工夫也难判断这类程序的 对错,错误在哪里。当问题更复杂时,这些同学就遇到了困难:程序难以通过测试,弄不清 错误出在那儿,该怎样修改。这种程序像建在沙滩上的大楼,无论如何修补都不行,只能推 倒重来。这些情况的提示是:从简单程序开始就应该注意程序设计的正确途径。 这些都说明了强调程序设计过程中科学性的必要。本书从开始就强调问题的分析和分 解,反复讨论函数抽象方法。后面不断有进一步论述,实例中也特别注意这方面的问题。一 些地方还通过实例介绍了一些更深入的理论问题,如通过对程序运行时间的测试介绍计算过 程的基本性质(复杂性);通过分析循环过程是否完成了所需工作,介绍“循环不变关系” 的概念和意义等。当然,这些只是希望读者了解有关情况,作为思考程序问题的线索。 这里说程序设计的工程性,并不是指规模大,参加人员多等,而是从另一个角度看问题。 工程设计中需要分析和理解问题,寻找可能解决方案,对各种方案做出评价和选择。对所做 选择应有清醒认识(优点和缺点,是否对问题的某些方面有所偏向或不足等),进而确定具 体实施方案。这些问题在程序设计中都有直接反映。如果学习程序设计的目的是希望提高能 力、真正理解程序设计过程的话,这些问题都需要特别强调。 本书始终强调一种观点:程序问题并没有需要记住的标准答案。由于分析问题时的不同 考虑,设计过程中的不同决定或选择,人们对同一问题常会得到许多合理而正确的不同程序。
这些程序常各有长短,可能各有侧重点,也可能反映了对问题的不同认识。应该特别注意思 考和解决问题的方法,包括如何分析问题,逐步把问题弄得更清楚明确;如何寻找可能求解 途径,把复杂问题分解为相对简单的步骤;如何在可用的语言结构中做出选择等。这里的每 一步都可能产生分支,应该认清各种选择的后果,无论是收获还是损失。 工程中通常没有完美的选择,更多的是权衡和折衷,这些对程序设计也是本质性的。本 书对许多实例给出了较详细的分析过程,常常对一个问题给出多个解答,有时还指出了其他 可能性:还可能如何看问题,还可能如何做等等。这里还常常给读者提出一些问题,希望读 者发挥自己的思维能力和主观能动性。各章节后面的练习也试图反映这些看法。 我们希望读者能建立一种认识:程序设计问题并没有什么“标准答案”,要追求的是比 较好的“正确”答案,各种书籍中给出的答案(包括本书)不过是作者对问题理解和分析的 反映,还有很多可能选择。进一步说,我们还希望读者养成这样的习惯:在看别人的程序时, 应分析其中隐含着作者的哪些考虑和选择,哪些是合理的有价值的(或不合理没价值的)? 还可能有什么选择?沿其他选择走下去可以得到什么(或失去什么)等等。这种思考习惯必 将使人受益无穷。当然,这并不是说书中的示例不重要。恰恰相反,因为程序设计中有许多 选择可能,书中更应当给出合理的好的选择供读者参考。入门书籍还应当说明理由,如果可 能,还应当指出采取这些选择带来的问题(缺点,限制等等)。 正如本书的书名所言,程序设计是“从问题到程序”的思考和工作过程,这里既要求掌 握严格的科学方法,又要求谨慎灵活的工程能力。要很好地完成程序设计工作,编程者需要 充分发挥聪明才智,还要有细致认真、一丝不苟的工作态度。即使将来不从事程序工作,这 一课程中的锻炼也可能很重要,尤其对于理科学生,可能弥补其工程方面训练的不足。 前些年的程序设计课常用 PASCAL、FORTRAN 或 BASIC 等语言,目前已转向 C 或其 他类 C 语言(如 C++)。从作为入门课教学语言的角度看,没有一种语言具有无可比拟的天 然优势,选择时都应考虑其有利方面,也需要克服这种选择带来的不利因素。 选择 C 作为教学语言的主要理由有:C 是目前实际使用最广的语言之一,它包含了需要 理解的基本机理和主要机制,能满足讨论程序与程序设计问题的需要。学生可以用它完成程 序练习,得到有关知识积累和能力锻炼,还能掌握一种实用的工具。另一方面,程序设计是 计算机领域的基础课,学了 C 语言后,后续课程比较容易安排。C 语言适合(也正被)作为 计算机领域许多课程的教学语言。第三,C 是一种很灵活的语言,用它写程序常需要了解一 些细节,这是人们对用 C 作为基础课语言的主要疑虑。问题也有另一面,通过对 C 语言程 序设计的较好理解,读者也可能得到更深入的认识。这个问题实际上对课程组织,教材和教 师提出了较高要求。C 程序可以在较低层次上做,也可以在较高层次上做,学生可能从中更 多了解程序设计过程中的各种问题。此外,许多语言从 C 借鉴了想法和形式,有些是 C 的 扩充和发展,C 语言知识对于进一步了解其他语言,包括未来的新语言都有价值。 在撰写本书时我心中有几个努力追求的目标,列在这里供读者和同行参考: 1. 假定读者(基本上)没有程序设计经验,希望本书适合作为入门课教材。 2. 以程序设计为基本线索,同时对 C 语言做深入介绍,强调如何认识程序、写程序和用 C 写程序。通过实例讨论问题分析和分解,设计求解过程,找出主要步骤,确定函数抽象, 找出循环,选择语言结构,最后写出程序的过程。不少实例给出了在不同考虑下可能形 成的多种解法,以帮助读者理解程序设计的真谛。 3. 强调好的程序设计风格,通过函数抽象建立起清晰结构的重要性。尽可能早地引进函数 概念,从库函数、简单函数定义等等。强调程序的结构性、可读性、易修改性。书中还 根据进展和遇到的问题分析了一些不良程序设计习惯及其危害。
4. 注意强调“好的”C 程序设计。历史使 C 成为一个不太严格的语言,如不注意,用 C 写的程序常会隐含不易发现的错误*。ANSI C 标准倡导了一套写“好的”C 程序写法。 本书力图坚持这种正确途径,讨论了如何写出更可靠、不易包藏隐含错误的 C 程序的 各方面问题,通过实例说明了应该如何写和不应该如何写。在此基础上也介绍了一些实 用的 C 程序设计技术。本书希望强调的是如何写正确、清晰、简洁、高效的 C 程序。 5. 详细介绍和解释了 C 的各种结构和机制,因为其中不少问题反应了相关领域的普遍性 知识和情况。这里还尽可能提供一些背景理由,以帮助读者理解问题实质。对语言和程 序设计的一般性问题及计算机科学中的一般问题也有适度介绍。 本书包括如下各章和若干附录: 第一章,程序设计与 C 语言。介绍程序与程序语言的概念,C 语言的发展及其特点。用 一个小例子介绍 C 程序形式,其加工和执行。最后介绍程序设计与开发过程。 第二章,数据对象与计算。讨论程序语言的许多最基本概念,包括:字符集、标识符和 关键字,数据与类型,数据表示,运算符、表达式与计算过程,数学函数库的使用等。 第三章,变量、函数和控制结构。讨论程序设计的一些基本问题,包括语句与复合结构, 变量及其使用,简单函数定义,逻辑条件的描述与使用等。最后介绍了几种基本控制结构。 第四章,基本程序设计技术。首先分析循环程序设计的基本问题,通过一系列程序实例 分析了循环的构造过程。此后介绍了 C 语言其他控制结构及其使用。 第五章,C 语言程序结构。讨论 C 语言许多具有一般性的重要问题,主要是 C 程序结 构,函数概念及有关的问题,预处理命令和预处理过程,递归的概念等。 第六章,数据对象的顺序组合:数组。介绍数组概念、定义和使用,数组与函数的关系, 两维和多维数组等。 第七章,指针。指针概念和指针变量的使用,C 语言中指针与数组的关系,多维数组作 为参数的通用函数。而后讨论了动态存储管理,类型定义,指向函数的指针等一系列问题。 第八章,输入输出与文件。讨论了文件概念,与输入输出有关的各种问题,标准库的输 入输出功能,以及输入输出的程序设计问题。 第九章,结构及其他数据机制。介绍结构(struct)、联合(union)、枚举(enum)等数 据定义机制的意义及在程序中的使用。随后简单介绍了链接结构的概念。 第十章,程序开发。讨论程序设计和开发中的许多一般性问题和技术。包括 C 程序的 分块开发问题等。 第十一章,标准库函数。介绍标准库提供的各方面功能及其相关知识。 最后有几个附录和一个比较详细的索引。 本书以标准 C 为背景,有关内容不依赖于具体 C 系统。读者可用任何符合 ANSI C 标准 的 C 系统作为编程环境,如国内常见的微机上的各种 C 系统,工作站或其他计算机上的 C 系统。虽然软件厂商不断推出新版本的程序开发环境,但从学习基本程序设计的角度看,新 开发环境比早先版本并没有实质性改善,通常是更复杂、占用更多计算机资源,初学者入门 更困难。本书的实例程序按 ANSI C 标准书写,习题也不涉及任何具体系统环境,因此建议 读者采用比较简单基本的系统作为学习工具,例如国内使用较多的 TURBO 系列 C 系统,一 些公开的免费 C 语言系统等。本书最后附了对 TURBO C 系统的简单使用说明。 我特别感谢北京大学数学学院和北京大学理科试验班参加课程的同学们和参加课程辅 * 任何语言都有弱点。有句名言说:“再好的语言也不能阻止人写出坏程序”。这不是说语言不重要,而 是说任何语言都有合理使用,写好程序的问题。C 在这方面的问题突出一点,读者应特别注意。
导的研究生们,是他们的思考和问题给了我许多启示,使我更深入地理解了许多问题。我也 要感谢我的家人与同事在这些年工作中给我的支持。 虽然本书包含了我几年的工作和思考,但书中难免有大的或小的错误,这些都由我个人 负责。希望读者能把发现的问题告诉我,也希望同行们对本书提出宝贵意见。 裘宗燕 北京大学数学学院信息科学系,1999 年 1 月 2003 年修订
裘宗燕 从问题到程序(2003 年修订),第一章 第一章 程序设计和 C 语言 在开始学习程序设计时,初学者首先遇到的问题可能是:“什么是程序”?“什么是程 序设计语言”?本章首先讨论这方面的问题,以期帮助读者在比较直观的基础上建立起对程 序、程序设计、程序设计语言的基本认识。而后将简单介绍本书中讨论程序设计问题时所用 的一种程序设计语言——C 语言,并通过一个简单实例介绍 C 语言程序的一些基本情况和 有关概念。最后介绍了程序设计中必然要遇到的一些问题。 1.1 程序和程序语言 程序一词也来自生活,通常指完成某些事务的一种既定方式和过程。从表述方面看,可 以将程序看着对一系列动作的执行过程的描述。日常生活中也可以找到许多“程序”实例。 例如,一个学生早上起床后的行为可以描述为: 1,起床; 2,刷牙; 3,洗脸; 4,吃饭; 5,早自习; 这是一个直线形程序,是最简单形式的程序。描述这种程序的就是给出一个包含其中各个基 本步骤的序列。如果按顺序实施这些步骤,其整体效果就完成了该项事务。 现在考虑另一个复杂些的过程:到图书馆借教学参考书。这一常见过程可以描述为: 1,进入图书馆; 2,查书目; 3,填写索书单; 4,交图书馆工作人员取书; 5,如果该书已经借出,读者可以有两种选择: 6,(工作人员找到了要借的书)办理借书手续; 7,离开图书馆。 5.1,回到第2步(进一步查找其他参考书的书目); 5.2,放弃借书,离开图书馆; 这个程序比前一个复杂得多。可以看到,这一程序不是一个平铺直叙的动作序列,其中步骤 更多,还出现了分情况处理和可能出现的重复性动作。 如果仔细探究这个实例,我们还可以可以看到,这一程序还可以进一步细化。例如可以 找出许多上面描述中未处理的情况,例如:若查找图书目录时没有找到所需书目;填写好索 书单后已经到了下班时间;借书时发现自己没有带借书证;工作人员查到该读者的借书册数 已经达到限额,或发现该读者有逾期未还的图书,因此拒绝借出等等。 由这些现实生活中的例子,可以初步看到程序的一些直观特征。现实生活中有许多程序 性活动,当我们身处其中时,通常需要按部就班地一步步完成一系列动作。对这种工作(事 物、活动)过程的细节动作描述就是一个“程序”。 在一个程序描述中,总有一批预先假定的“基本动作”,这些基本动作是执行程序者能 够理解和直接完成的。例如,在有关借书的程序描述中将“查图目”作为一个基本动作。如 果执行者不知道如何查书目,那么,在给这种读者的程序描述中,就需要将“查书目”的动 作进一步细分,描述查书目的细节过程。 一个程序总有开始与结束。在执行此程序的过程中,动作者(无论是不是人)需要按照 程序的描述执行一系列的动作。在达到结束位置时工作就完成了。 1
裘宗燕 从问题到程序(2003 年修订),第一章 本书中将要深入讨论的计算机程序同样具有这些特征。 程序与程序设计 日常生活中程序性活动的情况与计算机里的程序执行很相似。这一情况可以帮助我们理 解计算机的活动方式。当然,人们日常生活中的程序性工作中有更多变数,许多事情并不要 求完全按程序做,可以有许多“灵活性”。而计算机对程序的执行则完全是严格而一丝不苟 的,一步步按程序中的指令办事,一点“商量”的余地也没有。 计算机是人类发明的一种自动机器,它能完成的工作就是计算。计算机的最基本功能是 可以执行一组基本操作,每个操作完成一件很简单的计算工作,例如整数的加减乘除运算等 等。为使计算机能按人的指挥工作,每种计算机都提供了一套指令,其中的每一种指令对应 着计算机能执行的一个基本动作。 作为一种看得见、摸得着的物理实体,计算机的基本原理很简单,其最本质特征是它们 不仅能按指令工作,而且能自动地按程序(作为计算机能执行的基本动作序列)工作。因此, 人与计算机交流的基本方式就是提供要求它执行的程序。在命令计算机去执行某个程序之 后,计算机就会按照程序的规定,一丝不苟地执行其中的指令,直至程序结束。 计算机是一种通用的计算机器,加上一个或一组程序后,它就会变为处理某个专门问题、 完成某种特殊工作的专用机器。这种通用性与专用性的统一非常重要。这样,一方面,计算 机可以在大工厂里采用现代化生产方式大量制造;另一方面,通过运行不同程序,一台计算 机可以在不同时候处理不同问题,甚至同时处理许多不同的问题。这就是计算机威力的真谛。 人们描述(编制)计算机程序的工作被称为程序设计或者编程,这种工作的产品就是程序。 由于计算机的本质特征,从计算机诞生之初就有了程序设计工作。 今天,计算机的发展及其在各领域的广泛应用,它对人类社会生活各方面的深刻影响已 经是人所共知的事实了。计算机之所以能产生这样大的影响,其原因不仅在于人发明并大量 制造了这样一种令人敬畏的奇妙机器,更重要的是人们为计算机开发出了数量宏大、五彩缤 纷、能指挥计算机完成各种简单或复杂工作的程序。目前正在使用的计算机没有多少种,而 正是数量繁多、功能丰富多彩的程序给了计算机无穷无尽的“生命力”。 由上面介绍还可以看到程序和程序描述的另外一些问题。例如,对于上面学生借书的例 子,我们提出了许多需要考虑的细节。如果需要用计算机去处理问题,写程序时就必须精确 描述所有动作的细节过程,不能有一点含糊其词的地方。 程序设计语言及其发展 要说明在一个程序的进行中需要做些什么,就需要仔细给出这一程序性活动的一步步的 细节过程,需要描述程序运行中的各种动作及其执行的顺序。为做到这些,就需要有某种适 当的描述方式。一套描述方式就形成了一个语言。 语言一词通常指人生活工作中使用的自然语言,如汉语、英语等。这些语言随着人类发 展进步而自然形成,是人互相间交流信息的工具和媒介。人们用口头语言向别人传播见闻、 表达看法和想法。用书面语言写文章、书籍,以实现更大范围中的信息交流。在前面所描述 的现实生活中的程序实例中,我们就是用汉语作为描述程序的语言,所描述的程序是为了给 人看,要人去做的。 为了与计算机交流,指挥它工作,同样需要有与之交流的方式,需要一种意义清晰、人 用起来比较方便、计算机也能处理的描述方式。也就是说,需要有描述程序的合适语言。可 供人编程序用的语言就是程序设计语言,这是一类人造语言。程序设计语言也常被称为编程 语言,本书中常常简称为程序语言,在上下文清楚之处简称为语言。 有人可能说:小学生就学数学,数学的一个基本部分是计算,小学生已经会用数学方式 (或说,用数学语言)描述计算过程,程序设计语言有什么特殊之处吗?确实有!程序语言 2
裘宗燕 从问题到程序(2003 年修订),第一章 的一个突出特点就在于不仅人能懂得和掌握它,能用它描述所需的计算过程,而且计算机也 可以“懂得”它,可以按程序语言给出的关于计算过程的描述去行动,完成人所需要的计算 工作。程序设计语言是人描述计算的工具,也是人与计算机交流信息的媒介:通过用程序语 言写程序,人能指挥计算机完成各种特定工作,完成各种计算。 计算机诞生之初,人们只能直接用二进制形式的机器语言写程序。对于人的使用而言, 二进制的机器语言很不方便,用它书写程序非常困难,不但工作效率极低,程序的正确性也 难以保证,发现有错误也很难辨认和改正。下面是一台假设计算机上的指令系列: 00000001000000001000 -- 将单元1000的数据装入寄存器0 00000001000100001010 -- 将单元1010的数据装入寄存器1 00000101000000000001 -- 将寄存器1的数据乘到寄存器0原有数据上 00000001000100001100 -- 将单元1100的数据装入寄存器1 00000100000000000001 -- 将寄存器1的数据加到寄存器0原有数据上 00000010000000001110 -- 将寄存器0里的数据存入单元1110 这里想描述的是计算算术表达式 a × b + c(这里的符号 a、b、c 分别代表地址为 1000、 1010 和 1100 的存储单元),而后将结果保存到单元 1110 的计算过程(程序)。 一个复杂程序里的指令可能有成百万、成千万条或者更多,程序中的执行流程错综复杂, 在二进制机器指令的层面上理解复杂程序到底做了什么,很容易变成人力所根本不能及的事 情。为缓解这一问题,人们发展了符号形式的,使用相对容易些的汇编语言。用汇编语言写 的程序需要用专门软件(汇编系统)加工,翻译成二进制机器指令后才能在计算机上使用。 下面是用某种假想的汇编语言写出的程序,它完成与上面程序同样的工作: load 0 a -- 将单元a的数据装入寄存器0 load 1 b -- 将单元b的数据装入寄存器1 mult 0 1 -- 将寄存器1的数据乘到寄存器0原有数据上 load 1 c -- 将单元c的数据装入寄存器1 add 0 1 -- 将寄存器1的数据加到寄存器0原有数据上 save 0 d -- 将寄存器0里的数据存入单元d 汇编语言的每条指令对应于一条机器语言指令,但采用了助记的符号名,存储单元也用用符 号形式的名字表示。这样,每条指令的意义都更容易理解和把握了。但是,汇编语言的程序 仍然完全没有结构,仅仅是许多这样的指令堆积形成的长长序列,是一团散沙。因此,复杂 程序作为整体仍然难以理解。 1954 年诞生了第一个高级程序语言 FORTRAN,宣告程序设计新时代的开始。FORTRAN 采用完全符号化的描述形式,用类似数学表达式的形式描述数据计算。语言中提供了有类型 的变量,作为存储的抽象模型。此外它还提供了一些流程控制机制,如循环和子程序等。这 些高级机制使编程者可以摆脱许多具体细节,方便了复杂程序的书写,写出的程序也更容易 阅读,有错误也更容易辨认和改正。FORTRAN 语言诞生后受到广泛欢迎。 高级语言及其实现 高级程序语言更接近人所习惯的描述形式,更容易被接受,也使更多的人能(并乐于) 加入程序设计活动中。用高级语言书写程序的效率更高,这使人们开发出更多应用系统,反 过来又大大推动了计算机应用的发展。应用的发展又推动了计算机工业的大发展。可以说, 高级程序设计语言的诞生和发展,对于计算机发展到今天起了极其重要的作用。 从 FORTRAN 语言诞生至今,人们已提出的语言超过千种,其中大部分只是试验性的, 只有少数语言得到了广泛使用。随着时代发展,今天绝大部分程序都是用高级语言写的。人 们也已习惯于用程序设计语言特指各种高级程序语言了。 在高级语言(例如 C 语言)的层面上,描述前面同样的程序片断只需一行代码: d = a * b + c; 这表示要求计算机求出等于符号右边的表达式,而后将计算结果存入由 d 代表的存储单元 中。这种表示方式与人们所熟悉的数学形式直接对应,因此更容易阅读和理解。高级语言程 3
裘宗燕 从问题到程序(2003 年修订),第一章 序中完全采用符号形式,使人可以摆脱难用的二进制形式和具体计算机的细节。此外,高级 语言中还提供了许多高级的程序结构,供编写程序用于去组织复杂的程序。与机器语言和汇 编语言的程序相比,情况确实大大改观了。 当然,计算机也不能直接执行高级语言描述的程序。人们在定义好一个语言之后,还需 要开发出一套实现这一语言的软件,这种软件被称作高级语言系统,也常被说成是这一高级 语言的实现。在研究和开发高级语言的工作过程中,人们也研究了各种实现技术。高级语言 的基本实现技术是编译和解释,下面是两种方式的简单介绍: 1. 采用编译方式实现高级语言:人们首先针对具体语言(例如 C 语言)开发出一个翻译 软件,其功能就是将采用该种高级语言书写的程序翻译为所用计算机的机器语言的等价 程序。用这种高级语言写出程序后,只要将它送给翻译程序,就能得到与之对应的机器 语言程序。此后,只要命令计算机执行这个机器语言程序,计算机就能完成我们所需要 的工作了。 2. 采用解释方式实现高级语言:人们首先针对具体高级语言开发一个解释软件,这个软件 的功能就是读入这种高级语言的程序,并能一步步地按照程序要求工作,完成程序所描 述的计算。有了这种解释软件,只要直接将写好的程序送给运行着这个软件的计算机, 就可以完成该程序所描述的工作了。 目前在实际程序设计工作中,最常用的是第一种实现方式,本书后面还会进一步介绍这种实 现方式的一些具体情况。 随着计算机科学技术的发展,人们不断提出新的程序语言,老的语言被逐渐淘汰。仍在 使用的老语言也在急剧变化。以 FORTRAN 语言为例,它在过去 40 多年里经过了四五次大 改版,目前最新版本(FORTRAN 90)与开始的 FORTRAN 相比早已面目全非了。其他历史 较长的语言也都如此。推动语言发展的因素很多,一个重要原因是人们对程序工作的新认识。 随着程序设计实践越来越丰富,人们对程序设计工作应该怎样做,需要什么东西去描述等不 断产生新认识。推动语言发展的另一原因是应用的发展。新应用领域常对描述工具提出新要 求,这些认识和要求促使人们改造已有的语言,或者提出新语言。 世界上目前使用较广的语言有 FORTRAN、C、C++、PASCAL、Ada、Java 等,这些语 言通常被认为是常规语言,因为它们有许多共同性质。还有一些语言比较特殊,在形式、编 程方式等方面与常规语言差别很大,互相间也常常大相径庭。这些非常规语言各有各的特点 或应用领域,甚至有特殊的使用人群。这类语言如 LISP、Smalltalk、PROLOG、ML 等。它 们虽然不如常规语言使用广泛,但也非常重要,都曾在程序语言或计算机的发展历史上起过 (有些仍在起着)极其重要的作用。 程序及其抽象层次 对于程序的描述而言(无论是前面给出的日常生活实例中的非形式的“程序”,还是希 望计算机去执行的程序),还有几个重要的问题值得提出: 可以写在程序里的基本“指令”包括哪些?洗脸、查书目等是前面日常生活中的“程序” 里的基本动作。在编写需要计算机去执行的程序时,其中的基本动作应该是计算机能完成的 事项。例如,要写前面那样的二进制代码形式的程序,就需要按照具体计算机指令系统的规 定写出一条条指令。用一种高级语言写程序时,同样必须基于这种语言所支持的基本功能(基 本命令等等)。学习用高级语言写程序,一个最基本的方面就是了解语言所提供的基本功能, 了解它们的描述形式和所完成的操作效果。 对于描述程序的语言有什么要求?描述前面有关日常生活的“程序”时采用的是汉语, 是我们日常用于人际交流的“自然语言”。自然语言词汇丰富,有极强的表达能力。但在许 多地方要依赖于接受者的知识和常识。如果,要求孔子按照前面给出的程序到图书馆去借书, 4
分享到:
收藏