《C语言教程(原书第4版)》前言
《C语言教程(原书第4版)》(《A Book on C: Programming in C (Fourth Edition)》详细介绍了C这种通用的编程语言,既显示了C“简单即是美”的优雅特性,又展现了它“深入底层”的强大功能。本书通过详细探讨许多来自应用领域的交互式运行程序,深入描述了ANSI版本的C语言。本书一步一步地对C语言进行了完整的描述;另外,还提供了许多完整的工作程序。
在适当的时候,我们会讨论传统C和ANSI C的不同之处(传统C仍然被广泛使用)。本书通过大量的例子,对每个重要的语言特性进行阐述。此外,还以表格形式对C的关键信息进行总结,便于读者以后参考。每一章在结束的时候都有总结和练习部分。总结部分对该章所讨论的一些关键概念进行概括,而练习部分则是对正文的论证和延伸。
本书从通用编程语言的角度对C语言进行描述。它可以作为读者学习编程语言的入门课程;也可以作为进一步学习C语言的高级课程;还可以与比较式编程语言、计算语言学、数据结构、数据库系统、分形几何、图形学、数值分析、操作系统、编程方法学以及科学应用程序等课程一起学习。C适用于编写上述领域的应用程序,本书解释了编写这些应用程序所需要的所有特性。本书也可以作为数据结构课程的教材,因为它讨论了枚举类型、联合、自引用等结构以及不规则数组等高级数据结构特性。作为与UNIX或Windows 95/NT相关的操作系统课程,本书探讨了有关文件结构和系统函数的一些知识,使程序员能对原有的系统函数库进行添加,并理解与操作系统相关的底层C代码。对于应用程序和科学应用编程,本书介绍了如何编写示例函数库。本书所提供的工作代码还涉及统计、求方程式的根、排序、文本操纵、文件处理和游戏等内容。
新增的Java内容
在第14章中,我们讨论了C程序员可以很自然和很方便地用Java进行编程的原因。Java是一种适合在Internet上运行的语言,它借鉴了C和C++的许多思想,并按照一种独立于机器和系统的方式运行。这使它特别适合在Internet上运行,例如编写由浏览器所使用的在Web页面上运行的Applet。由于Java是对C和C++的扩展,因此C程序员很乐意学习Java语言。
完整的ANSI C语言
计算机专业人员可以在本书中找到C语言的所有主题,包括枚举类型、列表处理和操作系统接口。第1章对这门语言进行了总览性描述。在阅读了这一章之后,有编程基础的读者就可以编写C代码了。由于本书各章的内容相对独立,因此编程基础较扎实的读者可以根据需要阅读特定的章节。第11章详细讨论了C语言与操作系统的连接,这些内容可以帮助系统程序员在MS-DOS和UNIX下用C进行编程。
交互性环境
本书充分利用了现代计算机的交互性环境。我们在本书中始终鼓励读者进行试验。键盘和屏幕是常规的输入/输出设备,但本书也对其他的输入输出途径进行了解释。因此,本书既适用于小型的家用和商用计算机用户,也适用于大型交互性系统的用户。我们假定读者可以使用交互性的ANSI C系统。在编写本书期间,我们使用了一些不同的C系统:在IBM兼容的奔腾机器上运行的各种Borland和Microsoft编译器,GNU的gcc编译器,运行于DEC、SGI、Sun等工作站的本地编译器以及运行于San Diego的Cray大型机上的C编译器。
工作代码
我们通过示例程序、解释和语法来描述C语言。本书使用了大量的工作代码,通过许多小而有用的例子对一些重要的概念进行描述。之所以使用小型代码,是为了更容易让读者理解。之所以说这些小例子非常有用,是因为总是可以将程序分解为层次式的基本构件。本书所描述的程序和函数可以在实际的系统中使用。作者所信奉的哲学是读者应该不断进行试验,并从中享受乐趣。
分析
本书采用“分析”段落,对所提供的许多程序和函数进行详细的分析。这种分析方法是作者最初于1984年创造的,这是一种独一无二的教学方法,用于说明工作代码的一些关键特性。这种分析方法类似于对代码进行结构化的走查,目的是向读者解释新接触的编程元素以及工作代码中所出现的惯用法。
灵活的组织
本书的组织形式非常灵活。第1章分为两个部分:第一部分解释了实现交互性输入/输出所需要的关键编程技巧,这些内容是必须理解的;第1章的第二部分是对整个语言的总览性介绍。对于那些已经熟悉其他类似编程语言的读者,在阅读了这些内容之后,很容易了解C语言的概貌。对于初学编程的读者,第二部分可以推迟阅读。警告:初学者应该推迟第1章第二部分的学习。
第2章在词法层次上对C语法进行描述,讨论了C的语法规则。该章选择性地使用了一些语法规则来显示C语言的结构。对于第2章所描述的Backus-Naur-Form(BNF巴克斯-诺尔形式)记法,读者可以选择完全将其略过,这并不会对学习的连续性造成任何影响。本书使用了BNF风格的语法描述,使读者可以了解标准的编程语言描述形式。另外,本书通过示例程序和解释对语言的成分进行详细的描述。
参考作用
本书可以作为C语言的参考手册。本书提供了许多表格,简洁地总结了C语言的一些关键概念。附录A描述了完整的ANSI C标准函数库以及相关的头文件。附录A的内容是根据标准头文件组织的,例如ctype.h、stdio.h和string.h等。在适当的时候,我们会提供示例代码说明某个特定结构或特定函数的用法。
在附录B中,我们提供了C语言的完整语法。在附录C中,我们讨论了ANSI C和传统C的一些主要区别。
完整的语法特性
第3章到第10章对C语言的各个特性进行了完整的介绍。其中包括了许多高级话题,读者在第一遍阅读时可以将它们省略,这样并不会对接下来的学习产生影响。例如,读者在第一遍阅读本书时可以忽略枚举类型的介绍。本书强调了像字长和浮点表示形式等依赖于机器的特性,但初学者可以忽略这些细节。
预处理器
第8章完整地讲述了预处理器,它用于对C语言的功能和概念进行扩展。宏可以用于生成内联代码,可以代替函数调用。使用宏可以减少程序的执行时间。该章对预处理器进行了详细的描述,包括ANSI C委员会所增加的一些新特性。在传统C中,预处理器在不同的编译器中可能具有显著的差别。在ANSI C中,预处理器的功能完全是预先指定的。
递归和列表处理
第5章对递归进行了详细讨论。递归这个概念对于初学者而言常常显得颇为神秘。第8章在讨论快速排序算法时以及第10章在讨论基本的列表处理技巧时再次说明了递归的用法。要完整地理解列表处理技巧,读者需要学习高级编程和数据结构课程。
与操作系统连接
第11章讨论了C语言和操作系统的连接。在该章中,我们解释了如何进行文件处理,并详细介绍了标准函数库中的各个输入/输出函数。我们还解释了如何在C程序中执行系统命令,如何设置文件访问权限以及如何使用环境变量。我们提供了一些例子,说明了性能评估程序、函数库管理工具以及make工具的用法。
高级应用
在第12章中,我们讨论了C语言的一些高级应用。我们讨论了诸如并发进程的创建、叠加进程、进程间通信以及信号等话题,并提供了一些工作代码。另外,我们还讨论了向量和矩阵的动态内存分配,这些知识工程师和科学家会用到。读者可以根据需要选择性地使用这些高级技巧,它们可以作为高级编程实践的基础。本书也可以作为以C为实现语言的高级计算机科学课程的辅导书。
表格、总结和练习
在本书中,我们用许多表格对C语言的一些关键概念进行总结。这些表格可以帮助读者加深对C语言的理解。例如,C具有大量的操作符,并且几乎允许操作符进行各种类型的混合使用。理解这些操作符的优先级和结合性是非常重要的,它有助于理解各种混合表达式的求值顺序。本书中的很多表格就是对各种混合表达式的求值顺序进行分析。作为参考手册,这些表格和代码很容易寻找。
练习部分是对语言的基本元素进行测试,并讨论了一些高级的以及因系统而异的特性。许多练习的目的是为了解决问题,还有些练习则是测试读者对C的语法或语义的理解。有些练习所讨论的主题是对正文的补充,有些读者可能会对它们产生兴趣。本书的练习提供了难易程度各异的问题,适合各个层次的读者。
样张试读:从零开始
http://blog.chinaunix.net/space.php?uid=18942516&do=blog&id=2238200-----------------------------------------
目录:
第0章 从零开始 1
0.1 为什么要用C 1
0.2 ANSI C标准 2
0.3 从C到C++ 3
0.4 从C和C++到Java 3
第1章 C语言概述 4
1.1 编程和预备知识 4
1.2 程序输出 4
1.3 变量、表达式和赋值 7
1.4 使用#define和#include 9
1.5 使用printf()和scanf() 12
1.6 控制流 14
1.7 函数 19
1.8 数组、字符串和指针 24
1.8.1 数组 24
1.8.2 字符串 25
1.8.3 指针 28
1.9 文件 31
1.10 与操作系统有关的内容 35
1.10.1 编写和运行C程序 35
1.10.2 中断程序 36
1.10.3 输入文件尾标志 37
1.10.4 输入和输出的重定向 37
1.11 总结 38
1.12 练习 39
第2章 词法元素、操作符和C系统 45
2.1 字符和词法元素 46
2.2 语法规则 48
2.3 注释 49
2.4 关键字 50
2.5 标识符 50
2.6 常量 51
2.7 字符串常量 52
2.8 操作符和标点符号 53
2.9 操作符的优先级和结合性 53
2.10 增值操作符和减值操作符 55
2.11 赋值操作符 56
2.12 例子:计算2的乘方 57
2.13 C系统 58
2.13.1 预处理器 59
2.13.2 标准函数库 59
2.14 总结 62
2.15 练习 63
第3章 基本数据类型 69
3.1 声明、表达式和赋值 69
3.2 基本数据类型 71
3.3 字符和char数据类型 72
3.4 int数据类型 75
3.5 整数类型short、long和unsigned 76
3.6 浮点类型 77
3.7 typedef的用法 79
3.8 sizeof操作符 79
3.9 使用getchar()和putchar() 80
3.10 数学函数 82
3.10.1 使用abs()和fabs() 84
3.10.2 UNIX和数学函数库 84
3.11 隐式类型转换和强制类型转换 84
3.11.1 整型提升 85
3.11.2 寻常算术转换 85
3.11.3 强制类型转换 86
3.12 十六进制和八进制常量 87
3.13 总结 89
3.14 练习 89
第4章 控制流 96
4.1 关系操作符、相等操作符和逻辑操作符 96
4.2 关系操作符和表达式 97
4.3 相等操作符和表达式 99
4.4 逻辑操作符和表达式 100
4.5 复合语句 103
4.6 表达式和空语句 103
4.7 if和if-else语句 104
4.8 while语句 106
4.9 for语句 108
4.10 例子:布尔变量 110
4.11 逗号操作符 111
4.12 do语句 112
4.13 例子:斐波那契数 113
4.14 goto语句 115
4.15 break和continue语句 116
4.16 switch语句 117
4.17 条件操作符 118
4.18 总结 119
4.19 练习 120
第5章 函数 128
5.1 函数定义 128
5.2 return语句 130
5.3 函数原型 131
5.4 例子:创建乘方表 132
5.5 从编译器的角度观察函数原型 133
5.6 函数定义顺序的另一种风格 134
5.7 函数调用和传值调用 134
5.8 开发大型程序 136
5.9 使用断言 138
5.10 作用域规则 139
5.10.1 平行和嵌套代码块 140
5.10.2 以调试为目的使用代码块 140
5.11 存储类型 141
5.11.1 auto存储类型 141
5.11.2 extern存储类型 141
5.11.3 register存储类型 143
5.11.4 static存储类型 143
5.12 静态外部变量 144
5.13 默认初始化 145
5.14 递归 145
5.15 例子:汉诺塔 149
5.16 总结 152
5.17 练习 153
第6章 数组、指针和字符串 159
6.1 一维数组 159
6.1.1 初始化 160
6.1.2 下标 160
6.2 指针 161
6.3 传引用调用 164
6.4 数组和指针之间的关系 165
6.5 指针运算和元素的大小 166
6.6 数组作为函数的实参 166
6.7 例子:冒泡排序 167
6.8 用calloc()和malloc()进行动态内存分配 168
6.9 例子:归并和归并排序 171
6.10 字符串 175
6.11 标准函数库中的字符串处理函数 177
6.12 多维数组 180
6.12.1 二维数组 180
6.12.2 存储映射函数 180
6.12.3 形式参数声明 181
6.12.4 三维数组 182
6.12.5 初始化 182
6.12.6 使用typedef 183
6.13 指针数组 184
6.14 main()函数的参数 188
6.15 不规则数组 189
6.16 函数作为参数 190
6.17 例子:使用二分法寻找函数的根 192
6.18 函数指针数组 196
6.19 类型限定符const和volatile 199
6.20 总结 200
6.21 练习 202
第7章 位操作符和枚举类型 214
7.1 位操作符和表达式 214
7.1.1 按位求反 215
7.1.2 补码 215
7.1.3 位逻辑操作符 216
7.1.4 左移位和右移位操作符 217
7.2 掩码 218
7.3 软件工具:打印int值的二进制形式 219
7.4 包装和解包 220
7.5 枚举类型 223
7.6 例子:“石头、剪刀、布”游戏 225
7.7 总结 229
7.8 练习 230
第8章 预处理器 235
8.1 #include的使用 235
8.2 使用#define 236
8.3 带参数的宏 237
8.4 stddef.h中的类型定义和宏 239
8.5 例子:用qsort()进行排序 239
8.6 例子:带参数的宏 243
8.7 stdio.h和ctype.h中的宏 246
8.8 条件编译 247
8.9 预定义的宏 249
8.10 “#”和“##”操作符 249
8.11 assert()宏 250
8.12 使用#error和#pragma 250
8.13 行号 251
8.14 对应的函数 251
8.15 例子:快速排序 251
8.16 总结 254
8.17 练习 254
第9章 结构和联合 262
9.1 结构 262
9.2 访问结构成员 264
9.3 操作符的优先级和结合性的总结 267
9.4 在函数中使用结构 268
9.5 结构的初始化 269
9.6 例子:玩扑克牌 269
9.7 联合 273
9.8 位字段 275
9.9 例子:访问位和字节 276
9.10 ADT堆栈 277
9.11 总结 280
9.12 练习 281
第10章 结构和列表处理 288
10.1 自引用的结构 288
10.2 线性链表 289
10.3 链表操作 290
10.4 一些链表处理函数 293
10.4.1 插入 294
10.4.2 删除 295
10.5 堆栈 296
10.6 例子:波兰记法和堆栈求值 298
10.7 队列 303
10.8 二叉树 306
10.8.1 二叉树的遍历 307
10.8.2 创建树 308
10.9 普通的树 309
10.9.1 遍历 311
10.9.2 calloc()的用法以及树的创建 311
10.10 总结 312
10.11 练习 313
第11章 输入/输出和操作系统 318
11.1 输出函数printf() 318
11.2 输入函数scanf() 321
11.3 fprintf()、fscanf()、sprintf()和sscanf()函数 324
11.4 fopen()和fclose()函数 325
11.5 例子:对文件进行空间加倍 327
11.6 使用临时文件和优雅函数 329
11.7 随机访问文件 331
11.8 文件描述符输入/输出 332
11.9 文件访问权限 333
11.10 在C程序内部执行命令 334
11.11 在C程序内部使用管道 335
11.12 环境变量 336
11.13 C编译器 337
11.14 使用性能评估程序 338
11.15 函数库 339
11.16 对C代码进行计时 340
11.17 使用make 343
11.18 使用touch 347
11.19 其他有用的工具 348
11.20 总结 349
11.21 练习 350
第12章 高级应用 358
12.1 用fork()创建并发进程 358
12.2 进程的叠加:exec...()函数族系 360
12.3 使用pipe()实现进程间的通信 362
12.4 信号 363
12.5 例子:哲学家用餐问题 365
12.6 矩阵的动态分配 368
12.6.1 为什么二维数组无法满足要求 368
12.6.2 用指针数组创建矩阵 369
12.6.3 调整下标范围 371
12.6.4 一次分配所有内存 373
12.7 返回状态 374
12.8 总结 377
12.9 练习 378
第13章 从C到C++ 383
13.1 输出 383
13.2 输入 384
13.3 函数 386
13.4 类和抽象数据类型 387
13.5 重载 389
13.6 构造函数和析构函数 390
13.7 面向对象编程和继承 392
13.8 多态 393
13.9 模板 395
13.10 C++的异常 396
13.11 面向对象编程的优点 396
13.12 总结 397
13.13 练习 398
第14章 从C到Java 402
14.1 输出 402
14.2 变量和类型 403
14.3 类和抽象数据类型 404
14.4 重载 406
14.5 类的创建和销毁 406
14.6 面向对象编程和继承 406
14.7 多态和重写方法 407
14.8 Applet 408
14.9 Java的异常 409
14.10 Java和OOP的优势 410
14.11 总结 410
14.12 练习 411
附录A 标准函数库 413
附录B C的语法 441
附录C ANSI C与传统C的比较 446
附录D ASCII字符码 452
附录E 操作符的优先级和结合性 454
阅读(1548) | 评论(0) | 转发(1) |