天天看点

《C语言程序设计进阶教程》一导读

《C语言程序设计进阶教程》一导读

为什么要写这本书

本文讲的是<b>C语言程序设计进阶教程一导读</b>,市面上有成百上千种关于编程的书籍,其中有很多都是关于C语言编程的,那么为什么我还要写这本书呢?为什么建议你花时间读它呢?这本书跟其他书有什么不同呢?跟很多作者一样,我写这本书是因为我觉得有必要,觉得这本书中的方法比其他书中的更好。

我将现在已有的关于编程的书分为两类:入门和进阶。入门类书是给初学者写的,一般都假设读者没有编程基础,所以主要是介绍基本的概念。通常以“Hello World!”程序开始,也就是将“Hello World!”输出到电脑屏幕的程序。这种类型的书主要是一步步地介绍语言特点,包括关键词、数据类型、控制结构、字符串、文件操作等,而这些书一般都有一个特点:程序很短,一般是1~2页。这很奏效,因为短程序有助于解释编程语言的新概念。如果把学编程语言比作学自然语言,如英语、汉语、法语、韩语等,这些书就相当于教导如何造句和撰写短段落。

第二类书是写给有程序开发经验的读者的。这些书主要介绍解决现实中的问题的程序,比如关于电脑游戏或者图像。而这类书的例子一般很长,有些甚至几千行代码,因此不会全部印在书本上。书中只会解释程序的其中一部分,而源程序一般保存在CD或者某个网址上。这类书一般不会再介绍如何编程,而是大多专注于解决特定问题的算法研究,有时包括算法性能的详细信息。读者不可能再找到类似于“Hello World!”这样的例子。再比作自然语言的例子,这类书就是在教导如何撰写可能超过20页的短篇小说。

问题是,从写一个段落到写一篇小说,这种跨越太难了。

一本针对中级编程能力的学生的书

市面上很少有针对中级编程能力学生的书籍。这些学生往往已经掌握了编程的基本知识,在看到if或者while时不会茫然,知道如何创建函数和调用函数,有能力编写几十上百行的短代码,却不知道如何处理上千行的程序。他们经常会犯错误,因为大多数入门级的书籍只教导如何编写正确的程序,却不会教导避免常见的错误。他们往往对大多数的概念和那些可以帮助提高编程能力的工具都不太熟悉,他们需要这样一个台阶:可以帮助他们从有能力编写短代码到有能力编写解决现实问题的程序。

现在入门和进阶的空档已经被数据结构和算法的书籍填充了一部分,这类图书一般提供实现数据结构或算法的完整例子。然而这并不是最合适的解决方法,这类图书致力于介绍数据结构和算法,却罕有提供帮助读者编写正确代码的信息。事实上,它们大多只提供程序,而很少解释。它们往往不解释编程概念,比如函数需要一个指针作为实参的原因或者深拷贝与浅拷贝之间的差异等。因此,读者只能自学这些编程技巧。

为了迎合这个需求,我写下这本针对中级编程能力的学生的书,本书适合作为学习编程的第二本教材。

避免出错和调试的重点

我们可以看到有很多关于如何编程的书籍,却很少关于开发软件的书籍。开发软件不是简单地输入代码,它需要更多的知识和技能。为了弥补这种不足,最好就是去研究什么是对的、什么是错的。只解释如何编写正确的程序是不够的,还需要解释常见的错误并将它们与正确的程序进行对比。

一次疏忽可能使程序运行出乎意料,甚至是某些情况下运行正确而另一些情况下出错。这种类型的错误往往很难发现,更别说更正了。本书将介绍一些常见的错误以教导读者如何避免这些错误。调试过程在大多数书中都不会涉及,罕有书籍会提到“调试器”这个词,以至于有些读者都不知道这类工具的存在。学会如何使用调试器一般不超过30分钟,这可以帮助程序员节省很多时间。关于如何使用调试器和调试策略的书籍则更少了。

程序设计和离散数学

程序设计和离散数学是计算机科学中的两个重要学科,然而,大多数书籍都将这两个主题分开,所以很少会在编程的书籍中看到数学公式,同样也很难在离散数学中看到代码。在本书中,这两个主题紧密结合,我相信读者可以从中学到更多的知识。

为什么本书使用C语言?

C语言诞生于20世纪60年代后期和20世纪70年代早期。在C语言发明之后,很多语言也相继出现,这些语言也深受C语言的影响。除了它的历史影响之外,C语言的简单易用也保证了它在几乎所有现代化平台中的重要地位。与许多操作系统一样,Linux是就用C语言编写的,Android基本都是用Java编写的但仍有叫作JNI(Java Native Interface,Java本地接口)的C语言接口。大多数计算机语言都可以与C语言进行通信或通过C语言进行通信,事实上这对一种编程语言而言是有用的,因为大多数操作系统接口都使用C语言。当一个全新的系统被设计出来,C语言通常是第一种(很多情况下是唯一一种)被系统支持的编程语言。

对于具有中级编程能力的学生来说,C语言是一个很好的选择,因为学习C语言需要了解很多计算机概念。langpop.com网站对比了编程语言的受欢迎程度,得出C语言是最受欢迎的语言,紧接着是Java。IEEE Spectrum中的一个报告将编程语言进行排行,主要考虑四类软件:移动应用、企业软件、嵌入式系统和网页。其中嵌入式系统中最受欢迎的就是C语言。四种类型都考虑时,前五名编程语言如下所示:

Java(100%)

C(99.3%)

C++(95.5%)

Python(93.4%)

C#(92.4%)

可以发现,基于C的编程语言(C、C++、C#)占据了前五席的三席。而Java是受C++影响的。

为什么需要读这本书?

如果你是计算机科学、计算机工程或者电子工程专业的学生,那么就绝对应该读本书。本书包含了很多基本概念,这些概念对于理解计算机中程序的运行方式十分重要。如果你是工程、科学、数学或者技术专业的学生,在学习工作中就很有可能需要用到计算机,而阅读本书将会有很大帮助。即便你不是上述专业的学生,仍然可以在本书中学到很多有用的概念(比如递归)。

作者、审稿人及封面设计师

作者简介

Yung-Hsiang Lu 是美国印第安纳州西拉法叶普渡大学电子与计算机工程学院的副教授。他是美国计算机协会(ACM)的杰出科学家和演说家。2011年8~12月,曾是新加坡国立大学计算机科学系的客座副教授。他在美国加利福尼亚州斯坦福大学电子工程系取得博士

学位。

审稿人简介

Aaron Michaux是美国印第安纳州西拉法叶普渡大学电子与计算机工程学院的一名研究生。他在澳大利亚昆士兰科技大学取得计算机科学学士学位,在加拿大新布伦瑞克圣托马斯大学获得心理学学士学位。Aaron在重新回到学校攻读博士学位之前已经作为专业程序员工作了10年。他的研究方向主要围绕计算机视觉和人类视觉感知。

Pranav Marla是美国印第安纳州西拉法叶普渡大学电子与计算机工程学院的一名本科生。他主修的专业是计算机科学。在计算机工程、心理学和哲学上也稍有涉猎。他希望可以专攻机器学习和人工智能。

封面设计师简介

本书封面是由Kyong Jo Yoon描绘的。他是一名韩国画家,经常在自然场景中加入英雄人物。他是韩国美术协会的一名顾问,他的作品在美国伊利诺伊州芝加哥市的安内森美术馆中展出。

软件开发中的规则

如果由于软件错误,银行每天将你的钱减少0.1%,你会满意吗?你能接受每个月都少走40分钟的手表吗?这两种情况都是“成功了99.9%”,但却都让人无法接受。计算机现在用在很多应用程序中,有些甚至会影响人类的安全。即使你编写的程序在99.9%的时间里都可以正确地运行,那也有可能会在剩余的0.1%的时间里危害人类的生命。这是绝对让人无法接受的,这是一个失败的程序。因此,99.9%的成功就是失败。

如果你住在加州的帕萨迪纳,现在想去纽约,你会走哪条路呢?也许你会去洛杉矶机场,然后坐飞机去纽约。但是纽约在帕萨迪纳的东边,而机场在帕萨迪纳的西边。你为什么不直接开车去东边呢?你为什么要绕路去机场呢?如果你直接开车去东边,而不是去机场排队的话,你就离纽约越来越近了啊。答案很简单:相对于汽车来讲,飞机这一交通工具更适合长途旅行。在程序开发中,有许多用以管理大型软件的开发工具,你需要学习这些工具。没错,学习使用工具会消耗一些时间,但是如果你使用不合适的工具或者不使用工具的话,将浪费更多的时间。花些时间学习使用编程工具将在软件开发和调试时节省大量时间。

尽管经过了数十年的努力,现在的计算机依然没有达到智能化的水平。计算机无法猜测你的想法。如果你写的程序让计算机去做一件错事,那么计算机就会跟随指令去做。如果你的程序是错的,那就是你的责任。计算机无法猜测你的想法。在很多例子中,计算机程序中一个微小的错误就可以造成巨大的财产损失,甚至危及人类的生命。缺少一个分号“;”或者用“,”取代“. ”,程序将无法执行。计算机程序不能容忍任何微小的错误。

通过测试方案并不能保证程序的正确性。测试只能得出一个程序有错误的结论但不能表明一个程序是正确的。为什么呢?测试方案能覆盖所有可能的情景吗?覆盖全部情景是非常困难的,而且在很多情况下是不可能的。因为测试方案很难检测特殊行为,所以一些问题可能会隐藏在你的程序中。

产生正确的输出并不意味着程序是正确的。你会认为一架已经安全起飞并着陆的飞机是安全的吗?如果飞机在漏油,你会在登机前要求航空公司维修飞机吗?如果航空公司回复:“之前没有人受伤,说明这架飞机是安全的。”你会接受航空公司的回应吗?如果司机闯红灯而没出事故的话,是否意味着闯红灯是安全的呢?一个可以产生正确输出的程序就像是一架安全着陆的飞机。可能有很多问题隐藏在安全的表面之下。很多工具可以检测人类隐藏的健康问题,比如X–射线,核磁共振以及超声波扫描。我们也需要工具来检测出隐藏在电脑程序中的问题。即使程序可以产生正确的输出,我们也要对它们进行修改。

你必须假设程序会出问题,并开发出检测和改正问题的策略。在写程序时,应该每次只专注于一小部分。在仔细检查并确保没有问题之后再进行下一部分。对于大多数程序,你需要为了测试这些小的模块而编写额外的程序。虽然这些测试代码并不包含在最终的程序中,但是编写测试程序可以节省大量时间。有时,测试代码可能会比程序本身还要多。我自己的经验建议1:3的比例:最终程序中的1行代码,需要3行测试代码。

没有什么工具可以取代一个清醒的大脑。工具可以提供一些帮助,但是对概念清晰深刻的理解才是最重要的。如果你想成为一名优秀的程序员,那么你需要完全理解每一个细节。不要指望工具可以替你思考:它们做不到。

源代码

本书中所有的程序都可以从github.com上获取。请使用下面的命令获取文件:

…………………………………………

$是Linux终端的shell提示符

<a href="https://yq.aliyun.com/articles/214042">1.1 编译</a>

<a href="https://yq.aliyun.com/articles/214053">1.2 重定向输出</a>

<a href="https://yq.aliyun.com/articles/214073">2.1 值和地址</a>

<a href="https://yq.aliyun.com/articles/214088">2.2 栈</a>

<a href="https://yq.aliyun.com/articles/214121">2.3 调用栈</a>

<a href="https://yq.aliyun.com/articles/214134">2.3.2 函数实参</a>

<a href="https://yq.aliyun.com/articles/214139">2.3.3 局部变量</a>

<a href="https://yq.aliyun.com/articles/214148">2.3.4 值地址</a>

<a href="https://yq.aliyun.com/articles/214153">2.3.5 数组</a>

<a href="https://yq.aliyun.com/articles/214157">2.3.6 获取地址</a>

<a href="https://yq.aliyun.com/articles/214166">2.4 可见度</a>

<a href="https://yq.aliyun.com/articles/214170">2.5 习题</a>

<a href="https://yq.aliyun.com/articles/214175">2.5.1 绘制调用栈I</a>

<a href="https://yq.aliyun.com/articles/214180">2.5.2 绘制调用栈II</a>

<a href="https://yq.aliyun.com/articles/214188">2.6.1 绘制调用栈I</a>

<a href="https://yq.aliyun.com/articles/214193">2.6.2 绘制调用栈II</a>

<a href="https://yq.aliyun.com/articles/214406">2.7 在DDD(命令行调试程序)上检测调用栈</a>

<a href="https://yq.aliyun.com/articles/214412">第3章 预防、检测及消除bug</a>

<a href="https://yq.aliyun.com/articles/214418">3.1.1 编程前</a>

<a href="https://yq.aliyun.com/articles/214423">3.1.2 编程中</a>

<a href="https://yq.aliyun.com/articles/214431">3.1.3 编程后</a>

<a href="https://yq.aliyun.com/articles/214434">3.2 常见错误</a>

<a href="https://yq.aliyun.com/articles/214439">3.2.1 未初始化变量</a>

<a href="https://yq.aliyun.com/articles/214443">3.2.2 错误数组下标</a>

<a href="https://yq.aliyun.com/articles/214453">3.3 后执行式和交互式调试</a>

<a href="https://yq.aliyun.com/articles/214458">3.4 生产代码与测试代码分离</a>

原文标题:C语言程序设计进阶教程一导读