《程序设计语言 概念和结构 原书第2版》PDF下载

  • 购买积分:15 如何计算积分?
  • 作  者:(美)Ravi Sethi著;裘宗燕等译
  • 出 版 社:北京:机械工业出版社
  • 出版年份:2002
  • ISBN:711109431X
  • 页数:467 页
图书介绍:本书是国外比较成功的一本讨论程序设计语言的教科书,已在一些学校使用多年。书的主要内容包括:引论、命令式程序设计、面向对象的程序设计、函数式程序设计、其他程序设计范型以及语言的描述六大部分。本书适合作为计算机及其相关专业本科高年级学生的教材或教学参考书,或作为研究生的基础课程教材或参考书,也适合其他相关的技术人员参考。本书的学习基础是学过用过一种或几种程序设计语言(最好是Pascal/C/C++),有一定程序设计经验,并对数据结构等计算机基础知识有所理解。

第一部分 引言 2

第1章 程序设计语言的位置 2

1.1 走向高级语言 2

1.1.1 机器语言是晦涩难懂的 3

1.1.2 汇编语言是低级的 3

1.1.3 高级语言的优点 5

1.2 规模的问题 6

1.2.1 人的错误因素 6

1.2.2 程序设计语言扮演的角色 7

1.3 程序设计范型 7

1.3.1 命令式程序设计 8

1.3.2 函数式程序设计 9

1.3.3 面向对象的程序设计 11

1.3.4 逻辑程序设计 12

1.3.5 语言的选择 12

1.4 语言实现:在裂谷上架桥 12

1.4.1 编译 13

1.4.2 解释 14

1.4.3 编译器和解释器:对比 15

练习 15

引文注记 16

第2章 语言的描述:语法结构 18

2.1 表达式的记法 20

2.1.1 前缀记法 20

2.1.2 后缀记法 21

2.1.3 中缀记法:优先级和结合性 21

2.1.4 混合记法 22

2.2 抽象语法树 22

2.3 词语法 24

2.4 上下文无关文法 25

2.4.1 文法介绍 25

2.4.2 上下文无关文法的定义 26

2.4.3 BNF:Backus-Naur范式 26

2.4.4 语法分析树描绘了具体语法 27

2.4.5 语法的歧义性 28

2.4.6 悬空的else的歧义性 28

2.4.7 导出 29

2.5 表达式的文法 30

2.5.1 中缀表达式中的表列 30

2.5.2 从抽象语法到具体语法 31

2.6 文法的各种变形 33

2.6.1 扩充的BNF 33

2.6.2 语法图 35

练习 35

引文注记 38

第二部分 命令式程序设计 41

第3章 语句:结构化程序设计 41

3.1 结构化程序设计的必要性 41

3.1.1 静态程序和动态计算 41

3.1.2 命令式语言的设计原则 42

3.1.3 一个例子 42

3.1.4 不变式:程序设计 43

3.2 语法制导的控制流 44

3.2.1 语句的复合 44

3.2.2 选择:条件语句 45

3.2.3 循环结构:while和repeat 46

3.2.4 定性迭代:for循环 48

3.2.5 选择:case语句 48

3.2.6 case语句的实现 49

3.3 设计考虑:语法 50

3.3.1 序列:分隔符和终止符 50

3.3.2 避免悬空的else 52

3.4 处理循环中的特殊情况 53

3.4.1 循环中的break和continue语句 54

3.4.2 return语句 56

3.4.3 goto语句 56

3.5 使用不变式做程序设计 56

3.5.1 前条件和后条件 57

3.5.2 实例:线性搜索 58

3.6 部分正确性的证明规则 60

3.6.1 断言和公式 61

3.6.2 复合语句的证明规则 61

3.6.3 条件语句的证明规则 62

3.6.4 有关while语句的规则 62

3.6.5 关于赋值的规则 62

3.6.6 化简规则 63

3.6.7 Pascal中的语句 63

3.7 C语言的控制流 63

3.7.1 赋值运算符 64

3.7.2 表达式里的赋值 65

3.7.3 C语言的for循环:非定性迭代 65

3.7.4 循环中的break和continue语句 66

练习 66

引文注记 70

第4章 类型:数据表示 72

4.1 类型的作用 72

4.1.1 值和它们的类型 73

4.1.2 类型表达式 73

4.1.3 本章中的类型 73

4.1.4 静态布局决策 74

4.1.5 有关类型名、数组和记录的预览 75

4.2 基本类型 76

4.2.1 枚举 76

4.2.2 整型和实型 77

4.2.3 布尔表达式的短路求值 77

4.2.4 子域 78

4.2.5 基本类型的布局 78

4.2.6 程序设计的风格:字符和类型转换 78

4.3 数组:元素的序列 79

4.3.1 数组类型 79

4.3.2 数组的布局 81

4.3.3 数组边界和存储分配 82

4.3.4 数组的值和初始化 83

4.4 记录:命名的域 84

4.4.1 记录类型有一组特定的域 84

4.4.2 变量声明分配存储空间 84

4.4.3 对记录的操作 84

4.4.4 数组和记录的比较 85

4.5 联合和变体记录 85

4.5.1 变体记录的布局 86

4.5.2 变体记录损害类型安全 87

4.6 集合 88

4.6.1 集合的值 88

4.6.2 集合类型 88

4.6.3 集合类型的实现 88

4.6.4 集合的运算 88

4.7 指针:效率和动态存储分配 89

4.7.1 指针类型 90

4.7.2 指针操作 90

4.7.3 数据结构的增长和缩减 90

4.7.4 悬空指针和存储流失 91

4.7.5 指针作为代理 92

4.8 两种字符串列表 95

4.8.1 pascal的一种表示 95

4.8.2 C语言的一种表示 96

4.9 类型和错误检查 97

4.9.1 变量约束:变量的类型 98

4.9.2 类型系统:表达式的类型 98

4.9.3 类型检查的基本规则 99

4.9.4 类型名和类型等价 99

4.9.5 静态和动态类型检查 101

练习 102

引文注记 104

第5章 过程活动 105

5.1 对过程的介绍 106

5.1.1 过程调用 106

5.1.2 过程的要素 106

5.1.3 递归:过程的多个活动 109

5.1.4 过程的价值 109

5.2 参数传递方式 110

5.2.1 值调用 110

5.2.2 引用调用 111

5.2.3 值结果调用 113

5.3 名字的作用域规则 114

5.3.1 词法作用域和动态作用域 114

5.3.2 词法作用域与局部变量的重命名 115

5.3.3 宏展开与动态作用域 116

5.3.4 按名调用与词法作用域 117

5.4 源文本中的嵌套作用域 118

5.4.1 声明的作用域 118

5.4.2 嵌套作用域:C中的变量声明 119

5.4.3 嵌套作用域:Pascal中的过程声明 121

5.5 活动记录 122

5.5.1 活动间的控制流 122

5.5.2 活动记录的元素 124

5.5.3 堆存储分配和释放 127

5.5.4 堆栈分配和释放 127

5.5.5 在编译时分配静态变量 128

5.6 词法作用域:在C中的过程 128

5.6.1 C程序的存储布局 129

5.6.2 局部变量的存储 129

5.6.3 C的过程调用和返回 130

5.6.4 运行时的变量访问 131

5.6.5 过程作为参数 131

5.6.6 悬空指针 132

5.6.7 尾递归消除 132

5.7 词法作用域:嵌套过程和pascal 135

5.7.1 可见性规则 135

5.7.2 访问非局部变量:控制链和访问链 136

5.7.3 过程的调用和返回 138

5.7.4 过程作为参数 139

5.7.5 用于快速访问的区头向量 139

练习 141

引文注记 143

第三部分 面向对象程序设计 147

第6章 数据和操作 147

6.1 程序构造的结构 147

6.1.1 过程:提高计算的层次 148

6.1.2 程序静态文本的模块划分 149

6.1.3 用户定义数据类型 150

6.1.4 几种方法的比较 151

6.2 信息隐藏 152

6.2.1 动机:区分行为与实现 152

6.2.2 数据不变式 154

6.2.3 数据的可见性 154

6.2.4 实现的隐藏和程序开发 154

6.3 使用模块设计程序 155

6.3.1 表达式求值程序的设计 155

6.3.2 程序组织 157

6.3.3 讨论:程序组织 161

6.4 模块和用户定义类型 161

6.4.1 导出名字和导入名字 161

6.4.2 导出类型 162

6.5 C++的类声明 164

6.5.1 类声明中的数据和操作 164

6.5.2 将类名作为定义的类型使用 166

6.5.3 公用、私用和保护成员 167

6.6 C++的动态存储分配 168

6.6.1 指向对象的指针 168

6.6.2 用建构函数和析构函数进行动态存储分配 169

6.6.3 链表的单元 169

6.7 模板:参数化类型 172

6.8 C++对象的实现 173

6.8.1 一个简单实现 173

6.8.2 函数体的在线展开 174

6.8.3 类声明中的私用变量 174

练习 175

引文注记 178

第7章 面向对象程序设计 179

7.1 什么是对象 179

7.1.1 对象的外部和内部视图 179

7.1.2 形状的属性 180

7.2 面向对象的思想 181

7.2.1 将对象组织为类层次结构 181

7.2.2 对象响应消息,对象具有状态 182

7.3 继承 184

7.3.1 接收者决定一个消息的含义 185

7.3.2 信息隐藏是为了可扩充性 186

7.3.3 添加子类 187

7.3.4 对象和类 189

7.4 用C++语言做面向对象的程序设计 189

7.4.1 C++语言回顾 189

7.4.2 基类和派生类 190

7.4.3 公用基类 190

7.4.4 虚函数 191

7.4.5 C++中形状实例的细节 193

7.4.6 初始化和继承 194

7.5 一个扩充的C++例子 194

7.5.1 素数筛 194

7.5.2 基类 196

7.5.3 派生类 196

7.5.4 基类和派生类的初始化 196

7.5.5 子类型和超类型 197

7.5.6 虚函数 198

7.5.7 生成过滤器对象 199

7.5.8 剩余的程序 199

7.6 派生类和信息隐藏 199

7.6.1 公用和私用的基类 200

7.6.2 私用性原理 200

7.6.3 继承成员的可访问性 201

7.7 Smalltalk中的对象 202

7.7.1 系统类 202

7.7.2 类定义中的元素 203

7.7.3 消息语法 205

7.8 Smalltalk对象的self 207

7.8.1 发送给self的消息 208

7.8.2 发送给super的消息 208

练习 209

引文注记 212

第四部分 函数式程序设计 215

第8章 函数式程序设计的要素 215

8.1 一个很小的表达式语言 215

8.1.1 Little Quilt操作什么 215

8.1.2 为方便而做的扩充 217

8.1.3 评论:Little Quilt的设计 219

8.2 类型:值和运算 220

8.2.1 构造和检查值的操作 221

8.2.2 基本类型 221

8.2.3 类型的积 221

8.2.4 ML中的类型 223

8.3 函数声明 224

8.3.1 函数作为算法 225

8.3.2 函数声明和应用的语法 225

8.3.3 递归函数 226

8.4 表达式的求值方式 226

8.4.1 最内求值 227

8.4.2 选择性求值 227

8.4.3 递归函数的求值 228

8.4.4 从左到右的最外求值 228

8.4.5 短路求值 230

8.5 词法作用域 231

8.5.1 val约束 231

8.5.2 fun约束 232

8.5.3 嵌套的约束 233

8.5.4 同时约束 233

8.6 类型检查 234

8.6.1 类型推理 234

8.6.2 类型名和类型等价 235

8.6.3 重载:多重含义 235

8.6.4 强制:隐式类型转换 236

8.6.5 多态性:参数化类型 236

练习 237

引文注记 240

第9章 一个有类型语言中的函数式程序设计 241

9.1 表的探查 241

9.1.1 表上的运算 242

9.1.2 定义在表上的两个函数:append和reverse 242

9.2 函数的分情况声明 244

9.2.1 函数应用 245

9.2.2 模式 246

9.2.3 模式和情况分析 246

9.3 函数作为一级的值 248

9.3.1 将函数映射到表的各个元素上 249

9.3.2 匿名函数 251

9.3.3 选择性复制 251

9.3.4 积累结果 252

9.4 ML:隐含类型 253

9.4.1 类型推理 253

9.4.2 参数化多态性 254

9.5 数据类型 254

9.5.1 值构造符 255

9.5.2 微分:一个传统实例 257

9.5.3 多态数据类型 258

9.5.4 讨论 259

9.6 ML的异常处理 259

9.7 在Standard ML中实现Little Quilt 261

9.7.1 一些辅助函数 262

9.7.2 拼块的表示 263

9.7.3 sew运算 263

9.7.4 turn运算 264

9.7.5 拼块的显示 266

9.7.6 Little Quilt中的表达式 267

练习 269

引文注记 271

第10章 表的函数式程序设计 272

10.1 Scheme,一种Lisp方言 272

10.1.1 为什么用Scheme 273

10.1.2 如何与Scheme解释器交互 273

10.1.3 怎样写表达式 274

10.1.4 怎样定义函数 275

10.1.5 匿名函数值 275

10.1.6 条件式 275

10.1.7 let结构 276

10.1.8 引号 277

10.2 表的结构 278

10.2.1 表元素 278

10.2.2 表的运算 279

10.3 表的操作 280

10.3.1 一个有用的函数 281

10.3.2 连接两个表 281

10.3.3 将函数映射到表的所有元素上 282

10.3.4 关联表 283

10.3.5 子表达式的表 284

10.3.6 一个参数化的函数 285

10.4 启发性的实例:微分 286

10.4.1 语法制导的微分 286

10.4.2 常量 287

10.4.3 变量 287

10.4.4 对和式与乘积的微分规则 287

10.4.5 和式的微分 287

10.4.6 乘积的微分 289

10.4.7 对微分程序的总结 289

10.5 表达式化简 290

10.6 表的存储管理 292

10.6.1 cons分配单元 293

10.6.2 相等的概念 293

10.6.3 分配和释放 295

练习 296

引文注记 298

第五部分 其他范型 300

第11章 逻辑式程序设计 300

11.1 用关系做计算 301

11.1.1 关系 301

11.1.2 规则和事实 301

11.1.3 查询 302

11.2 Prolog初步 304

11.2.1 项 304

11.2.2 与Prolog交互 305

11.2.3 存在性查询 305

11.2.4 全称性的事实和规则 306

11.2.5 否定作为失败 307

11.2.6 合一 308

11.2.7 算术 309

11.3 Prolog的数据结构 309

11.3.1 Prolog中的表 309

11.3.2 项作为数据 310

11.4 程序设计技术 312

11.4.1 猜测和验证 312

11.4.2 用变量作为项里的占位符 314

11.4.3 差表 317

11.5 Prolog的控制 318

11.5.1 合一和替换 319

11.5.2 将规则应用于目标 320

11.5.3 Prolog搜索树 322

11.5.4 目标的顺序将改变解 323

11.5.5 规则顺序影响对解的搜索 324

11.5.6 出现检查问题 326

11.6 割 326

11.6.1 割作为第一个条件 327

11.6.2 割的作用 328

11.6.3 应用割的程序设计 329

11.6.4 否定等同于失败 332

练习 333

引文注记 334

第12章 并发程序设计导引 336

12.1 硬件的并行性 336

12.1.1 输入/输出的并行执行 336

12.1.2 中断和分时 337

12.1.3 多处理器组织结构 338

12.1.4 反应式系统 338

12.2 流:隐式的同步 338

12.2.1 进程网络 339

12.2.2 管道实例 339

12.3 作为交错的并发性 340

12.3.1 线程的交错 341

12.3.2 Ada中的并发作业 341

12.4 进程的活性性质 343

12.4.1 资源共享限制并发性 343

12.4.2 哲学家就餐问题 343

12.4.3 死锁:无法继续 344

12.4.4 活锁:没有进程能够取得进展 344

12.4.5 公平性 344

12.4.6 避免死锁的发生 345

12.5 共享数据的安全访问 345

12.5.1 “非确定”的进程 345

12.5.2 临界区和互斥 346

12.5.3 可串行化与安全性 347

12.6 Ada中的并发性 348

12.6.1 握手式同步 348

12.6.2 同步通信 349

12.6.3 有选择的接收 352

12.7 共享变量的同步访问 353

12.7.1 对缓冲区的直接访问 353

12.7.2 信号量:互斥 355

练习 359

引文注记 362

第六部分 语言的描述 366

第13章 语义方法 366

13.1 综合属性 368

13.1.1 求值顺序 369

13.1.2 总结 369

13.2 属性文法 370

13.3 自然语义 372

13.3.1 一个计算器 372

13.3.2 环境为名字约束值 373

13.3.3 let约束 373

13.3.4 基于Prolog的实现 375

13.4 指称语义 376

13.5 一个Scheme计算器 377

13.6 词法作用域中的lambda表达式 378

13.6.1 lambda表达式的自然语义 379

13.6.2 环境的一种实现 380

13.7 一个解释器 381

13.7.1 常量 381

13.7.2 加引号项 381

13.7.3 变量 382

13.7.4 条件表达式 382

13.7.5 let表达式 382

13.7.6 lambda表达式 383

13.7.7 函数应用 384

13.7.8 初始化环境 384

13.7.9 解释器的使用 385

13.8 一个扩充:递归函数 386

13.8.1 作为值的递归函数 387

13.8.2 对解释器的修改 387

练习 388

引文注记 389

第14章 静态类型和Lambda演算 390

14.1 纯lambda演算中的相等 391

14.1.1 语法约定 392

14.1.2 自由变量和约束变量 392

14.1.3 替换 393

14.1.4 beta-相等 394

14.2 再论替换 395

14.3 纯lambda项的计算 396

14.3.1 归约 397

14.3.2 不终止的归约 398

14.3.3 Church-Rosser定理 398

14.3.4 计算规则 399

14.4 作为lambda项的程序设计结构 400

14.4.1 一个应用lambda演算 400

14.4.2 Curry化 401

14.4.3 常量的归约规则 401

14.4.4 语言MLO 402

14.4.5 不动点算子 403

14.5 带类型的lambda演算 404

14.6 多态类型 406

14.6.1 取自标准ML的例子 406

14.6.2 显式的多态性 407

14.6.3 单态与多态 408

14.6.4 Core-XML的类型规则 409

练习 411

引文注记 412

第15章 语言概览 414

15.1 Pascal:一种教学语言 414

15.1.1 Pascal的程序结构 415

15.1.2 声明 415

15.1.3 类型 416

15.1.4 表达式 416

15.1.5 语句 416

15.2 C:系统程序设计 417

15.2.1 C语言程序结构 417

15.2.2 C的函数 418

15.2.3 C的变量声明 419

15.2.4 表达式 419

15.2.5 C的控制流 420

15.2.6 指针和数组 420

15.2.7 头文件 421

15.2.8 标准输入/输出 422

15.3 C++:多种程序设计风格 422

15.3.1 C++中的类 422

15.3.2 C++的继承 424

15.4 Smalltalk语言 424

15.4.1 表达式 426

15.4.2 类和实例方法 426

15.4.3 系统类 427

15.5 Standard ML 428

15.5.1 与ML解释器交互 428

15.5.2 基于模式匹配的函数定义 430

15.5.3 数据类型 430

15.5.4 异常 430

15.6 Scheme:一种Lisp方言 431

15.6.1 基本结构 432

15.6.2 表操作 433

15.7 Prolog 434

15.7.1 项 435

15.7.2 与Prolog交互 436

15.7.3 规则 436

15.7.4 查询 436

15.7.5 算术 436

15.7.6 作为数据的项 437

参考文献 438

索引 450