C语言编写程序的步骤:输入10个数,找出两个相差为9的数,再在剩余的8个数中找出相差为7的数,求有多少种方法?

C语言程序设计:现代方法:第2版(被誉为”近10年来最好的一部C语言著作”) - 互动出版网
时至今日, C语言仍然是计算机领域的通用语言之一,但今天的 C语言已经和最初的时候大不相同了。本书最主要的一个目的就是通过一种“现代方法”来介绍 C语言,书中强调标准 C,强调软件工程,不再强调“手工优化”。这一版中紧密结合了 C99标准,并与 C89标准进行对照,补充了 C99中的最新特性。本书分为 C语言的基础特性、 C语言的高级特性、 C语言标准库和参考资料 4个部分。每章末尾都有一个“问与答”小节给出一系列与该章内容相关的问题及答案,此外还包含适量的习题。本书是为大学本科阶段的 C语言课程编写的教材,同时也非常适合作为其他课程的辅助用书。
第1章 C语言概述 11.1 C语言的历史 11.1.1 起源 11.1.2 标准化 11.1.3 基于C的语言 21.2 C语言的优缺点 31.2.1 C语言的优点 31.2.2 C语言的缺点 31.2.3 高效地使用C语言 4问与答 5第2章 C语言基本概念 72.1 编写一个简单的C程序 7程序 显示双关语 72.1.1 编译和链接 82.1.2 集成开发环境 82.2 简单程序的一般形式 92.2.1 指令 92.2.2 函数 92.2.3 语句 102.2.4 显示字符串 102.3 注释 112.4 变量和赋值 122.4.1 类型 122.4.2 声明 132.4.3 赋值 132.4.4 显示变量的值 14程序 计算箱子的空间重量 142.4.5 初始化 152.4.6 显示表达式的值 162.5 读入输入 16程序 计算箱子的空间重量(改进版) 162.6 定义常量的名字 17程序 华氏温度转换为摄氏温度 172.7 标识符 182.8 C程序的书写规范 19问与答 21练习题 23编程题 24第3章 格式化输入/输出 263.1 printf函数 263.1.1 转换说明 27程序 用printf函数格式化数 283.1.2 转义序列 283.2 scanf函数 293.2.1 scanf函数的工作方法 303.2.2 格式串中的普通字符 313.2.3 易混淆的printf函数和scanf函数 32程序 分数相加 32问与答 33练习题 34编程题 35第4章 表达式 364.1 算术运算符 36程序 计算通用产品代码的校验位 384.2 赋值运算符 394.2.1 简单赋值 404.2.2 左值 414.2.3 复合赋值 414.3 自增运算符和自减运算符 424.4 表达式求值 434.5 表达式语句 45问与答 45练习题 47编程题 49第5章 选择语句 505.1 逻辑表达式 505.1.1 关系运算符 505.1.2 判等运算符 515.1.3 逻辑运算符 515.2 if语句 525.2.1 复合语句 535.2.2 else子句 535.2.3 级联式if语句 54程序 计算股票经纪人的佣金 555.2.4 “悬空else”的问题 565.2.5 条件表达式 575.2.6 C89中的布尔值 585.2.7 C99中的布尔值
585.3 switch语句 59程序 显示法定格式的日期 61问与答 62练习题 65编程题 67第6章 循环 696.1 while语句 69程序 显示平方表 71程序 数列求和 716.2 do语句 72程序 计算整数的位数 736.3 for语句 736.3.1 for语句的惯用法 746.3.2 在for语句中省略表达式 756.3.3 C99中的for语句
756.3.4 逗号运算符 76程序 显示平方表(改进版) 776.4 退出循环 786.4.1 break语句 786.4.2 continue语句 786.4.3 goto语句 79程序 账簿结算 806.5 空语句 81问与答 83练习题 84编程题 85第7章 基本类型 887.1 整数类型 887.1.1 C99中的整数类型
907.1.2 整数常量 907.1.3 C99中的整数常量
917.1.4 整数溢出 917.1.5 读/写整数 91程序 数列求和(改进版) 927.2 浮点类型 937.2.1 浮点常量 947.2.2 读/写浮点数 947.3 字符类型 947.3.1 字符操作 957.3.2 有符号字符和无符号字符 957.3.3 算术类型 967.3.4 转义序列 967.3.5 字符处理函数 977.3.6 用scanf和printf读/写字符 987.3.7 用getchar和putchar读/写字符 98程序 确定消息的长度 997.4 类型转换 1007.4.1 常用算术转换 1017.4.2 赋值过程中的转换 1027.4.3 C99中的隐式转换
1037.4.4 强制类型转换 1037.5 类型定义 1057.5.1 类型定义的优点 1057.5.2 类型定义和可移植性 1057.6 sizeof运算符 106问与答 107练习题 109编程题 110第8章 数组 1138.1 一维数组 1138.1.1 数组下标 113程序 数列反向 1158.1.2 数组初始化 1158.1.3
指定初始化式
116程序 检查数中重复出现的数字 1168.1.4 对数组使用sizeof运算符 117程序 计算利息 1188.2 多维数组 1198.2.1 多维数组初始化 1208.2.2 常量数组 121程序 发牌 1218.3 C99中的变长数组
122问与答 123练习题 124编程题 125第9章 函数 1299.1 函数的定义和调用 129程序 计算平均值 129程序 显示倒计数 130程序 显示双关语(改进版) 1319.1.1 函数定义 1329.1.2 函数调用 133程序 判定素数 1349.2 函数声明 1359.3 实际参数 1369.3.1 实际参数的转换 1379.3.2 数组型实际参数 1389.3.3 变长数组形式参数
1409.3.4 在数组参数声明中使用static
1419.3.5 复合字面量
1419.4 return语句 1429.5 程序终止 1439.6 递归 144程序 快速排序 146问与答 147练习题 150编程题 153第10章 程序结构 15510.1 局部变量 15510.1.1 静态局部变量 15610.1.2 形式参数 15610.2 外部变量 15610.2.1 示例:用外部变量实现栈 15610.2.2 外部变量的利与弊 157程序  猜数 15810.3 程序块 16110.4 作用域 16210.5 构建C程序 163程序 给一手牌分类 163问与答 169练习题 169编程题 170第11章 指针 17211.1 指针变量 17211.2 取地址运算符和间接寻址运算符 17311.2.1 取地址运算符 17311.2.2 间接寻址运算符 17411.3 指针赋值 17411.4 指针作为参数 176程序 找出数组中的最大元素和最小元素 17711.5 指针作为返回值 179问与答 180练习题 181编程题 182第12章 指针和数组 18412.1 指针的算术运算 18412.1.1 指针加上整数 18512.1.2 指针减去整数 18512.1.3 两个指针相减 18612.1.4 指针比较 18612.1.5 指向复合常量的指针
18612.2 指针用于数组处理 18612.3 用数组名作为指针 188程序  数列反向(改进版) 18912.3.1 数组型实际参数(改进版) 18912.3.2 用指针作为数组名 19112.4 指针和多维数组 19112.4.1 处理多维数组的元素 19112.4.2 处理多维数组的行 19212.4.3 处理多维数组的列 19212.4.4 用多维数组名作为指针 19212.5 C99中的指针和变长数组
193问与答 194练习题 195编程题 197第13章 字符串 19813.1 字符串字面量 19813.1.1 字符串字面量中的转义序列 19813.1.2 延续字符串字面量 19913.1.3 如何存储字符串字面量 19913.1.4 字符串字面量的操作 20013.1.5 字符串字面量与字符常量 20013.2 字符串变量 20013.2.1 初始化字符串变量 20113.2.2 字符数组与字符指针 20213.3 字符串的读和写 20313.3.1 用printf函数和puts函数写字符串 20313.3.2 用scanf函数和gets函数读字符串 20313.3.3 逐个字符读字符串 20413.4 访问字符串中的字符 20513.5 使用C语言的字符串库 20613.5.1 strcpy函数 20713.5.2 strlen函数 20813.5.3 strcat函数 20813.5.4 strcmp函数 209程序  显示一个月的提醒列表 20913.6 字符串惯用法 21113.6.1 搜索字符串的结尾 21113.6.2 复制字符串 21313.7 字符串数组 214程序  核对行星的名字 217问与答 218练习题 220编程题 222第14章 预处理器 22514.1 预处理器的工作原理 22514.2 预处理指令 22714.3 宏定义 22714.3.1 简单的宏 22714.3.2 带参数的宏 22914.3.3 #运算符 23114.3.4 ##运算符 23114.3.5 宏的通用属性 23214.3.6 宏定义中的圆括号 23314.3.7 创建较长的宏 23314.3.8 预定义宏 23414.3.9 C99中新增的预定义宏
23514.3.10 空的宏参数
23614.3.11 参数个数可变的宏
23614.3.12 __func__标识符
23714.4 条件编译 23714.4.1 #if指令和#endif指令 23814.4.2 defined运算符 23814.4.3 #ifdef指令和#ifndef指令 23914.4.4 #elif指令和#else指令 23914.4.5 使用条件编译 24014.5 其他指令 24014.5.1 #error指令 24014.5.2 #line指令 24114.5.3 #pragma指令 24214.5.4 _Pragma运算符
242问与答 243练习题 245第15章 编写大型程序 24815.1 源文件 24815.2 头文件 24915.2.1 #include指令 24915.2.2 共享宏定义和类型定义 25015.2.3 共享函数原型 25115.2.4 共享变量声明 25215.2.5 嵌套包含 25315.2.6 保护头文件 25315.2.7 头文件中的#error指令 25415.3 把程序划分成多个文件 254程序 文本格式化 25515.4 构建多文件程序 26015.4.1 makefile 26015.4.2 链接期间的错误 26215.4.3 重新构建程序 26215.4.4 在程序外定义宏 264问与答 264练习题 265编程题 266第16章 结构、联合和枚举 26716.1 结构变量 26716.1.1 结构变量的声明 26716.1.2 结构变量的初始化 26916.1.3 指定初始化
26916.1.4 对结构的操作 27016.2 结构类型 27016.2.1 结构标记的声明 27116.2.2 结构类型的定义 27216.2.3 结构作为参数和返回值 27216.2.4 复合字面量
27316.3 嵌套的数组和结构 27416.3.1 嵌套的结构 27416.3.2 结构数组 27416.3.3 结构数组的初始化 275程序  维护零件数据库 27516.4 联合 28116.4.1 用联合来节省空间 28216.4.2 用联合来构造混合的数据结构 28416.4.3 为联合添加“标记字段” 28416.5 枚举 28516.5.1 枚举标记和类型名 28616.5.2 枚举作为整数 28616.5.3 用枚举声明“标记字段” 286问与答 287练习题 289编程题 293第17章 指针的高级应用 29417.1 动态存储分配 29417.1.1 内存分配函数 29417.1.2 空指针 29517.2 动态分配字符串 29617.2.1 使用malloc函数为字符串分配内存 29617.2.2 在字符串函数中使用动态存储分配 29617.2.3 动态分配字符串的数组 297程序  显示一个月的提醒列表(改进版) 29717.3 动态分配数组 29917.3.1 使用malloc函数为数组分配存储空间 29917.3.2 calloc函数 30017.3.3 realloc函数 30017.4 释放存储空间 30117.4.1 free函数 30117.4.2 “悬空指针”问题 30117.5 链表 30217.5.1 声明结点类型 30217.5.2 创建结点 30317.5.3 -)运算符 30317.5.4 在链表的开始处插入结点 30417.5.5 搜索链表 30617.5.6 从链表中删除结点 30717.5.7 有序链表 308程序  维护零件数据库(改进版) 30917.6 指向指针的指针 31317.7 指向函数的指针 31417.7.1 函数指针作为参数 31417.7.2 qsort函数 31417.7.3 函数指针的其他用途 316程序  列三角函数表 31717.8 受限指针
31817.9 灵活数组成员
319问与答 320练习题 323编程题 325第18章 声明 32718.1 声明的语法 32718.2 存储类型 32818.2.1 变量的性质 32818.2.2 auto存储类型 32918.2.3 static存储类型 32918.2.4 extern存储类型 33018.2.5 register存储类型 33118.2.6 函数的存储类型 33218.2.7 小结 33218.3 类型限定符 33318.4 声明符 33418.4.1 解释复杂声明 33518.4.2 使用类型定义来简化声明 33618.5 初始化式 33618.6 内联函数
33718.6.1 内联定义 33818.6.2 对内联函数的限制 33918.6.3 在GCC中使用内联函数 339问与答 339练习题 342第19章 程序设计 34519.1 模块 34519.1.1 内聚性与耦合性 34719.1.2 模块的类型 34719.2 信息隐藏 34719.3 抽象数据类型 35019.3.1 封装 35119.3.2 不完整类型 35119.4 栈抽象数据类型 35219.4.1 为栈抽象数据类型定义接口 35219.4.2 用定长数组实现栈抽象数据类型 35319.4.3 改变栈抽象数据类型中数据项的类型 35419.4.4 用动态数组实现栈抽象数据类型 35519.4.5 用链表实现栈抽象数据类型 35719.5 抽象数据类型的设计问题 35919.5.1 命名惯例 35919.5.2 错误处理 35919.5.3 通用抽象数据类型 35919.5.4 新语言中的抽象数据类型 360问与答 360练习题 361编程题 362第20章 底层程序设计 36320.1 位运算符 36320.1.1 移位运算符 36320.1.2 按位求反运算符、按位与运算符、按位异或运算符和按位或运算符 36420.1.3 用位运算符访问位 36520.1.4 用位运算符访问位域 366程序  XOR加密 36620.2 结构中的位域 36720.3 其他底层技术 36920.3.1 定义依赖机器的类型 36920.3.2 用联合提供数据的多个视角 37020.3.3 将指针作为地址使用 371程序  查看内存单元 37120.3.4 volatile类型限定符 373问与答 374练习题 374编程题 376第21章 标准库 37721.1 标准库的使用 37721.1.1 对标准库中所用名字的限制 37721.1.2 使用宏隐藏的函数 37821.2 C89标准库概述 37821.3 C99标准库更新 38021.4 (stddef.h):常用定义 38121.5 (stdbool.h):布尔类型和值
381问与答 382练习题 382编程题 383第22章 输入/输出 38422.1 流 38422.1.1 文件指针 38522.1.2 标准流和重定向 38522.1.3 文本文件与二进制文件 38522.2 文件操作 38622.2.1 打开文件 38622.2.2 模式 38722.2.3 关闭文件 38822.2.4 为打开的流附加文件 38922.2.5 从命令行获取文件名 389程序  检查文件是否可以打开 38922.2.6 临时文件 39022.2.7 文件缓冲 39122.2.8 其他文件操作 39222.3 格式化的输入/输出 39322.3.1 …printf函数 39322.3.2 …printf转换说明 39322.3.3 C99对…printf转换说明的修改
39522.3.4 …printf转换说明示例 39622.3.5 …scanf函数 39822.3.6 …scanf格式串 39822.3.7 …scanf转换说明 39822.3.8 C99对...scanf转换说明的改变
40022.3.9 scanf示例 40022.3.10 检测文件末尾和错误条件 40122.4 字符的输入/输出 40322.4.1 输出函数 40322.4.2 输入函数 403程序  复制文件 40422.5 行的输入/输出 40522.5.1 输出函数 40522.5.2 输入函数 40622.6 块的输入/输出 40622.7 文件定位 407程序  修改零件记录文件 40922.8 字符串的输入/输出 40922.8.1 输出函数 41022.8.2 输入函数 410问与答 411练习题 414编程题 416第23章 库对数值和字符数据的支持 41923.1 (float.h):浮点类型的特性 41923.2 (limits.h):整数类型的大小 42123.3 (math.h):数学计算(C89) 42223.3.1 错误 42223.3.2 三角函数 42223.3.3 双曲函数 42323.3.4 指数函数和对数函数 42323.3.5 幂函数 42423.3.6 就近取整函数、绝对值函数和取余函数 42423.4 (math.h):数学计算(C99)
42523.4.1 IEEE浮点标准 42523.4.2 类型 42623.4.3 宏 42623.4.4 错误 42623.4.5 函数 42723.4.6 分类宏 42723.4.7 三角函数 42823.4.8 双曲函数 42823.4.9 指数函数和对数函数 42923.4.10 幂函数和绝对值函数 43023.4.11 误差函数和伽玛函数 43023.4.12 就近取整函数 43123.4.13 取余函数 43223.4.14 操作函数 43223.4.15 最大值函数、最小值函数和正差函数 43323.4.16 浮点乘加 43323.4.17 比较宏 43423.5 (ctype.h):字符处理 43423.5.1 字符分类函数 435程序  测试字符分类函数 43623.5.2 字符大小写映射函数 437程序  测试大小写映射函数 43723.6 (string.h):字符串处理 43723.6.1 复制函数 43723.6.2 拼接函数 43823.6.3 比较函数 43923.6.4 搜索函数 44023.6.5 其他函数 442问与答 442练习题 443编程题 444第24章 错误处理 44624.1 (assert.h):诊断 44624.2 (errno.h):错误 44724.3 (signal.h):信号处理 44824.3.1 信号宏 44924.3.2 signal函数 44924.3.3 预定义的信号处理函数 45024.3.4 raise函数 450程序  测试信号 45124.4 (setjmp.h):非局部跳转 452程序  测试setjmp和longjmp 452问与答 453练习题 454第25章 国际化特性 45625.1 (locale.h):本地化 45625.1.1 类别 45625.1.2 setlocale函数 45725.1.3 localeconv函数 45825.2 多字节字符和宽字符 46125.2.1 多字节字符 46125.2.2 宽字符 46125.2.3 统一码和通用字符集 46225.2.4 统一码编码 46225.2.5 多字节/宽字符转换函数 46325.2.6 多字节/宽字符串转换函数 46525.3 双字符和三字符 46525.3.1 三字符 46525.3.2 双字符 46625.3.3 (iso646.h):拼写替换 46725.4 通用字符名
46725.5 (wchar.h):扩展的多字节和宽字符实用工具
46725.5.1 流倾向 46825.5.2 格式化宽字符输入/输出函数 46825.5.3 宽字符输入/输出函数 47025.5.4 通用的宽字符串实用工具 47125.5.5 宽字符时间转换函数 47425.5.6 扩展的多字节/宽字符转换实用工具 47425.6 (wctype.h):宽字符分类和映射实用工具
47725.6.1 宽字符分类函数 47725.6.2 可扩展的宽字符分类函数 47825.6.3 宽字符大小写映射函数 47825.6.4 可扩展的宽字符大小写映射函数 478问与答 479练习题 479编程题 480第26章 其他库函数 48226.1 (stdarg.h):可变参数 48226.1.1 调用带有可变参数列表的函数 48326.1.2 v…printf函数 48426.1.3 v…scanf函数
48526.2 (stdlib.h):通用的实用工具 48526.2.1 数值转换函数 485程序  测试数值转换函数 48626.2.2 伪随机序列生成函数 488程序  测试伪随机序列生成函数 48826.2.3 与环境的通信 48926.2.4 搜索和排序实用工具 490程序  确定航空里程 49126.2.5 整数算术运算函数 49226.3 (time.h):日期和时间 49226.3.1 时间处理函数 49326.3.2 时间转换函数 495程序  显示日期和时间 498问与答 500练习题 501编程题 502第27章 C99对数学计算的新增支持 50327.1 (stdint.h):整数类型
50327.1.1 (stdint.h)类型 50327.1.2 对指定宽度整数类型的限制 50427.1.3 对其他整数类型的限制 50527.1.4 用于整数常量的宏 50527.2 (inttypes.h):整数类型的格式转换
50627.2.1 用于格式说明符的宏 50627.2.2 用于最大宽度整数类型的函数 50727.3 复数
50827.3.1 复数的定义 50827.3.2 复数的算术运算 50927.3.3 C99中的复数类型 50927.3.4 复数的运算 51027.3.5 复数类型的转换规则 51027.4 (complex.h):复数算术运算
51127.4.1 (complex.h)宏 51127.4.2 CX_LIMITED_RANGE编译提示 51227.4.3 (complex.h)函数 51227.4.4 三角函数 51227.4.5 双曲函数 51327.4.6 指数函数和对数函数 51427.4.7 幂函数和绝对值函数 51427.4.8 操作函数 514程序  求二次方程的根 51527.5 (tgmath.h):泛型数学
51527.5.1 泛型宏 51627.5.2 调用泛型宏 51727.6 (fenv.h):浮点环境
51827.6.1 浮点状态标志和控制模式 51827.6.2 (fenv.h)宏 51927.6.3 FENV_ACCESS编译提示 51927.6.4 浮点异常函数 52027.6.5 舍入函数 52027.6.6 环境函数 521问与答 521练习题 522编程题 523附录A C语言运算符 524附录B C99与C89的比较 525附录C C89与经典C的比较 529附录D 标准库函数 532附录E ASCII字符集 569参考文献 570索引 573
在计算领域中,把显而易见的转变为有实用价值的,这一过程是“挫折”一词的生动体现。自本书第1版出版以来,基于C的语言大量兴起(其中最杰出的代表是Java和C#),已有的C++和Perl等相关语言也取得了更大的成就。尽管如此,C语言仍然像当年一样流行,仍然悄无声息地掌控着世界上的许多软件。跟1996年一样,C语言仍然是计算机领域里的通用语言。但即便是C语言也必须随着时间而发展。C99标准的发布催生了对本书新版的需求,而且,第1版涉及的DOS和16位处理器也已经趋于过时。本版对内容进行了全面更新,并在其他许多方面进行了改进。本版新增内容下面列出了本版的新特色和所做的改进。完整地覆盖了C89标准和C99标准。本版和第1版最大的差别就在于覆盖了C99标准。我的目标是覆盖C89和C99之间的每一个重要差别,包括C99新增的所有语言特性和库函数。C99中的每一处改变都会清楚地标出来,或者在小节标题中加上“C99”字样,或者在讨论比较简短时在正文的左边空白处用一个专门的图标表示。我这样做有两个目的:一是提醒读者注意C99中的改变,二是让那些对C99不感兴趣或没有C99编译器的读者知道哪些内容可以跳过。C99新增的许多内容可能只有特定的读者会感兴趣,但有些新特性几乎对所有的C程序员都有用。提供了对所有C89和C99库函数的快速参考。第1版中附录D介绍了C89的所有标准库函数,本版的附录D给出了C89和C99的所有库函数。扩展了GCC的内容。自本书第1版出版以来,GCC(最初是GNU C Compiler的简称,现在指GNU Compiler Collection)得到了广泛应用。GCC有很多优点,包括高性能、低成本(不用花钱)以及在众多软硬件平台之间的可移植性等。由于认识到GCC日渐重要,我在本版中介绍了更多与GCC相关的信息,包括如何使用GCC以及常见的GCC错误消息和警告。增加了对抽象数据类型的讨论。在第1版中,第19章重点讨论了C++。这部分内容现在看起来似乎作用不大,因为本书的读者可能已经学过C++、Java或者C#了。在本版中,对C++的介绍替换为讨论如何在C中建立抽象数据类型。扩展了国际化特性的内容。本版第25章更加详尽地讨论了C语言的国际化特性。重点扩展了Unicode字符集及编码。针对CPU和操作系统做了更新。当我编写本书第1版时,许多读者用的还是16位机和DOS操作系统,但现在情况不同了。在本版中,我把讨论的重点放在32位机和64位机上。尽管本版也介绍了Windows和Mac OS操作系统中影响C程序员的方面,但是针对Linux和其他UNIX版本的出现,我们的讨论更侧重于后一个系列的操作系统。更多的练习题和编程题。本书第1版包括311道习题,本版有将近500(准确地说是498)道习题,分为两组:练习题与编程题。练习题和编程题的答案。本书第1版的读者反馈最多的问题就是希望我提供习题的答案。针对读者的这一需求,我将大约三分之一的练习题和编程题的答案放到了网上,见/books/c2。这一特色对于那些没有选修相应大学课程但却需要检验自己工作的读者来说是非常有用的。提供了答案的练习题和编程题都用 图标标记(“W”表示“此题在网站上有答案”)。有密码保护的教师网站。我为本版书建了一个新的教师资源网站(通过knking. com/books/c2访问),给出了其余练习题和编程题的答案以及大部分章节的PowerPoint讲义。教师可以通过与我联系。请使用您学校的邮件地址并给出一个可以访问贵系网站的链接,以便我核实您的身份。此外,我在本版中对全书的文字和解释说明做了改进。这些改变所需的工作量很大,过程很辛苦:每句话都检查过并(在必要的时候)重新写过。尽管本版改动很大,我仍然尽可能多地保持了原有的章节编号。尽管只有一章(最后一章)内容是全新的,但其他许多章都有新增的内容,少数原有章节的顺序也有所变动。本版删去了一个附录(C语言语法),但又新增了一个比较C99和C89的附录。目标本版的目标与第1版一致。清晰易读,并尽可能带有趣味性。对普通读者来说,许多C语言的书籍都过于简洁。甚至某些C语言书籍不是编写得一塌糊涂,就是平淡无趣。我试图对C语言进行清晰、全面的讲解,并用适当的幽默来激发读者的阅读兴趣。适用于广泛的读者群。我假设本书的读者都至少有一点点编程经验,但不需要掌握某种具体的编程语言。我尽量减少“行话”并定义用到的每一个术语。同时,为了鼓励初学者,我还尝试将某些高级内容从基本主题中分离出来。有权威性,但不是学究气十足。为了避免对应该包含哪些内容、不应该包含哪些内容的武断决定,我尽量涵盖了所有C语言的特性和库函数。同时,为了避免给读者造成负担,我还忽略了一些不必要的细节。具备简单易学的组织结构。根据多年教授C语言的经验,我强调循序渐进地展示C语言特性的重要性。针对有一定难度的主题,我采用了螺旋式的介绍方法。也就是说,对于较难的主题先进行简要介绍,然后在后续章节中再进行一次或多次介绍,每次逐渐增加一些细节内容。本书的进度是经过深思熟虑的。每章都按照循序渐进的方式进行组织,并且前后内容由浅入深,相互呼应。对于大多数学生来说,这种循序渐进的方法是最合适的:既能避免产生厌倦,又能防止“信息超载”。深入探讨语言特性。我的目标不是仅描述语言的每个特性,并展示应用该特性的几个简单示例,而是尝试深入讲解每一个特性,并且探讨如何将其应用到实际问题中。强调编码风格。对每位C程序员来说,采用一种统一的编码风格是非常重要的。但是,与指定某种风格相比,我更愿意给出多种编码风格,让读者根据自己的喜好做出选择。因为了解多种编码风格对阅读别人的程序是很有帮助的(程序员经常要花费大量时间阅读别人的程序)。避免依赖任何特定的计算机、编译器或操作系统。C语言可以应用在许多平台上,所以我试图避免编写的程序依赖于任何特定的计算机、编译器或操作系统。所有程序都经过精心设计,可以移植到多种平台上去。用图示的方法阐明关键概念。我在书中加入了尽可能多的图,因为我认为图对于理解C语言的许多方面都是至关重要的。特别地,我尽可能地通过图来显示不同计算阶段的数据状态,以此来动态地展示算法。现代方法到底指的是什么本书最重要的目标之一就是通过一种“现代方法”来介绍C语言。我试图通过以下这些途径来实现这一目标。正确看待C语言。我没有把C语言看成是唯一值得学习的编程语言,而是把它作为众多有用语言中的一种进行介绍。我在书中提到了最适合用C语言编程的应用类型。此外,我还展示了如何扬长避短地使用C语言。强调C语言的标准版本。我尽可能少地关注C89标准之前的C语言,只是零星地提到了经典(K&R)C语言(Brian Kernighan和Dennis Ritchie所著的The C Programming Language第1版中所描述的1978版C语言)。附录C列出了C89和经典C之间的主要差异。揭穿神话。现今的编译器常常与过去的C语言基本假设不一致,我很乐于揭穿C语言的某些神话,并挑战一些存在了很久的C语言信条(例如,指针的算术运算一定比数组下标操作快)。我重新审查了C语言的旧惯例,保留了那些仍然有帮助的惯例。强调软件工程。我把C语言视为一种成熟的软件工程工具,着眼于如何运用C语言来处理大规模程序设计过程中产生的问题。本书强调程序要易读、可维护、可靠且容易移植,尤其重视信息隐藏。推迟介绍C语言的底层特性。虽然这些特性对于那些用C语言编写的系统来说非常有用,但现在它们已经不那么适用了,因为C语言的应用比以前广泛得多。本书没有像其他许多C语言书籍那样把这部分内容放在前面介绍,而是推迟到第20章再进行讲述。不再强调“手工优化”。许多书籍指导读者编写一些技巧性较强的代码,以获得程序效率的些许提高。如今优化的C语言编译器随处可见,这些编程技巧往往已经不必要了;事实上,它们反而会降低程序的运行效率。“问与答”部分每章的末尾都有一个“问与答”部分,汇集了与本章内容相关的问题及其答案。“问与答”部分包括以下一些内容。常见问题。我尽力回答了某些频繁出现在我的课堂里、其他书籍中及与C语言相关的新闻组里的问题。对一些难以理解的问题的进一步讨论和澄清。虽然具有多种编程语言经验的读者会满足于简明扼要的说明和少量的示例,但是缺乏经验的读者却需要更多的内容以帮助理解。非主流的问题。某些问题所引出的并不是所有读者都感兴趣的技术问题。某些对普通读者来说过于超前或深奥的内容。这类问题都用星号(*)进行了标记。好学且有一定编程经验的读者也许希望立刻深入研究这些问题,而另外一些读者则需要在首次阅读时跳过这部分内容。提示:这类问题往往引用后续章节的内容。C语言编译器之间的常见差异。我讨论了某些特定编译器所提供的一些频繁使用的(非标准)特性。“问与答”部分中的某些问题与对应章中的具体内容直接相关,我们用一个专门的图标 来标记这些具体内容,以提示读者有附加信息可用。其他特色除了“问与答”部分,我还加入了许多有用的特色,其中很多都用简单而独特的图标做了标记。警告( )警示读者一些常见的缺陷。C语言以其陷阱多而出名,要记录所有的陷阱非常困难。我试着挑选出了一些最常见或最重要的缺陷供大家参考。交叉引用( 前言)提供一种类似超文本的能力来定位信息。多数引用指向后续章节中的内容,也有一些引用指向先前的内容供读者回顾。惯用法是C语言程序中常见的代码模式。它被标记出来以便于速查参考。可移植性技巧给出了编写不依赖于特定计算机、编译器或操作系统的程序所需的提示。附加说明包含一些严格来讲并不属于C语言的内容,但每位熟练的C程序员都应该知道。(下面的“源代码”给出了附加说明的示例。)附录提供有价值的参考资料信息。程序选择程序示例并不是件轻松的工作。如果程序过于简洁和做作,那么读者将无法体会如何将这些特性应用于现实世界。另一方面,如果程序过于真实,那么它的要点将很容易被忽略在过多的细节中。我采取了折中方案。在首次介绍时,先通过小而简单的示例使概念清晰,然后再逐步建立完整的程序。我没有使用过长的程序,因为根据我个人的经验,教师没有时间介绍这些内容,而学生也不会有耐心去阅读。但是,我并没有忽视编写大规模程序时会出现的问题,相关内容在第15章和第19章中进行了详细的介绍。我克制住了自己重新编写程序以利用C99特性的冲动,因为并不是每个读者都安装了C99编译器或愿意使用C99。但是,在有些程序中我仍然使用了C99的头文件,因为它定义了bool、true和false宏。如果你的编译器不支持,就需要自己定义这些宏。本版的程序有些小的改变。现在main函数的格式在大多数情况下为int main (void) {...}。这一改变既反映了业界的惯例,又能够与C99兼容,C99要求每个函数都有一个显式的返回类型。源
码本书中所有程序的源代码都可以从/books/c2下载 。有关本书的更新、校正和最新消息也可以从这一网站获得。读者本书是为大学本科阶段的C语言课程编写的教材。具有其他高级语言或汇编语言的编程经验会很有帮助,不过这些经验对于会用计算机的读者(我以前的一位编辑称他们为“熟练的初学者”)来说并不是必需的。因为本书内容齐备、自成一体,并且既可用于学习又可作为参考,所以它非常适合作为其他一些课程的辅助读物,如数据结构、编译器设计、操作系统、计算机图形学、嵌入式系统及其他要用C语言进行项目设计的课程。“问与答”部分以及对实际问题的强调,使得本书对于培训班学员和自学C语言的人来说也很有吸引力。组织结构本书分为4个部分。C语言的基本特性。第1章~第10章包含的C语言内容足以帮助读者编写出使用数组和函数的单文件程序。C语言的高级特性。第11章~第20章建立在前面各章内容的基础上,内容有一定的难度,深入介绍了指针、字符串、预处理器、结构、联合、枚举以及C语言的底层特性。此外,第15章和第19章提供了程序设计方面的指导。C语言标准库。第21章~第27章集中介绍C语言库――与编译器相关联的庞大函数集合。其中一部分内容适合讲解,但大部分材料更适合作为参考。参考资料。附录A给出了C语言运算符的完整列表。附录B描述了C99和C89之间的主要差别。附录C讨论了C89和经典C之间的差异。附录D按字母顺序列出了C89和C99标准库中的全部函数,并为每个函数给出了详尽的说明。附录E列出了ASCII字符集。还有一个带注解的参考文献列表为读者指明了其他的信息来源。全面讲授C语言的课程应该按顺序覆盖前20章的内容,并根据需要增加第21章~第27章中的一些内容(其中讨论了文件输入/输出的第22章最为重要)。短期课程可以忽略以下内容而不失连贯性:8.3节(变长数组)、9.6节(递归)、12.4节(指针和多维数组)、14.5节(其他指令)、17.7节(指向函数的指针)、17.8节(受限指针)、17.9节(灵活数组成员)、18.6节(内联函数)、第19章(程序设计)、20.2节(结构中的位域)和20.3节(其他底层技术)。练习题和编程题作为一本教材,拥有多样化的精选习题显然是非常必要的。本版既有练习题(不需要写出完整程序的简短习题)又有编程题(需要编写或修改完整程序的习题)。有些练习题的答案不是显而易见的(有人称其为“刁钻问题”)。因为C语言程序经常包含这类代码的大量案例,所以我认为有必要提供一些这样的练习,并用星号(*)进行了标注。对于有星号的习题一定要小心:要么格外小心,认真考虑,要么干脆绕开它。反馈为了使本书准确,我付出了极大的努力。然而,任何这种篇幅的书籍都不可避免地会有一些错误。如果读者发现了错误,请通过这个电子邮箱与我联系。我也同样期望听到读者的其他反馈,比如,你觉得哪些内容特别有用,哪些内容没什么用,希望添加哪些内容等。致谢首先,我要感谢本书的编辑,Norton出版社的Fred McFarland和Aaron Javsicas。本书的编辑工作最初由Fred负责,随后Aaron加入并付出了极大努力使本书得以完成。同时,还要感谢副主编Kim Yi、文字编辑Mary Kelly、生产经理Roy Tedoff和编辑助理Carly Fraser。以下同事对本版的部分或全部书稿进行了审阅,在此致以诚挚的谢意:Markus Bussmann(多伦多大学)、Jim Clarke(多伦多大学)、Karen Reid(多伦多大学)和Peter Seebach(comp.lang.c.moderated新闻组的主持人)。其中需要特别提到的是Jim和Peter,他们的详细审阅使本版少了许多错误。再次感谢第1版书稿的审稿人(按姓氏字母排序):Susan Anderson-Freed、Manuel E. Bermudez、Lisa J. Brown、Steven C. Cater、Patrick Harrison、Brian Harvey、Henry H. Leitner、Darrell Long、Arthur B. Maccabe、Carolyn Rosner和Patrick Terry。我收到了第1版读者反馈的许多有用的意见,感谢每一位花时间提意见的读者。佐治亚州立大学的学生和同事也向我反馈了不少有价值的意见。Ed Bullwinkel和他的妻子Nancy阅读了手稿的很多内容,在此我也要感谢他们。我还要特别感谢我的系主任Yi Pan,他非常支持我的这项工作。感谢我的妻子Susan Cole一如既往地支持着我。还有我们的猫咪Dennis、Pounce和Tex,在完成本书的过程中,它们一直陪伴着我。有时,Pounce和Tex的争吵使我在深夜写作时仍能保持清醒。最后,我还要感谢已故的Alan J. Perlis 。他的警句出现在本书每一章的开始。20世纪70年代中期我在耶鲁大学求学期间,曾有幸在Alan的指导下进行过短暂的学习。我想如果他知道自己的警句出现在一本C语言书中一定会非常高兴。
“我完全沉浸在阅读的过程中,我迫切地想用这本书作为授课教材。”――Karen Reid,多伦多大学计算机科学系资深讲师
“我将这本书用作工程系新生的教材。它语言简洁,阐述清晰,并且覆盖了C语言的方方面面,非常适用于初学者。“――Maekus Bussmann,多伦多大学机械工业工程系教授
“这是我目前读到过的一本最好的C语言书籍,15年前如果有这本书的话,我大概会少走很多弯路。“ ――互动网读者评论
C语言的输入/输出库是标准库中最大且最重要的部分。由于输入/输出是C语言的高级应用,因此这里将用一整章(本书中最长的一章)来讨论头――输入/输出函数存放的主要地方。从第2章开始,我们已经在使用了,而且已经对printf函数、scanf函数、putchar函数、getchar函数、puts函数以及gets函数的使用有了一定的了解。本章会提供更多有关这6个函数的信息,并介绍一些新的用于文件处理的函数。值得高兴的是,许多新函数和我们已经熟知的函数有着紧密的联系。例如,printf函数就是printf函数的“文件版”。本章的开始将会讨论一些基本问题:流的概念、FILE类型、输入和输出重定向以及文本文件和二进制文件的差异(22.1节)。随后将转入讨论特别为使用文件而设计的函数,包括打开和关闭文件的函数(22.2节)。在讨论完printf函数、scanf函数以及与“格式化”输入/输出相关的函数(22.3节)以后,我们将着眼于读/写非格式化数据的函数。?每次读写一个字符的getc函数、putc函数以及相关的函数(22.4节)。?每次读写一行字符的gets函数、puts函数以及相关的函数(22.5节)。?读/写数据块的fread函数和fwri七e函数(22.6节)。随后,22.7节会说明如何对文件上执行随机的访问操作。最后,22.8节会描述sprintf函数、snpr?intf函数和sscanf函数,它们是printf函数和scan£函数的变体,后两者分别用于写入和读取一个字符串。本章涵盖了中的绝大部分函数,但忽略了其中8个函数。perror函数是这8个函1数中的一个,它与头紧密相关,所以我把它推迟到24.2节讨论头时进行介绍。26.1节涵盖了其余7个函数(vfprintf、vprintf、vsprintf、vsnprintf、vfscanf、vscanf和vsscanf)。这些函数依赖于valist类型,该类型在26.1节介绍。在C89r扣,所有的标准输入/输出函数都属于但C99有所不同,有些输入/输出函数在.头(25.5节)中声明。中的函数用于处理宽字符而不是普通字符,但大多数函数与中的函数紧密相关。中用于读或写数据的函数称为宇节输入/输出函数,而中的类似函数则称为宽字符输入/输出函数。

我要回帖

更多关于 编写程序的步骤 的文章

 

随机推荐