首页>参考读物>计算机科学与技术>软件与程序设计

C语言的科学和艺术
作者 : (美)Eric S. Roberts 著
译者 : 翁惠玉 张冬茉 杨鑫 蒋文新 译
丛书名 : C语言经典译丛
出版日期 : 2011-06-01
ISBN : 978-7-111-34775-0
定价 : 79.00元
扩展资源下载
扩展信息
语种 : 简体中文
页数 : 558
开本 : 16
原书名 : The Art and Science of C: A Library Based Introduction to Computer Science
原出版社: Pearson Education Asia
属性分类: 店面
包含CD :
绝版 : 未绝版
图书简介

本书是计算机科学的经典教材,介绍了计算机科学的基础知识和程序设计的专门知识。本书以介绍ANSI C为主线,不仅涵盖C语言的基本知识,而且介绍了软件工程技术以及如何应用良好的程序设计风格进行开发等内容。本书采用了库函数的方法,强调抽象的原则,详细阐述了库和模块化开发。此外,本书还利用大量实例讲述解决问题的全过程,对开发过程中常见的错误也给出了解决和避免的方法。本书既可作为高等院校计算机科学入门课程及C语言入门课程的教材,也是C语言开发人员的极佳参考书。

图书特色

本书是一本C语言经典教材,强调软件工程和优秀的程序设计风格。此外,读者还可以从书中学习到ANSI C的基础知识,这些内容已经成为计算机行业的标准。作者的写作风格使得书中深奥的概念变得易于理解和引人入胜。

  本书集中讨论库和抽象的用法,这是当代程序设计技术中最基本的知识。作者使用库来隐藏C语言的复杂性,更加突出主题,使读者可以较好地掌握每一个主题的精髓。然后,进一步给出每个库的底层实现,较好地展示了库自身的抽象威力。

图书前言

作者简介
  Eric S. Roberts第一次教授计算机科学入门课程是在20多年前,当时他还是一名哈佛学子。1980年获得博士学位以来,Roberts先后在哈佛、韦尔斯利、斯坦福大学教授计算机科学课程。在斯坦福大学,Roberts担任计算机科学系副主任,并负责本科生的计算机科学课程。虽然Roberts也教授计算机科学的高级课程并作一些研究工作,但他最大的乐趣还是向初学者展示计算机的强大功能。
  在斯坦福大学任教的同时,Roberts自1990年起还担任计算机专业协会主席。这是一个由计算机专业人士组成的公益团体,在全美有22个分会,2000名会员。计算机在多方面影响着我们的社会。学习有关计算机的技术固然重要,但确保计算机服务于社会也很重要。
  若读者发现本书中有表述不清楚的地方或错误之处,恳请不吝赐教。请通过Roberts的电子邮箱ericr@aw.com与他联系。
致学生
  欢迎你!拿起这本书,你就迈进了计算机科学的世界—这门学科出现在半世纪以前,现在却成为这个时代最具生机和活力的学科之一。
  在几十年的发展过程中,计算机几乎使所有领域中看似不可能的事情成为可能。由于计算机可在瞬间将信息传递到任何地方,所以今天的企业家能以空前的规模经营跨国公司。由于计算机可进行必要的、但人工很难完成的计算,科学家才能解决许多问题。电影人利用计算机制作出更具感染力的视觉效果。由于计算机能处理医学中大量的信息处理,因此医生能对患者的病情做出更精确的诊断。
  计算机技术正在飞速发展。目前我们已经看到的优势与新的世纪将要经历的发展相比肯定将相形见绌。最近50年,计算机已经对世界产生了深远影响,在新的世纪亦将如此。今日的学生将会是执行这项伟大的工程的中流砥柱。要做到这一点,就必须懂得如何使用计算机。
  和其他值得掌握的技能一样,理解计算机的工作原理以及学会怎样控制它们是需要花费时间的。这一切不可能一蹴而就,必须从某个起点开始循序渐进。2500年前,中国的哲学家老子曾说过:“千里之行,始于足下”。本书就是一个很好的起点。
  然而对很多人来说,万事开头难。许多学生在计算机面前束手无策,认为计算机科学超出了他们的理解范围。可是基本的程序设计并不需要具备高等数学和电子学的知识。在程序设计中,最重要的是能否从陈述问题过渡到解决问题。要做到这一点,就必须以逻辑方式考虑问题。训练自己用计算机能够理解的方式表达自己的逻辑。最重要的是,不要被困难和挫折压倒,要坚持到底。若能坚持下来,就会发现解决问题是件多么令人兴奋的事情,它所带来的喜悦足以让你忘却学习过程中遇到的任何挫折。
  本书旨在教授程序设计基础和C语言基础。C语言是当今计算机产业中处于主导地位的程序设计语言。本书不但介绍了程序设计中的“为什么”,还介绍了“如何做”,使读者对程序设计有总体的印象。为使读者避免出现那些阻碍学习的错误,本书在结构上做出了精心安排,可以帮助读者掌握重点。接下来将总结本书在结构上的一些独具匠心之处,并说明如何在学习过程中高效地利用本书。
本书的特色
  为了使本书在学习C语言的过程中发挥最大的作用,首先要充分了解本书的一些特色。
  1) 本书的每一章都包含一些指导读者学习以及掌握主题的材料。
   学习目标中列出了该章包含的关键内容。因为每个目标都与一个具体的技能相关,所以该章的学习目标有助于你评估自己对基本知识的掌握程度。
第1章  概   述
学习目标
   理解硬件和软件的区别。
   认识问题求解是计算机科学的一个重要组成部分。
   理解术语算法的含义。
   理解编译器在高级程序设计语言和低级机器语言之间所起的翻译器的作用。
   认识程序设计错误的主要类型。
   认识软件维护的重要性和使用良好的软件工程实践方法的重要性。
  在计算机技术高速发展的今天,很难想像在1940年计算机还不存在。如今,计算机随处可见,大家都会说,我们生活在计算机时代。
1.1  计算简史
  从某种意义上说,计算的使用古已有之。许多早期数学家致力于解决重要的实际问题的计算,如观察兽群中动物的数量,计算小块土地的面积或记录商业交易等。这些活动要求人们开发新的计算技术,有时甚至要求人们发明新机器来帮助完成计算过程。例如,在亚洲使用了几千年的算盘,它是由在杆上滑动的小珠组成,这种计数装置大约在公元前2000年就出现了。
   小结部分详细地描述了你应该学到的与学习目标部分相关的知识。
小结
  第3章从宏观角度展示了程序设计的过程,强调了问题的求解。在此过程中,以非正式的方法介绍了一些控制语句。本章详细地研究了这些控制语句的工作细节。此外,还介绍了一个新的数据类型—布尔型数据。尽管这种数据类型只有TRUE和FALSE两个值,但是能高效地使用它对成功的程序设计十分重要,因此应该多加练习。
  本章中还介绍了几个新的运算符,在这里回顾一下已学过的运算符间的优先级关系是有好处的。表4-1总结了这些信息,所有的运算符是按优先级递减的顺序列出的。
表4-1  本章中出现过的运算符的优先级表
运  算  符 结  合  性
一元  -  ++  --  !  (类型转换) 从右到左
*  /  % 从左到右
+  - 从左到右
<  <=  >  >= 从左到右
==  != 从左到右
&& 从左到右
|| 从左到右
: 从右到左
=  op= 从右到左
  本章的重要知识点包括:
   简单语句由表达式跟上分号构成。
   “=”是C语言中用来赋值的运算符。因此,赋值是一个合法的表达式。它可以以嵌套赋值和多重赋值的形式出现。
   多个独立的语句可以组合为复合语句,通常称为程序块。
   控制语句分成两类:条件和迭代。
   genlib库定义了一种bool数据类型,用它来表示布尔型数据。bool型数据只有TRUE和FALSE两个值。
   使用关系运算符(<, <=, >, >=, ==和!=)能够产生布尔值,然后可以使用逻辑运算符(&&, ||和!)连接关系表达式。
   逻辑运算符&&和||是从左到右计算的,一旦能确定整个表达式的值就停止计算。这种行为叫做简化求值。
   当有些代码仅在特定情况下才执行或程序需要在两条执行路径之间选择其一时可以使用if语句。
   有些问题有这样的结构:在情况1下完成操作1,情况2下完成操作2,依此类推。此时就可以使用switch语句。
   while语句用来指定在一定条件满足的情况下重复执行某些操作。
   for语句指示一定次数的重复操作,它在每个周期中要更新下标变量的值。
  2) 程序设计既是一门科学,也是一门艺术。形成良好的程序设计风格需要掌握很多知识,而不只是记住一组规则。你必须通过实践并阅读其他程序来不断学习。书中在介绍程序设计时的一些特色可以为你提供帮助。
   本书包括大量的程序实例,这些实例说明了如何用C语句建立一个完整的程序。这些实例也可作为你自己设计程序时的模型。在许多情况下,你可以对书中的程序作简单的修改来解决一个新的程序设计问题。
图4-7  liftoff.c
   实例输出具有统一的格式,都是用一个带圆角的方框模拟计算机的屏幕。输入用黑体表示。
   语法框总结C语法的主要规则,对关键程序设计概念作简单的回顾。
语法:多行if语句
if (condition) {
  statements;
}
其中:condition是将要测试的布尔值。
      statements是当条件为TRUE时将要执行的一个语句块。
  3) 所有的程序员,即使是最好的程序员,都会犯错误。在程序中找出这些错误是非常重要的。以下这些特色有助于你培养这些技能。
   为了帮助你识别和纠正逻辑错误,本书包括了一些说明某些典型错误的程序。为了确保你不会把这些程序作为模型,本书在这些不正确的程序上面叠印了一个苍蝇的图像。
   常见错误对所有初级程序员常犯的错误给出了提示,并说明如何避免这些错误。代码中的错误行用苍蝇图案加以突出,旁边给出相应的说明。
  在大多数情况下,逻辑表达式不至于复杂到必须用真值表来计算的程度。唯一容易引起混淆的是!或!=和&&或||一起出现的情况。当说起某某情况不为真时(即需要用到!或!=的情况),日常用语和数学逻辑表达有时是相悖的,因此需要格外小心避免犯错。比如,在程序中要表达这样一个意思:x不等于2或3。通过这个条件测试语言表述,新程序员很可能会写出以下语句:
  如果用数学观点来观察这个条件测试,会发现只要x不等于2或只要x不等于3,if测试中的表达式均为TRUE。无论x取什么值,其中一个表达式必定为真,因为如果x为2,则它不可能同时为3,反之亦然。因此上面写出的if测试将永远成功。
  常见错误  当&&和||运算符与涉及!和!=运算符的关系测试一起使用时,必须非常小心。自然语言在逻辑上有一些模糊,而程序设计要求非常精确。
  4) 学习程序设计需要大量的实践。为了保证你能进行必要的实践,每章都包括了大量的练习和问题,测试你对各章内容的掌握程度。
   每章最后都有大量的复习题,其中包括对该章内容的回顾、代码的改编以及调试的练习。
复习题
  1. 判断题:本章包含了你需要知道的有关接口的所有信息。
  2. 定义下列术语:接口、软件包、抽象、实现者、客户。
  3. 实现者和客户的观点有何区别?
  4. 在C语言中,接口是如何表示的?
   程序设计练习让你自己动手进行更多的程序设计项目。
程序设计练习
  1. 虽然本章重点介绍数学的算法,但希腊人也非常喜欢研究一些其他类型的算法。例如,在希腊神话中,雅典的特修斯拿着一个线球,一边走一边放线,然后沿着线回到了出口,从人身牛头怪物的迷宫中逃了出来。特修斯的策略表示了从迷宫中出逃的一个算法,但这并不是解决这个问题的唯一算法。例如,如果迷宫内部没有回路,那么总是可以根据右手法则逃出来,即右手总是贴在墙上。这种方法有时会使你从原路返回,但能保证最终找到出口。
  例如,假设特修斯在迷宫中的位置用希腊字母Q表示:
致教师
  从1991~1992年,斯坦福大学决定调整计算机科学系的入门课程,使用C语言来代替原先使用的Pascal语言。选择ANSI C的主要原因如下:
   学生要求学习更为实用的语言。雇主期望学生们对业界使用的工具有一定的使用经验,而当今业界使用最广泛的语言工具是C和C++。在招聘中,使用Pascal语言的程序员的就业机会越来越少,于是有的学生开始质疑教育的初衷。
   许多基于Pascal语言的课程要求学生使用今后很可能用不到的Pascal语言编程。我们发现许多学生在放弃使用Pascal语言转而学习更现代的语言时,往往忘记曾经学过的程序设计风格和软件工程原则。现在改用学生们会继续使用的语言来教授这些技巧,结果发现他们能写出更好的程序。
   许多高级的计算机科学课程,尤其是偏系统方面的课程,要求学生使用C语言编程。在入门时就使用C语言可以使学生们在学习高级课程时有更多的经验。
   早日学习C语言为学习C++和面向对象的语言铺平了道路。由于学生在第一年的学习后,就有了较丰富的使用C语言的经验,学校就可以更早开设教学计划中的面向对象的系统设计这门课程。
   C语言中覆盖了一些重要的主题,如模块化开发和抽象数据类型等。这在Pascal语言环境里是很难讲授的。
   在最近五年中,在工程科学领域的编程中,C语言正在逐步取代Fortran的重要地位。
  考虑到近三年的经历,作者确信选用C语言作为计算机科学的入门课程是正确的选择,这种改变将使将来的程序更为强壮。
  与此同时,也要意识到在程序设计的早期课程中教授C语言并不是那么容易。C语言是为程序员设计的,并非为作为初学者的学生设计的。其中很多的特性只有在理解了大的概念框架后才有意义,而初学者往往意识不到这一点。从许多方面讲,C语言都是一门复杂的语言,向初学者讲授这门语言时必须很好地控制讲授的进度。
基于库函数的方法
  让教师能够控制C语言所固有的复杂性是本教材的中心目标之一。而控制复杂性又是程序员的重要职责。当面对一个很复杂的、不能立即解决的问题时,可将它分解成多个部分,然后单独思考每个部分的解决方案。此外,当某个部分达到了一定的复杂度时,可以将它抽象出来,定义为一个简单的接口。这样,用户就不必仔细理解这个抽象的细节,从而简化了程序的概念结构。
  这种方法也适用于程序设计的教学。为使知识更浅显易懂,本书采用了基于库函数的方法,该方法强调抽象的原则。这种方法的特征反映在以下两方面,这也是本书区别于其他入门教材之处:
  1) 在开始部分详细地介绍库和模块化开发,这是现代程序设计的基本概念。第二部分集中介绍库、接口、抽象和模块化开发的知识。这样,学生在学习数组之前就可以先学会高效使用这些技术。
  2) 本书通过库函数的使用来展示它们的功能。一方面告诉学生库函数可以隐藏复杂性,另一方面向他们说明了这个概念。本书介绍了一些新的库函数以帮助学生写出一些有用的程序,但在他们能消化吸收之前并不讲述库函数所隐藏的细节内容。它们的具体实现放在后面的章节讲述,以使学生能够更深刻地意识到抽象的重要作用。
  在1992年,作者曾试图只用ANSI C的库函数来讲授入门课程,但结果并不理想。每个新的主题都要求学生对C语言的其余部分很熟悉,这样便无法开展教学。例如,字符串操作尽管在概念上很简单,但在学生能灵活使用字符串之前,他们必须理解数组、指针和内存分配等机制。最优秀的学生也是到了学期末才理解,而大部分学生则根本没有明白这些概念。自从1993年初引进基于库函数的方法以来,学生理解起来更容易了,对计算机这个学科的了解也更多了。
  本书使用的库函数接口和相关实现见附录B。附录B还给出了获取源代码的方法。
讲述顺序
  本书的章节顺序与斯坦福大学的入门课程的授课顺序大致相同,只是将第17章的内容放在第二门课程中讲授。教师可以根据学生情况和授课的具体目标调整讲述顺序。以下简要地说明章节的内容以及它们之间的依赖关系。
  第1章追溯计算机的发展史,描述了程序设计的过程。该章不需要读者具备程序设计知识,仅仅是为其他章提供相关背景知识。
  第2章和第3章主要面向稍具或完全不具备程序设计基础的学生。这两章意图讲述一些概念性的内容,关注问题的解决而不纠缠于C语言的细节问题。初学者在面对纷繁的语法和结构时,往往全神贯注地学习规则而忽视了基本的概念,但在该阶段,对初学者来说,掌握概念比掌握规则重要得多。如果学生已经对程序设计有所了解,则这两章可以一带而过。
  第2章和第3章中的方法是非正规的,重点在于培养学生解决问题的能力。虽然这两章介绍了一些基本的语句形式和控制结构,但这些语句形式和控制结构只是完成一个特定任务的习语。第4章介绍每个语句的正式结构,并详细描述其语法和语义。该章还对布尔型数据进行了广泛的讨论。
  第5章开始介绍函数和过程。讲述的例子由简单到复杂。该章专门安排了一个小节讨论参数传递机制,并附有很多图表以帮助学生领会数据从一个函数向另一个函数传递的过程。该章的末尾给出一个重要的编程示例以说明逐步精化的概念。
  第6章所讲述的算法的概念是计算机科学的基础,但不要求所有的学生都掌握。若读者是工程人员或有潜力的计算机专业学生,那么这些材料对他们会大有裨益,给非专业的学生授课时则不必介绍得太过深入。
  作者发现,在入门课程中加入图形部分可以提高学生的学习兴趣,因此专门编写了第7章。在此阶段,学生已经学习了函数的机制,但还没有实际编写程序的欲望。让学生在屏幕上画出复杂的图形可以激发他们的这种欲望。一些主要的编程环境都实现了图形库,因此在大多数情况下都可以使用。
  第8章有两个主题,这两个主题从某种意义上讲是相互独立的。第一部分介绍接口的设计标准,这对于任何一个需要理解现代程序设计原理的人来说都是至关重要的。第二部分运用这些标准建立了一个随机数函数库。虽然学习random.h的具体接口并不如学习通用的接口设计标准那样重要,但后面的一些练习是需要使用随机数库函数的。
  第9章将字符串作为一个抽象的数据类型来介绍,并在一定程度上介绍了一些基于库函数的方法。利用动态字符串库,学生可以轻而易举地编写出一些复杂的字符串操作程序,即使他们并不能理解底层的表示方法。这些内容将在第14章中介绍。字符串的引入可以使学生编写出更优秀的程序。
  第一遍浏览过后,读者很容易忘记第10章的真正目的,仿佛它是第9章中对字符串讨论的继续。该章的重要价值并不在于程序Latin Pig,它虽然有趣但却不实用。举这个例子的目的是使读者意识到构造一个用来区分用户输入中各个单词的扫描器接口的必要性。不单单在第一门课程,而且在其后续课程中这个扫描器模块都将显示出其实用性,它将是学生在本课程中创造的最具实用价值的工具,同时也是说明模块化重要性的一个最佳例子。
  第11章~第16章分别介绍了一些基本的复合结构—数组、指针、文件、记录等,这样的介绍顺序在实际教学实践中的效果较好。考虑到作为基础语言的C语言的一些特性,为了要强调这些结构之间的联系,在介绍过数组后应尽快介绍指针。有了这些概念做基础,第14章就可以更加严密地讲述字符串数据,从而揭示出封装在抽象定义中的内容。第16章构造了一个数据驱动的教学程序,它综合运用了这些基本的数据结构,是本书中最复杂的一个程序设计示例。
  第17章包含了在第一门程序设计课程中经常出现的三个重要主题:递归、抽象数据类型和算法分析。在斯坦福,这些主题在第二门课程中用1/4学期的时间讲述。若决定在第一门程序设计课程中讲述递归,强烈建议早日开始介绍,以便学生有时间去消化吸收。教师可以在第5章后直接讲述递归函数,在第6章后讲述递归算法,也可以在第12章后将递归和算法分析放在一起讲解。
教师资源
  教师要获取本书的相关教学资源,请到华章网站www.hzbook.com上申请。
致谢
  本书的前身是课程讲义,在此基础上进行了大量改进而形成本书,这很大程度上要归功于使用本书的读者的建议。在这里我要衷心感谢斯坦福大学的讲师们:Jon Becker、Katie Capps、Stephen Clausing、Todd Feldman、Allison Hansen、Margaret Johnson、Jim Kent、Andrew Kosoresow、Mehran Sahami和Julie Zelenski,他们在过去三年的14个班讲授了本书。此外,我还要感谢所有的班导师、助教和教务人员:Felix Baker、John Lilly、Sandy Nguyen、Bryan Rollins以及Scott Wiltamuth,他们提供了必要的后勤支持。
  本书中很多好的想法来自于一个计算机入门教学的社团,这是我于1992~1993年倡导成立的。它为解决一些困难问题和对教材进行重要改进提供了一个讨论的平台。在此我想向所有参与其中的人表示感谢:Perry Arnold、Jon Becker、Tom Bogart、Karl Brown、Bryan Busse、Katie Capps、Peter Chang、Scott Cohen、Stacey Doerr、Jeff Forbes、Stephen Freund、Jon Goldberg、Tague Griffith、Matt Harad、Lindsay Lack、Christine Lee、Tricia Lee、John Lilly、Albert Lin、Mara Mather、Hugh McGuire、Jeffrey Oldham、David O誎eefe、Bryan Rollins、Samir Saxena、Nikhyl Singhal、Eric Tucker、Garner Weng、Howard Wong-Toi和John Yong。
  同时,我还要感谢所有使用本书并为本书的初稿提出意见的学生们:Adjo Amekudzi、Eric Anderson、Andrew Arnold、Kevin Berk、Kevin Carbajal、Ajit Chaudhari、Alida Cheung、Hye-won Choi、Elisabeth、Christensen、Ralph Davis、Joel Firehammer、Peter Frelinghuysen、Trevor gattis、Teddy Harris、Heather Heal、Enoch Huang、Ann Lee、Ted Lee、Daphne Lichtensztajn、Lisa Maddock、Allan Marcus、Brad McGoran、Forrest Melton、Adrienne Osborn、Masatoshi Saito、Anne Stern、Ricardo Urena和Nichole Wilson。
  在1993~1994年,几位来自其他大学的教师试用了本书的初稿并提出了一些很有价值的建议。我要特别感谢哈佛大学的Margo Seltzer,内华达大学里诺分校的Rob Langsner,马里兰大学(巴尔的摩州)的Richard Chang,拉萨尔大学的Jane Turk和维斯特蒙德学院的Kim Kihlstrom。他们为本书早期阶段的修改提供了大力帮助。
  我还要感谢对本书进行审校的人员:
  Stephen Allan 犹他州立大学
  James Schmolze 塔夫茨大学
  Don Goelman Villanova大学
  Michael Skolnick Rensselaer Polytechnic
  Stan Kolasa Rutgers大学
  Jeffrey A.Slomka 西南得克萨斯州立大学
  Harry R.Lewis 哈佛大学
  Kevin Smith Emory大学
  Bill Muellner Elmhurst学院
  Phil Tromovitch SUNY-Stony Brook
  Rayno Niemi 罗切斯特理工学院
  John A.Trono St.Michaels昭г Robert G. Plantz Sonoma州立大学
  Robert Walker Rensselaer PolyTechnic
  David Rosenthal Seton Hall
  Richard Weinand Wayne州立大学
  此外,我的一些朋友和同事也对本书提供了有益的建议,他们是:Josh Barnes、Pavel Curtis、Kathleen Kells、James Finn和Steve Lewin-Berlin。
  本书最终版本的成形还要感谢Addison-Wesley的编辑,他们在整个过程中一直不遗余力地提供着帮助。在这里要特别感谢Lynne Doran Cote、Sue Gleason、Peter Gordon、Laura Michaels、Jim Rigney、Karen Stone和Amy Willcutt所作的大量工作。我很幸运有Lauren Rusk作为我的合作伙伴和编辑,没有她这一切都不会成为现实。

上架指导

计算机科学及应用

封底文字

本书是一本计算机科学的经典教材,强调软件工程和优秀的程序设计风格。此外,学生还可以从书中学习到ANSI C的基础知识,这些内容已经成为计算机行业的标准。作者的写作风格使得书中深奥的概念变得易于理解和引人入胜。

本书集中讨论库和抽象的用法,这是当代程序设计技术中最基本的知识。作者使用库来隐藏C语言的复杂性,更加突出主题,使学生可以较好地掌握每一个主题的精髓。然后,进一步给出每个库的底层实现,较好地展示了库自身的抽象威力。

本书从基础开始讲起,是C语言的入门教材。本书已经被美国斯坦福大学、哥伦比亚大学等多所大学和学院成功采用,是一本适合高级院校计算机及相关专业使用的优秀教材。

作者简介

(美)Eric S. Roberts 著:Eric S. Roberts是美国斯坦福大学计算机科学系教授,并担任系里主管教学事务的副主任,同时他还是工学院的Charles Simonyi讲席教授。他于1980年在哈佛大学应用数学系获得博士学位,并曾在DEC公司位于加州Palo Alto的系统研究中心做过5年的研究工作。作为一位获得高度评价的教育工作者,Roberts还因其在本科生教学中的杰出贡献获得了1993年的Bing Award奖。

译者简介

翁惠玉 张冬茉 杨鑫 蒋文新 译:暂无简介

译者序

随着计算机产业的迅速发展,对计算机专业人才的需求也日益迫切。而程序设计是所有计算机专业人才必备的基础知识和技能。俗话说“万事开头难”,如何使学生顺利地进入程序设计的大门,如何熟悉和精通程序设计,也是计算机专业教学的难题。
  本书是一本计算机科学的经典教材,是作者二十多年来从事计算机教学的经验的总结,它提供了丰富的计算机科学的基础知识和程序设计的专门知识。本书具有鲜明的特色。首先,用ANSI C作为教学语言。C语言是目前使用最广泛的教学语言,选用C语言可以使学生毕业后很快就能投入实际工作,并为学习C++和面向对象的语言铺平了道路。第二,采用了基于库函数的方法,强调抽象的原则。本书相当详细地介绍了库和模块化开发,介绍了如何通过库隐藏程序的复杂性,这些是现代程序设计的基本概念。第三,在程序设计中最重要的是从陈述问题过渡到解决问题,本书以通俗易懂的方式讲述了这一过程,使学生能轻松而有趣地学习程序设计。
  程序设计既是一门科学,也是一门艺术。学习良好的程序设计需要掌握很多知识,而不只是记住一组规则。必须通过实践以及阅读其他程序来学习。本书包括大量的程序实例,这些实例说明了如何用C语句建立一个完整的程序,如何培养良好的程序设计风格。每章都用丰富的复习题作为知识点的总结,并包含大量的程序设计练习让读者自己动手做更多的程序设计项目。
  正是因为本书具有的上述优点,我们认为把本书译成中文能让更多的学生从中获益,从而打下扎实的程序设计的基础。
  参加本书翻译工作的有翁惠玉、张冬茉、杨鑫和蒋文新,由翁惠玉对全书进行审校。本书也是上海交通大学《程序设计》课程所选用的教材。在翻译过程中得到了整个课程小组十多位教师的大力帮助,在此表示衷心的感谢。由于时间和水平的限制,书中难免有错漏之处,敬请读者指正。

译  者
2004年8月

图书目录

译者序
前言

第1章  概述 1
1.1  计算简史 1
1.2  什么是计算机科学 4
1.3  计算机硬件简介 5
1.3.1  CPU 5
1.3.2  内存 6
1.3.3  辅助存储器 6
1.3.4  I/O设备 6
1.4  算法 7
1.5  程序设计语言和编译 7
1.6  编程错误和调试 9
1.7  软件维护 10
1.8  软件工程的重要性 11
1.9  关于C程序设计语言的一些思考 11
小结 12
复习题 12
第一部分  C语言程序设计基础
第2章  通过例子学习 16
2.1  “Hello world”程序 17
2.1.1  注释 17
2.1.2  库包含 18
2.1.3  主程序 18
2.2  两个数的加法程序 20
2.2.1  输入阶段 21
2.2.2  计算阶段 23
2.2.3  输出阶段 23
2.3  有关程序设计过程的观点 24
2.4  数据类型 25
2.4.1  浮点型数据 25
2.4.2  字符串类型的数据 26
2.5  表达式 28
2.5.1  常量 28
2.5.2  变量 29
2.5.3  赋值语句 31
2.5.4  运算符和操作数 32
2.5.5  整型数和浮点型数的结合 33
2.5.6  整数除法和求余运算符 34
2.5.7  优先级 34
2.5.8  优先级法则的应用 36
2.5.9  类型转换 37
小结 39
复习题 40
程序设计练习 41
第3章  问题求解 44
3.1  程序设计习语和范例 44
3.1.1  复合赋值习语 45
3.1.2  自增和自减运算符 47
3.2  解决规模稍大的问题 47
3.3  控制语句 48
3.3.1  重复N次习语 49
3.3.2  迭代和循环 50
3.3.3  下标变量 50
3.3.4  初始化的重要性 51
3.3.5  读入-直到-标志习语 53
3.3.6  创造一个更实用的应用程序 54
3.3.7  条件执行和if语句 56
3.4  一个调试练习 58
3.5  格式化输出 61
3.5.1  printf的格式码 62
3.5.2  控制空格、对齐方式和精度 63
3.6  构思一个程序 65
3.6.1  程序设计风格 66
3.6.2  设计时考虑将来的修改 67
3.6.3  #define机制 67
小结 69
复习题 69
程序设计练习 70
第4章  语句形式 74
4.1  简单语句 74
4.1.1  赋值的嵌套 76
4.1.2  多重赋值 76
4.1.3  程序块 77
4.2  控制语句 78
4.3  布尔型数据 78
4.3.1  关系运算符 79
4.3.2  逻辑运算符 79
4.3.3  简化求值 81
4.3.4  标志 82
4.3.5  避免布尔表达式中的冗余 82
4.3.6  布尔计算示例 83
4.4  if语句 84
4.4.1  单行if语句 85
4.4.2  多行if语句 86
4.4.3  if/else语句 86
4.4.4  级联if语句 86
4.4.5  : 运算符(可选的) 87
4.5  switch语句 89
4.6  while语句 91
4.6.1  while循环的应用 91
4.6.2  无限循环 93
4.6.3  解决半途退出问题 93
4.7  for语句 95
4.7.1  嵌套的for循环 97
4.7.2  for和while的关系 98
4.7.3  for语句中浮点型数据的使用问题 99
小结 100
复习题 101
程序设计练习 102
第5章  函数 105
5.1  使用库函数 105
5.2  函数声明 107
5.3  自己编写函数 108
5.3.1  return语句 109
5.3.2  将函数与主程序放在一起 110
5.3.3  包含内部控制结构的函数 111
5.3.4  返回非数字值的函数 113
5.3.5  谓词函数 113
5.3.6  测试字符串是否相等的谓词函数 115
5.4  函数调用过程机制 116
5.4.1  参数传递 117
5.4.2  在其他函数中调用函数 119
5.5  过程 125
5.6  逐步精化 127
5.6.1  从顶开始 127
5.6.2  实现PrintCalendar 128
5.6.3  实现PrintCalendarMonth 128
5.6.4  完成最后的片段 132
小结 137
复习题 138
程序设计练习 138
第6章  算法 143
6.1  测试素数 144
6.1.1  一个IsPrime的简单版本 144
6.1.2  验证一个策略是否表示一个算法 144
6.1.3  说明IsPrime算法的正确性 145
6.1.4  改进算法的效率 146
6.1.5  在各个可选方案中选择 148
6.2  计算最大公约数 149
6.2.1  brute-force算法 149
6.2.2  欧几里得算法 150
6.2.3  欧几里得算法的正确性说明(可选) 150
6.2.4  比较GCD算法的效率 151
6.3  数值算法 151
6.3.1  连续逼近 152
6.3.2  报告错误 153
6.4  级数展开 154
6.4.1  Zeno悖论 154
6.4.2  用级数展开法设计平方根函数 156
6.4.3  估计平方根的泰勒级数展开
(可选) 156
6.4.4  泰勒级数近似的实现 157
6.4.5  停留在收敛半径之内 159
6.5  指定数值类型的大小 161
6.5.1  整数类型 161
6.5.2  无符号类型 162
6.5.3  浮点类型 162
小结 163
复习题 163
程序设计练习 164
第二部分  库和模块化开发
第7章  库和接口:一个简单的图形库 170
7.1  接口的概念 171
7.2  图形库介绍 172
7.2.1  graphics.h的基本模型 173
7.2.2  graphics.h接口的函数 174
7.2.3  软件包初始化 178
7.2.4  画直线 178
7.2.5  画圆和弧 179
7.2.6  获取有关图形窗口的信息 181
7.3  建立自己的工具 182
7.3.1  定义DrawBox 182
7.3.2  定义DrawCenteredCircle 184
7.3.3  绝对坐标和相对坐标间的切换 184
7.3.4  定义过程的好处 185
7.4  解决一个较大的问题 185
7.4.1  使用逐步精化 186
7.4.2  实现DrawHouse过程 187
7.4.3  寻找共同的模式 188
7.4.4  结束分解 189
小结 193
复习题 194
程序设计练习 195
第8章  设计接口:一个随机数库 200
8.1  接口设计 201
8.1.1  同一主题的重要性 201
8.1.2  简单性和信息隐藏的原则 202
8.1.3  满足客户的需要 202
8.1.4  通用工具的优势 203
8.1.5  稳定性的价值 203
8.2  用计算机生成随机数 204
8.2.1  确定行为与非确定行为 204
8.2.2  随机数和伪随机数 204
8.2.3  ANSI C中生成伪随机数 205
8.2.4  改变随机数的范围 206
8.2.5  将此问题通用化 210
8.3  在库中保存工具 212
8.3.1  接口的内容 212
8.3.2  写random.h接口 213
8.3.3  random.c的实现 214
8.3.4  构造客户程序 215
8.3.5  初始化随机数发生器 217
8.4  评价random.h接口的设计 219
8.4.1  产生随机实数 220
8.4.2  模拟一个概率事件 220
8.4.3  在接口中包含头文件 221
8.4.4  完成随机数软件包的实现 231
8.5  使用随机数软件包 222
小结 225
复习题 226
程序设计练习 226
第9章  字符串和字符 233
9.1  枚举的原理 234
9.1.1  在机器内部表示枚举类型 234
9.1.2  将枚举类型表示为整数 235
9.1.3  定义新的枚举类型 235
9.1.4  枚举类型的操作 237
9.1.5  标量类型 238
9.2  字符 238
9.2.1  数据类型char 238
9.2.2  ASCII代码 239
9.2.3  字符常量 240
9.2.4  ASCII代码方案的重要特性 240
9.2.5  特殊字符 241
9.2.6  字符运算 242
9.2.7  ctype.h接口 243
9.2.8  涉及字符的控制语句 244
9.2.9  字符的输入输出 245
9.3  字符串作为抽象数据类型 245
9.3.1  分层抽象 246
9.3.2  抽象类型的概念 247
9.4  strlib.h接口 247
9.4.1  确定字符串的长度 248
9.4.2  从一个字符串中选择字符 248
9.4.3  连接 249
9.4.4  将字符转换为字符串 250
9.4.5  抽取字符串的一部分 250
9.4.6  比较两个字符串 251
9.4.7  在一个字符串内搜索 252
9.4.8  大小写转换 255
9.4.9  数值转换 255
9.4.10  效率和strlib.h库 257
小结 257
复习题 258
程序设计练习 260
第10章  模块化开发 264
10.1  Pig Latin—一个模块化开发的
案例研究 266
10.1.1  应用自顶向下的设计 266
10.1.2  使用伪代码 267
10.1.3  实现TranslateLine 268
10.1.4  考虑空格和标点符号的问题 268
10.1.5  精化单词的定义 270
10.1.6  设计记号扫描器 271
10.1.7  完成TranslateLine的实现 272
10.1.8  定义扫描器模块接口 274
10.2  在模块中维护内部状态 276
10.2.1  全局变量 276
10.2.2  使用全局变量的危险性 277
10.2.3  保持变量的模块私有化 277
10.2.4  初始化全局变量 278
10.2.5  私有函数 279
10.3  实现扫描器抽象 280
小结 286
复习题 286
程序设计练习 286
第三部分  复合数据类型
第11章  数组 294
11.1  数组 295
11.1.1  数组声明 295
11.1.2  数组选择 296
11.1.3  一个简单的数组实例 297
11.1.4  改变下标值的范围 298
11.2  数据的内部表示法 299
11.2.1  比特、字节和字 299
11.2.2  内存地址 300
11.2.3  运算符sizeof 301
11.2.4  变量的内存分配 301
11.2.5  引用超出数组范围的元素 302
11.3  数组作为参数进行传递 303
11.3.1  元素个数的通用化 304
11.3.2  数组参数传递机制 306
11.3.3  实现函数PrintIntegerArray和GetIntegerArray 308
11.3.4  实现函数ReverseIntegerArray 309
11.3.5  实现函数SwapIntegerElements 310
11.4  使用数组制作表格 314
11.5  数组的静态初始化 320
11.5.1  自动确定数组大小 320
11.5.2  确定初始化数组的大小 321
11.5.3  初始化数组和标量类型 321
11.6  多维数组 321
11.6.1  向函数传送多维数组 322
11.6.2  初始化多维数组 323
小结 324
复习题 324
程序设计练习 326
第12章  查找和排序 332
12.1  查找 332
12.1.1  在整数数组中查找 333
12.1.2  关于查找的另一个更复杂
的例子 335
12.1.3  线性查找 337
12.1.4  二分查找 338
12.1.5  查找算法的相对效率 339
12.2  排序 341
12.2.1  对一个整数数组排序 342
12.2.2  选择排序算法 343
12.2.3  选择排序效率的评估 346
12.2.4  测试程序的运行时间 347
12.2.5  选择排序的算法分析 347
小结 348
复习题 348
程序设计练习 349
第13章  指针 354
13.1  将地址作为数据值 355
13.2  C语言的指针操作 356
13.2.1  在C语言中声明指针变量 356
13.2.2  基本的指针操作 357
13.2.3  特殊指针NULL 359
13.3  通过引用传递参数 359
13.3.1  设计函数SwapInteger 361
13.3.2  用引用调用返回多个结果 362
13.3.3  过度使用引用调用的危险 364
13.4  指针和数组 364
13.4.1  指针运算 365
13.4.2  运算符++和--的新作用 367
13.4.3  指针的自增和自减 369
13.4.4  指针和数组的关系 369
13.5  动态分配 371
13.5.1  Void *类型 371
13.5.2  动态数组 372
13.5.3  查找malloc中的错误 373
13.5.4  释放内存 374
小结 374
复习题 375
程序设计练习 377
第14章  再论字符串 381
14.1  string类型的概念表示 381
14.1.1  字符串作为数组 382
14.1.2  字符串作为指针 384
14.1.3  字符串作为抽象类型 384
14.1.4  字符串参数 385
14.1.5  字符串变量 385
14.1.6  指针和数组变量间的区别 387
14.1.7  决定字符串的表示方法 388
14.2  ANSI字符串库 389
14.2.1  strcpy函数 390
14.2.2  strncpy函数 392
14.2.3  strcat和strncat函数 393
14.2.4  strlen、strcmp和strncmp函数 394
14.2.5  strchr、strrchr和strstr函数 394
14.2.6  ANSI字符串函数的应用 395
14.3  strlib库的实现 397
14.3.1  实现转换函数 398
14.3.2  strlib分配函数的实现 398
小结 400
复习题 400
程序设计练习 401
第15章  文件 404
15.1  文本文件 404
15.2  C语言中文件的使用 406
15.2.1  声明FILE*类型的变量 406
15.2.2  打开文件 406
15.2.3  执行I/O操作 407
15.2.4  关闭文件 407
15.2.5  标准文件 408
15.3  字符I/O 408
15.3.1  文件更新 410
15.3.2  在输入文件中重新读取字符 413
15.4  面向行的I/O 415
15.5  格式化I/O 417
15.5.1  printf的三种形式 417
15.5.2  scanf函数 417
15.5.3  用scanf读入字符串 419
15.5.4  格式化I/O的一个实例 420
15.5.5  使用scanf的局限 423
小结 423
复习题 424
程序设计练习 425
第16章  记录 431
16.1  数据记录的概念 432
16.2  记录在C语言中的使用 432
16.2.1  定义一个结构类型 433
16.2.2  声明结构变量 433
16.2.3  记录选择 434
16.2.4  记录初始化 434
16.2.5  简单记录 434
16.3  数组与记录的结合 435
16.4  记录的指针 437
16.4.1  定义一个指向记录类型的指针 438
16.4.2  为记录数据分配空间 439
16.4.3  对记录指针进行操作 440
16.5  创建记录的数据库 440
16.5.1  创建员工信息数据库 441
16.5.2  数据库的使用 443
16.6  基于记录的应用程序设计 444
16.6.1  使用数据库的重要性 444
16.6.2  问题的框架 445
16.6.3  设计内部表示 445
16.6.4  设计外部结构 447
16.6.5  程序代码 448
16.6.6  数据驱动设计方法的重要性 455
小结 455
复习题 458
程序设计练习 458
第17章  深入学习 465
17.1  递归 465
17.1.1  递归的简单说明 466
17.1.2  Factorial函数 467
17.1.3  递归信任 471
17.1.4  递归范例 472
17.1.5  排列的生成 472
17.1.6  用递归的思想思考 475
17.2  抽象数据类型 475
17.2.1  队列抽象 476
17.2.2  以队列抽象表示类型 476
17.2.3  queue.h 接口 478
17.2.4  实现队列抽象 479
17.2.5  队列抽象的另一种实现方法 484
17.3  算法分析 486
17.3.1  评估算法效率 487
17.3.2  O标记 487
17.3.3  再看选择排序 488
17.3.4  分而治之策略 489
17.3.5  合并两个数组 490
17.3.6  合并排序算法 491
17.3.7  合并排序的计算复杂性 492
17.3.8  比较平方复杂性与NlogN复杂性的性能 493
小结 493
复习题 494
程序设计练习 495
附   录
附录A  C语言的语法和结构总结 501
附录B  库源代码 517

教学资源推荐
作者: [美]沃特·萨维奇 (Walter Savitch) 肯里克·莫克(Kenrick Mock)著
作者: (美)Al Kelley Ira Pohl
作者: 主编 牛力 韩小汀 参编 闫石 杨凯 刘楠楠
参考读物推荐
作者: 申远 古万荣 等编著
作者: 王华 朱时银 史兰 等
作者: Donald Thompson;Rob S. Miles