《国家精品课教材·大学计算机规划教材:C语言大学实用教程(第3版)》是普通高等教育“十一五”国家级规划教材和国家精品课程教材。全书共10章,内容包括:程序设计ABC,数据类型、运算符与表达式,键盘输入与屏幕输出,程序的控制结构,函数,数组,指针,结构体与共用体,文件操作,C程序设计常见错误及解决方案等。
《国家精品课教材·大学计算机规划教材:C语言大学实用教程(第3版)》注重教材的可读性和可用性,每章开头有内容关键词和难点提示;每章结尾安排本章小结,给出了该章常见编程错误提示;典型例题一题多解,由浅入深,强化知识点、算法、编程方法与技巧;还将程序测试、程序调试与排错、软件的健壮性和代码风格、结构化与模块化程序设计方法等软件工程知识融入其中;配套教材《C语言大学实用教程学习指导(第3版)》包括习题解答、上机实验指导、案例分析三部分,案例分析中给出了错误案例与趣味经典实例分析;为任课教师免费提供电子课件及全部例题和习题源代码。
致本书读者
在Java,C#等充满面向对象、快速开发和稳定可靠这样溢美之词的语言大行其道的今天,还如此耗费心力写一本关于已经落伍了的C语言的书,着实让人匪夷所思。虽然C语言在教育界还举足轻重,在系统开发领域依然健硕,铁杆支持者遍布世界各地,但是C语言的书籍种类繁多,早已被写到“滥”的地步了。这本书的存在还会有价值吗?
万物皆将成为时间的灰烬,其价值体现在燃烧时发出的光热。
C语言的重要性将会在第1章中阐述。在计算机教育方面,C语言是为数不多的与国外保持内容同步的课程之一,这大概也是因为C语言自身多年以来没有什么变化吧。但在教学深度上,尤其在把C语言从应试课程转变为实践工具方面,国内无论教材还是课程建设方面都跟不上时代发展的步伐。
计算机科学日进千里,很多旧的思想、方法都被打破,不能与时俱进的语言必遭淘汰。可C语言却能奇迹般地以不动如山之姿态笑傲天下,论剑江湖,这套以静制动的本领,来自于C语言的灵活。
灵活,使C语言的用法可以产生诸般变化。每种变化都有其利与害,趋利避害是根本。但何为利,何为害呢?这是程序设计科学研究的主题之一。随着时间的推移,判断的标准总在变化。比如20世纪90年代以前,性能一直是最重要的,所有的程序设计方法都趋向于提高性能。当硬件越来越快、越来越便宜,软件越来越复杂、越来越昂贵,设计程序时考虑更多的是如何降低开发成本和难度,不惜以牺牲性能为代价。当网络成为技术推动力时,安全问题又成为重中之重。
无论思潮怎样变化,C语言总能有一套行之有效的方法来应对。这些方法完全构建在对C语言基本语法的应用之上,丝毫影响不到它固有的体系。一些适时的方法被制定为规则,另一些落后的方法则被划为禁手。如果C语言的教科书还只以讲述语法为主,而忽略在新形势下的新方法、新规则和新思想的传授,就真的是没有价值了。
此书要做有价值的书,要让读这本书的人真正学会C语言。那么,达到什么程度算是“学会”了C语言呢?这倒是一个很有意思的问题。
本书作者中有一人,自称一生三次学会了C语言。
第一次是大一,看到C语言成绩后,不禁自封“C语言王子”。
待到大二,偶遇一个机会,用C语言开发一个真实的软件,才知道自己“卷上谈兵”的本领实在太小,实在与会用C语言的目标相去甚远。编了大小几个项目,上万行代码,自觉对C语言的掌握已炉火纯青,此为第二次学会。
待回眸品评这些项目,发现除了几副好皮囊能取悦用户之外,无论程序结构、可读性、可维护性还是稳定性都一团糟。年轻程序员的良心大受谴责,终于认识到,写好程序绝不是懂语法、会调用函数那么简单。又经历练,其间苦学软件工程、面向对象等理论,打造出第一个让自己由衷满意的程序,于是长出一口气,叹曰:“C,我终于会用了!”。
这条路走得着实辛苦,但也确实滋味无穷,乐在其中。留校任教后,他很快获得了讲C语言课的机会。欣然领命,直欲把经年积累一并爆发,送与学生。前辈高人指点,选择了Kernighan与Ritchie所撰的圣经《C Programming Language》为教材。早闻此书,初见其形;边教边品,仰天长叹:“原来C语言若此,吾不曾会矣!”
总结往事,环顾业界,何谓“学会”?这是一个没有答案的提问。学完语法规则只是读完了小学,识字不少,还会造句,但还写不出大篇的漂亮文章。若要进步,就非要在算法和结构设计两方面努力了。但这两者实非一蹴而就,大学四年也只能学到一些条条框框,就像高中毕业尽管作文无数,能力却仅止于八股应试而已。若要写出“惊天地、泣鬼神”之程序,还必须广泛实践,多方积累。学无止境啊!
行文至此,终于完成了这本自认还有价值的书。目前的计算机图书市场异常火爆,“经典与滥竽齐飞,赞美共炒作一色”。我们不知道此书能发出多少光热,也不知道有多少人能见到这份光、感到这点热,只知道它也会成为时间的灰烬,而且盼望这一天越早到来越好。因为,此书观点被大量否定之时,必是IT再次飞跃之日。
编著者
于哈尔滨工业大学计算机科学与技术学院
第1章 程序设计ABC
1.1 计算机与人
1.2 计算机与程序设计语言
1.3 程序设计语言的故事
1.4 C语言的故事
1.5 程序设计语言的工作原理
1.5.1 运行
1.5.2 内存
1.6 本章小结
习题1
第2章 数据类型、运算符与表达式
2.1 一个简单的C程序例子
2.2 C程序常见符号分类
2.3 数据类型
2.3.1 为什么引入数据类型
2.3.2 从基本数据类型到抽象数据类型
2.3.3 类型修饰符
2.3.4 标识符命名
2.4 常量
2.4.1 整型常量
2.4.2 实型常量
2.4.3 字符常量
2.4.4 字符串常量
2.4.5 宏常量
2.4.6 枚举常量
2.5 变量
2.5.1 变量的定义与初始化
2.5.2 const类型修饰符
2.5.3 使用变量时的注意事项
2.6 常用运算符及表达式
2.6.1 运算符的优先级与结合性
2.6.2 算术运算符
2.6.3 关系运算符
2.6.4 逻辑运算符
2.6.5 赋值运算符
2.6.6 增1和减1运算符
2.6.7 类型强制转换运算符
2.6.8 位运算符
2.6.9 逗号运算符
2.7 赋值和表达式中的类型转换
2.8 本章小结
习题2
第3章 键盘输入与屏幕输出
3.1 C语句分类
3.2 表达式语句
3.3 复合语句和空语句
3.4 基本的输入/输出操作
3.4.1 字符输入/输出
3.4.2 格式输入/输出
3.4.3 使用函数scanf时需要注意的问题
3.5 本章小结
习题3
第4章 程序的控制结构
4.1 算法及其描述方法
4.1.1 算法的概念
4.1.2 算法的描述方法
4.2 顺序结构
4.2.1 顺序结构的流程图表示
4.2.2 应用程序举例
4.3 选择结构
4.3.1 应用场合
4.3.2 选择结构的流程图表示
4.3.3 条件语句
4.3.4 开关语句
4.4 循环结构
4.4.1 应用场合
4.4.2 循环结构的流程图表示
4.4.3 循环语句
4.4.4 单重循环程序实例
4.4.5 嵌套循环及其程序实例
4.5 流程转移控制语句
4.5.1 goto语句
4.5.2 break与continue语句
4.5.3 程序实例
4.6 程序调试与排错
4.6.1 程序中常见的出错原因
4.6.2 程序调试与排错的基本方法
4.6.3 使用getchar需要注意的问题
4.7 结构化程序设计方法简介
4.7.1 关于goto论战
4.7.2 结构化程序设计的核心思想
4.7.3 “自顶向下、逐步求精”的程序设计方法
4.8 本章小结
习题4
第5章 函数
5.1 程序设计的艺术
5.2 函数的定义与使用
5.2.1 函数的分类
5.2.2 函数的定义
5.2.3 函数的调用、参数传递和返回值
5.2.4 函数原型
5.2.5 主函数main的特殊性
5.3 变量的作用域和存储类型
5.3.1 变量的作用域
5.3.2 全局变量
5.3.3 变量的存储类型
5.4 函数封装
5.5 预处理指令
5.5.1 #include
5.5.2 #define和#undef
5.5.3 条件编译
5.6 使用assert查错
5.7 模块和链接
5.8 模块化程序设计方法简介
5.8.1 模块划分的原则
5.8.2 应用实例--“猜数”游戏
5.9 递归
5.9.1 递归问题的提出
5.9.2 递归函数
5.10 本章小结
习题5
第6章 数组
6.1 数组类型的应用场合
6.2 数组的定义、引用和初始化
6.2.1 数组的定义
6.2.2 数组的引用
6.2.3 数组的初始化
6.2.4 程序实例
6.3 向函数传递一维数组
6.4 向函数传递二维数组
6.5 字符数组
6.5.1 字符数组与字符串的关系
6.5.2 字符数组的输入/输出
6.5.3 字符串处理函数
6.5.4 应用实例
6.6 本章小结
习题6
第7章 指针
7.1 指针概述
7.1.1 指针的概念
7.1.2 为什么引入指针的概念
7.1.3 指针变量作函数参数
7.1.4 字符指针作函数参数
7.2 指针和数组间的关系
7.2.1 一维数组的地址和指针
7.2.2 二维数组的地址和指针
7.3 指针数组
7.4 函数指针
7.5 带参数的main函数
7.6 动态数组的实现
7.6.1 C程序的内存映像
7.6.2 动态内存分配函数
7.6.3 一维动态数组的实现
7.6.4 二维动态数组的实现
7.7 使用const修饰指针变量
7.8 代码风格
7.8.1 程序版式
7.8.2 命名规则
7.8.3 函数设计
7.8.4 防御性程序设计
7.9 本章小结
习题7
第8章 结构体与共用体
8.1 结构体的应用场合
8.2 结构体类型与结构体变量
8.2.1 结构体类型的声明
8.2.2 用typedef定义结构体类型
8.2.3 结构体变量的定义
8.2.4 指向结构体变量的指针
8.2.5 结构体变量的引用和初始化
8.3 结构体数组
8.3.1 结构体数组的定义
8.3.2 结构体数组程序实例
8.3.3 指向结构体数组的指针
8.4 向函数传递结构体
8.5 动态数据结构
8.5.1 问题的提出
8.5.2 链表的定义
8.5.3 链表的特点及操作原理
8.5.4 链表的建立
8.5.5 链表的删除操作
8.5.6 链表的插入操作
8.6 共用体
8.7 本章小结
习题8
第9章 文件操作
9.1 计算机中的流
9.2 文件
9.2.1 存储设备的使用
9.2.2 目录
9.2.3 文件格式
9.3 基本文件操作
9.3.1 基本文件操作函数
9.3.2 错误处理
9.3.3 程序示例
9.3.4 基本文件操作的意义
9.4 高级文件操作
9.4.1 文件的打开与关闭
9.4.2 文件的读/写
9.4.3 程序实例
9.4.4 标准输入与标准输出
9.5 本章小结
习题9
第10章 C程序设计常见错误及解决方案
条款1:使用未初始化和未赋值的变量
条款2:不考虑数值溢出的可能
条款3:不用sizeof获得类型或变量的字长
条款4:假定类型取值范围
条款5:期望两个整数的运算自动得出浮点数的结果
条款6:不预先判断除数是否为0
条款7:混淆“&,|”与“&&,||”
条款8:使用依赖编译器求值顺序的语句
条款9:使用依靠算符优先级的表达式
条款10:表达式过于复杂
条款11:用“==”时误用“=”
条款12:用“==”比较两个浮点数
条款13:使用幻数
……