简介:《C程序设计(谭浩强第五版)》课后习题答案整理文档,面向高校C语言课程学生、考研复习者与自学入门读者,用于对照教材章节核对习题解答、梳理程序设计基础概念与上机流程。内容按章组织:第一章围绕程序与程序设计、计算机语言特点、源程序与目标程序及可执行程序的区别、程序编辑编译连接、程序模块与程序文件、函数与主函数及库函数、程序调试与测试等名词逐条释义,并给出Hello World、图形输出、三数求最大值等实践题的代码与运行结果;第二章延伸至算法概念、结构化算法与顺序、选择、循环三种基本结构,配合传统流程图与瓶子互换、求最大值等经典题解析。压缩包共1个PDF文件,约4.82MB,单文件便于在手机与电脑上直接翻阅检索。目前已有7192人学习,适合配合教材同步练习、期末复习与上机前查漏补缺。
1. 从一行 Hello World 说起:程序、程序设计这些词到底在说什么
很多人学 C 语言的第一课,是在编辑器里敲下一行printf("Hello World!\n");,点一下运行,屏幕上蹦出几个字母,然后心里冒出一个疑问:这就叫编程?其实这行字背后藏着三个词——程序、程序设计、计算机语言,它们几乎在每本 C 语言教材第一章都会出现,也几乎被每个人一眼扫过去。可偏偏是这三个词,决定了你后面是在“背语法”还是在“真理解”。打个比方,程序像一份写给机器的操作清单,计算机语言是写这份清单用的文字,程序设计则是从“想干什么”到“清单写完、验证能用”的整个过程。搞不清这三者的边界,写出来的代码就只能靠一次次试,出了错也不知道该往哪儿找。
2. 程序、程序设计、计算机语言:三个天天见却说不清的定义
2.1 程序:一份机器能照着做的操作清单
把程序想成一份写给厨房学徒的菜谱:先热锅、再倒油、下葱姜、翻炒三分钟。每一步都是一个具体动作,学徒照着做就能出菜。程序也是一样,它是一组能被计算机识别并执行的指令,每一条指令都对应一个明确的操作——把两个数加起来、把一段内存清零、把结果送到屏幕上。计算机不会“领会精神”,它只会一条一条往下执行,所以你写的每句话都得能被无歧义地翻译成一个或几个机器动作。
这个定义里有两个关键词容易被忽略。“能识别”意味着指令必须属于这台机器和这套编译环境认识的范围,你随手写个中文句子它当然不认;“能执行”意味着每条指令都得落到一个实际动作上,不能是“大概处理一下数据”这种含糊表达。新手常踩的坑就是把注释当指令写,以为写一句“这里应该排序”程序就会排序,结果编译器一句报错都懒得给,运行出来当然不对。
程序还有第二层含义:运行在计算机上、用来满足某种需求的信息化工具。这时候它不再是一堆抽象指令,而是一个有形的东西——一个能算成绩单的小工具、一个能画图形的演示程序。同一份代码,从内部看是指令集合,从外部看是解决问题的工具,这两种视角并不矛盾,只是看问题的距离不一样。理解这一点,后面听到“这个程序有多大”“这个程序有什么功能”时就不会觉得别扭。
指令本身也分层。最底层是机器指令,一串 0 和 1;往上一层是汇编指令,用助记符代替二进制;再往上是高级语言语句,一行sum = sum + i;背后可能是好几条机器指令。层次越高,人写起来越省力,机器执行前要做的工作也越多——这条线索会贯穿后面的编译、连接,值得先记下来。
2.2 为什么需要计算机语言:总得有个双方都认的写法
计算机内部只认电平高低、只存 0 和 1。人如果直接用 0 和 1 跟它说话,写十行代码可能就得对着手册查半天,改一个数还要担心错位。计算机语言要解决的正是这个“交流不通”的问题:它提供一套人和机器都能处理的写法,人写起来有章可循,机器拿到之后有办法翻译成自己的语言。
早期用的是机器语言和汇编语言,它们和具体硬件绑得很紧,换一台机器指令集变了,程序基本要重写。高级语言往前迈了一大步,教材里归纳的几个特点,其实都在说同一件事:让人写得更省心。数据结构比汇编和机器语言丰富,数组、结构体、指针这些现成的容器随手可用,不用自己拿一块内存去手工切分;与具体机器结构的关联没那么密切,同一份源代码换一套编译环境往往还能编出来,可移植性就是这么来的;更接近自然语言,if、while、return这些词读起来像英语句子,语义也直观,学起来的门槛低不少。
代价也在这里:高级语言写的程序,计算机并不能直接执行,必须先经过编译或解释,翻译成机器能懂的二进制形式。这笔“翻译成本”是躲不掉的,它换来了写代码时的省力,也顺带带来一个好处——编译器在翻译时会顺手做语法检查,很多低级错误在运行之前就被拦下来了。理解了这个交换关系,你就不会觉得“写完还得编译一次”是麻烦,而是把它当成一道免费的检查关口。
2.3 程序设计:从接到任务到交出文档的全过程
很多人把程序设计等同于敲代码,这是个挺常见的误解。教材给出的定义是从确定任务到得到结果、写出文档的全过程,这句话的重点在“全过程”三个字上。敲代码只是中间的一段,前面有想清楚要做什么,后面有验证做对了没有,两头都省不得。
拿盖房子类比最直观。真要盖一栋楼,不会有人扛起砖就开始砌:先得知道盖几层、住多少人,这是确定任务;再画图纸、算承重,这是设计算法和结构;然后才是砌墙浇筑,这是编码;砌完要验收、通水通电试试,这是调试和测试;最后交钥匙的时候还得给一份管线图,这是文档。少了前面任何一步,后面都会返工。写程序也一样,题目都没读明白就开始敲for循环,八成要推倒重来。
把这条流水线摊开,大致是这么几段:弄清楚问题到底要输入什么、输出什么;设计解题的步骤,也就是算法;用某门语言把步骤写出来,形成源程序;上机编辑、编译、连接,让机器能跑;跑起来之后调试改错、测试验证;把思路和数据整理成文档。每一段都有各自要操心的事,混在一起想就会乱。新手最常见的翻车场景是:算法没想清楚就直接编码,编到一半发现逻辑走不通,于是边改边想,最后代码变成一团自己也看不懂的东西。
这里还有一层现实意义。真到了多人协作的场合,程序设计的“设计”部分会被放大:模块怎么划分、函数怎么分工、接口怎么约定,全都要在敲代码之前定下来。一个函数只做一件事、一段代码只负责一个功能,这种习惯不是洁癖,而是让后面修改和维护的人少受点罪。教材反复强调结构化、强调模块化,说的就是这件事。
3. 从源程序到可执行程序:编辑、编译、连接到底各干了什么
3.1 三段身份:源程序、目标程序、可执行程序
同一个程序,在开发过程的不同阶段有不同的“身份”,教材用三个名词把它们区分开了。
源程序是你亲手敲出来的那个文件,它是按一定程序设计语言规范书写的文本文件,本质上是一系列人类可读的指令。它长得就像普通文本,用记事本也能打开,里面是你能读懂的英文单词和符号。这时候它还只是“文字”,计算机不能直接运行它。
目标程序是源程序经过编译之后得到的东西,是机器码的集合,在文件上通常以.obj作为扩展名。它已经是二进制了,你双击打不开,用文本编辑器打开也是一堆乱码。但它还不是最终能运行的程序,因为它可能只是整个工程里的一个零件,还缺别的零件,也缺公共的工具库。
可执行程序是最后一步的产物:把所有编译得到的目标模块连接装配起来,再与函数库连接成一个整体,生成一个可供计算机执行的目标程序。到这一步,它才是一个完整的、能独立跑起来的东西。
| 名称 | 内容形态 | 常见后缀 | 谁能直接读懂 |
|---|---|---|---|
| 源程序 | 按语言规范书写的文本 | .c | 人 |
| 目标程序 | 编译产生的机器码集合 | .obj | 机器 |
| 可执行程序 | 目标模块与函数库连接后的整体 | .exe | 机器 |
这张表值得记一下,因为后面很多报错信息都跟“现在处于哪个阶段”有关。语法错误出现在编译阶段,提示“找不到某个符号”往往出现在连接阶段,而运行结果不对则是程序跑起来之后的事。分不清阶段,就只能对着一屏幕英文发懵。
3.2 编译之前还有一步:预处理器和语法检查
很多人以为“编译”就是一个动作,实际上它内部还有先后。C 语言提供了一套预处理器,在正式翻译之前,先把程序里的预处理指令处理掉——典型的就是#include和#define。#include <stdio.h>会被原地展开成头文件的内容,#define N 10会把后面出现的N全部替换成10。这一步发生在语法检查之前,所以宏写错了常常会引发一堆看起来莫名其妙的语法错误。
处理完预处理指令,编译程序对源程序做语法检查,判断有没有语法错误,直到没有语法错误为止,然后才自动把源程序翻译成二进制形式的目标程序。注意这里的顺序:先查错,再翻译。所以有时候你改了一个分号,报错数量从二十个变成零个,不是玄学,是前面那个错误把后面的解析全带偏了。
#include <stdio.h> /* 预处理指令:编译前把头文件内容展开到这一行 */ #define N 10 /* 宏定义:预处理阶段把下文的 N 全部替换成 10 */ int main(void) { int sum = 0; for (int i = 1; i <= N; i++) { /* 循环变量 i 从 1 走到 10 */ sum += i; /* 每轮把 i 累加到 sum */ } printf("%d\n", sum); /* 输出 55 */ return 0; }这段代码里,#include和#define都不是运行时执行的语句,它们在编译之前就被处理掉了,你在最终的目标程序里找不到它们的痕迹。N是宏名,10是替换文本,替换发生在文本层面,不涉及类型检查,这也是宏容易被误用的原因。至于printf,编译阶段只是确认你调用它的写法没问题,真正的实现并不在这份源程序里——那是连接阶段要解决的事。
3.3 连接:把散装的模块和函数库焊成一个整体
编译完成,你手上可能有一堆.obj文件:主函数的、各个自定义函数的、还有从别处拿来的模块。它们各自是完整的机器码片段,但彼此之间还留着“接口没接上”的空位。程序连接要做的事,就是将所有编译后得到的目标模块连接装配起来,再与函数库相连接成为一个整体。
装修的类比挺好用。墙、地板、水电分别施工,各自验收合格,但这不代表房子能住;最后还得有人把水管接到龙头、把电线接到开关、把门装到门框上,整套系统才通。连接器干的就是这个活。它把 A 模块里调用 B 模块函数的那个“占位”替换成真正的地址,再把标准库里printf的实现接进来,最后吐出一个可以直接运行的文件。
这也解释了一类常见报错:代码明明语法没问题,编译也过了,连接的时候却提示某个符号找不到。多数情况是你调用了某个函数,却没有把定义它的目标模块或库带进来。这时候要检查的不是语法,而是“零件齐不齐”。反过来说,如果连编译都没过就去看连接错误,那基本是在错误的地方找答案。
顺带说一句,.obj和.exe的区别也在这里体现。前者是零件,后者是整机。零件可以单独存在、单独复用,但只有整机才能交付使用。理解了这个层次,再看到工程里一堆中间文件就不会觉得它们是垃圾——它们是流水线上的半成品。
4. 算法:程序的灵魂,和它的四种表达方式
4.1 算法就是解题步骤,跟代码没关系
算法这个词听起来很数学,其实日常里到处都是。教材给的定义很朴素:算法就是求解问题的步骤,是对特定问题求解步骤的一种描述。注意它没说“用计算机语言描述”,也没说“必须能运行”,它只是一套步骤。
举三个生活里的例子就够了。考大学的“算法”是:填报志愿、交报名费、拿准考证、按时参加考试、收到录取通知书、按日期到校报到。去外地听演唱会的“算法”是:网上买票、按时坐车过去、再坐车到会场。把大象放进冰箱的“算法”是三步:打开冰箱门、把大象放进去、关上冰箱门。这三个例子里没有一行代码,但步骤清清楚楚,谁照着做都能得到同样结果,这就是算法。
把这层理解迁移到编程上,好处很明显:你可以先在纸上把步骤想清楚,再考虑用什么语句实现。步骤想清楚了,代码只是翻译工作;步骤没想清楚,写多少行都是白搭。很多人写程序卡住,卡的不是语法,是不知道自己下一步该干什么,本质上是算法没成形。
同一个算法可以有多种表达方式,教材里提到的主要是自然语言、传统流程图、N-S 图和伪代码。它们描述的是同一件事,区别只在“给谁看、看什么”。自然语言给人看,最容易懂也最容易有歧义;流程图把控制流向画出来,一眼能看出分支和循环在哪;N-S 图去掉了箭头,用嵌套的矩形框表示结构,强迫你把逻辑写得规整;伪代码介于自然语言和代码之间, Borrow 了代码的结构但不拘泥于语法细节。
4.2 三种基本结构:顺序、选择、循环
结构化程序设计方法主要由三种基本结构组成,这个划分不是随便定的,而是因为任何复杂逻辑都能拆成这三样的组合。
顺序结构是一种线性、有序的结构,它依次执行各语句模块。代码从上往下走,不跳、不回头,先算 A 再算 B,简单直接。选择结构根据条件成立与否选择程序执行的通路,条件为真走一条路,为假走另一条,两条路不会同时走。循环结构则是重复执行一个或几个模块,直到满足某个条件才停下来,累加求和、遍历数组都靠它。
为什么教材反复提倡结构化?理由很实在:便于编写,可读性高,修改和维护起来简单,减少出错的机会,提高程序的可靠性,保证程序的质量。翻译成人话就是——写的时候不容易乱,别人(包括三个月后的你)看得懂,改的时候不会一动就崩一片。这点血泪经验,写过几百行没有函数的代码的人都懂。
一个合格的基本结构要满足几个条件:只有一个入口,只有一个出口,结构内的每一部分都有机会被执行到,结构内不存在死循环。前两条保证流程清晰,第三条保证没有写了却永远跑不到的死代码,第四条保证程序不会卡死在那儿。按这个标准,while 型和 until 型循环、多选择结构也都是合规的基本结构,它们不过是三种基本形态的组合变形。
判断一段代码结构好不好,有个简单的测法:拿张纸,从入口画一条线,看能不能只靠顺序、分支、循环这三种形状把它完整画出来,中途不需要跳来跳去。画得出来,结构就是清楚的;画到一半发现线要往回穿好几层,那多半是嵌套太深或者用了不该用的跳转。
4.3 同一件事的四种写法:以“交换两瓶液体”为例
教材里有个特别适合入门的例子:A 瓶装醋,B 瓶装酱油,要把两瓶的内容互换。直接倒是不行的,醋倒进 B 就把酱油盖了,所以必须借助一个空瓶 C 当中转。
用自然语言描述就是三句话:先把 A 里的醋倒进空瓶 C,再把 B 里的酱油倒进 A,最后把 C 里的醋倒进 B。这三句话已经是一个完整算法了,步骤明确、顺序不能换,谁照着做都能成功。
用流程图描述,会用到几种固定形状:椭圆表示开始和结束,矩形表示“倒液体”这种处理动作,箭头表示流向。整个图是一条直线,没有分支也没有循环,因为这件事本身就是顺序结构。N-S 图表达同一件事时不用箭头,而是把三个矩形框从上到下排在一起,用一个外框包住,读起来就是“依次做这三件事”。两种画法表达的信息一样,只是 N-S 图更强调“这是一个整体块”。
伪代码则是这样写的:
begin 醋 => A // 把醋装进 A 瓶 酱油 => B // 把酱油装进 B 瓶 A => C // 借助空瓶 C 暂存 A 中的醋 B => A // 把 B 中的酱油倒进 A C => B // 把暂存在 C 中的醋倒进 B end这里的=>表示“倒入/赋值”的方向,begin和end圈出算法范围。它没有分号,也没有声明变量类型,因为它不是给编译器看的,是给人看的。真正写成 C 语言,就变成了这样:
#include <stdio.h> int main(void) { int a = 1; /* 用 1 代表醋 */ int b = 2; /* 用 2 代表酱油 */ int c; /* 空瓶子 C,只做中转,初值无所谓 */ c = a; /* 第一步:醋倒进空瓶 C */ a = b; /* 第二步:酱油倒进 A */ b = c; /* 第三步:醋从 C 倒回 B */ printf("a=%d, b=%d\n", a, b); /* 输出 a=2, b=1,交换完成 */ return 0; }三个变量分别承担“醋”“酱油”“空瓶”的角色,c在这里就是那个临时中转站。如果不借助c,写成a = b; b = a;,第一句执行完a里原来的值就被覆盖了,第二句再把已经被覆盖的值赋给b,两边都变成酱油,交换失败。这正是“算法错了,代码写得再漂亮也没用”的最小例子。
同样的思路可以推广到更复杂的题目。比如求两个数的最大公约数,教材用的是辗转相除法:如果 m 大于 n 就交换,然后反复用 m 除以 n 取余数,把 n 给 m、余数给 n,直到 n 为 0,此时的 m 就是答案。这个算法的描述只有几句话,但它是整个程序的灵魂;换成代码,不过是把这几句话翻译成循环和取模运算。先有算法,后有代码,顺序反了就会陷入“边写边试”的泥潭。
5. 五个最容易混的概念:分清它们,教材前半本就不卡了
5.1 程序、程序模块、程序文件:说的不是同一个颗粒度
这三个词都带“程序”,日常口语里也常混着用,但它们的颗粒度完全不同。
程序是整体,是一组计算机能识别和执行的指令,运行在计算机上,满足人们某种需求。程序模块是零件,指可由汇编程序、编译程序、装入程序或翻译程序作为一个整体来处理的一级独立的、可识别的程序指令。程序文件是载体,程序的文件称为程序文件,它存储的是程序,包括源程序和可执行程序。
容易混是因为三者经常同时出现在一句话里:“这个程序由三个模块组成,分别放在三个文件里。”一句话三个词,指的全是不同的东西。区分方法看“它回答什么问题”:程序回答“这东西能干什么”,模块回答“它由哪几个可独立处理的部件构成”,文件回答“它存在哪儿、叫什么名字”。
用一辆车打比方:程序是整车,模块是发动机、变速箱、底盘这些能单独装配的部件,文件是存放整车和部件的仓库位置。整车能开,部件不能单独开,仓库更不会开。搞混了,写代码时就会把“拆模块”和“分文件”当成一回事,结果模块划得乱七八糟,文件倒是建了十几个。
5.2 函数、主函数、被调用函数、库函数:说的是角色不是同一种东西
这四个词都叫“函数”,最容易让人以为它们是并列的四种东西,其实它们描述的是不同层面的角色。
函数本身是一个封装单位:将一段经常需要使用的代码封装起来,在需要使用时可以直接调用,来完成一定功能。主函数又称 main 函数,是程序执行的起点,一个有可执行入口的程序里必须有且只有一个。被调用函数是相对关系词:由一个函数调用另一个函数,则称第二个函数为被调用函数。库函数是来源词:一般指编译器提供的、可在 C 源程序中调用的函数,分两类,一类是 C 语言标准规定的库函数,一类是编译器特定的库函数。
混的原因在于一个函数可以同时占好几个身份。main里调用printf,printf既是库函数(来源是标准库),又是被调用函数(相对main这个调用者而言)。同一个printf,换个角度看就是两个标签。区分方法问自己两个问题:它是谁提供的(自己写的还是库里带的),它在这次调用里站哪边(调用方还是被调方)。答案清楚了,标签自然就贴对了。
5.3 程序调试与程序测试:一个在找错,一个在证明没错
这两个词都发生在“正式使用之前”,都要把程序跑起来,所以经常被当成同义词。实际分工差别不小。
程序调试是把编制的程序投入实际运行前,用手工或编译程序等方法进行测试,修正语法错误和逻辑错误的过程。注意“修正”两个字,调试的终点是“改好了”。程序测试是对一个完成了全部或部分功能、模块的计算机程序在正式使用前的检测,以确保该程序能按预定的方式正确地运行。测试的终点是“确认它确实按预期工作”。
为什么容易混?因为现实中这两件事常常连着做:跑一遍发现结果不对,改代码,再跑一遍,看起来是一个动作。但目标不一样:调试是面对错误的,哪儿疼治哪儿;测试是面对需求的,逐条核对说好的功能有没有做到。只调试不测试,程序可能“不报错但结果是错的”;只测试不调试,发现问题也没人改。
实际顺序通常是先让程序能跑起来(把语法错误清掉),再验证它算得对不对(逻辑和功能)。语法错误编译器会直接告诉你行号,逻辑错误只能靠你自己比对预期结果,这部分没有捷径。
5.4 编译与解释:一个先全部翻译完再执行,一个翻一句执行一句
教材在讲高级语言特点时只提了一句“高级语言编写的程序要经过编译或解释计算机才能执行”,一笔带过,很多人就此留下一个模糊印象:反正都要翻译。
区别在于翻译的时机和产物。编译是先把你写的整个源程序翻译成目标程序,再由计算机执行这个目标程序;解释则是拿到一句翻一句,翻完立刻执行,不生成独立的目标程序。打个比方,编译像把一本外文书整本翻译好再出版,读者拿到的是译本;解释像同声传译,说一句翻一句,散场之后没有留下译本。
这个区别带来的实际影响是:编译型语言在翻译阶段就能发现大部分语法错误,运行速度快,但换个平台往往要重新编译;解释型语言启动快、跨平台方便,但错误可能要到执行到那一行才暴露。C 语言属于编译型,源程序要经过编译、连接才能运行,所以你在编辑器里写完代码必须走一遍构建流程,不能指望它自己边读边跑。
提示:判断一门语言偏编译还是偏解释,看它运之前要不要生成独立的目标文件,比记定义更靠谱。
5.5 算法与程序:一个是步骤,一个是步骤的落地
这两个词的混用率极高,因为写代码的时候两者是交织的:一边想步骤一边敲,界限被抹平了。
算法是求解问题的步骤描述,它不依赖任何编程语言,用自然语言、流程图、N-S 图、伪代码都能表达,甚至可以在纸上写完就扔掉。程序是算法的具体实现,必须符合某门语言的语法规则,必须能被计算机执行,必须处理输入输出的细节。算法回答“怎么一步步做”,程序回答“用这门语言怎么写出来并且跑通”。
区分的意义在于排错。程序跑出错误结果,先怀疑算法还是先怀疑代码?经验做法是先用手算几个小例子验证步骤本身对不对:如果按你的步骤手工算都得不到正确答案,那问题在算法,改代码是白费力气;如果手工算对了但程序算错了,那才是编码环节出了问题,比如循环边界差一、变量没初始化、类型转换丢精度。
一个程序能跑,不代表算法是对的;一个算法是对的,也不代表程序能跑。这两件事分开看,排查效率会高很多。很多初学者一遇到结果不对就盯着代码逐行看,看半天看不出问题,其实是第一步的步骤就想歪了。
6. 什么时候该翻这份资料,什么时候翻答案等于白翻
课后答案这类资料,用对了是加速器,用错了是拐杖,而且是一根会让人忘了怎么走路的拐杖。判断标准其实很简单:你是拿它来“对照”,还是拿它来“代替”。
先说该翻的场景。概念题答不上来的时候,比如被问到“程序模块和程序文件有什么区别”“调试和测试是不是一回事”,这类问题考的是定义的边界,自己憋半小时也憋不出标准表述,直接对照答案把差别记下来,效率最高。编程题写完一版能跑通的代码之后,拿来对照思路,看看自己的循环边界是不是更啰嗦、变量是不是多设了一个、有没有更直接的写法,这种对照是有营养的,因为你已经付出了思考成本,答案只是用来校准。还有一种是编译报错看不懂,答案里的完整代码可以帮你定位是不是少了头文件、括号是不是配错,但前提是你先读了报错信息。
再说别翻的场景。题目读完完全没思路就直奔答案,这是最常见的用法,也是最没效果的用法。看懂了答案不等于会做,你只是看了一遍别人的推导,大脑会给你一种“我明白了”的错觉,下次遇到同类题照样卡住。正确的做法是先自己写出哪怕很丑的一版,哪怕只能处理三个数、哪怕循环写错了,写完再对照,这时候你才知道自己差在哪个环节。还有一种情况是拿答案背代码应付检查,这个不用多说,背下来的代码换个输入就崩,考试和实际开发都不会陪你演。
| 场景 | 建议 | 原因 |
|---|---|---|
| 概念辨析题没把握 | 对照答案,记边界 | 定义类问题自己推容易推偏 |
| 编程题已写出可运行版本 | 对照思路,比较写法 | 有思考打底,对照才有校准作用 |
| 编程题完全没有思路 | 先自己想十分钟,再看提示 | 直接看代码会跳过思考环节 |
| 编译报错 | 先读报错信息,再查代码 | 报错本身已经指出了位置和类型 |
| 想背答案应付检查 | 不建议 | 换个输入就失效,学不到方法 |
我自己就吃过这个亏。早些年做课后编程题,习惯是先扫一眼答案的框架,再回头“补”自己的代码,感觉进度飞快,一章的题两个小时就刷完了。等到做综合练习,题目稍微变个形,比如把“输入三个数求最大”改成“输入十个数求最大”,我盯着屏幕半天写不出循环,才发现之前那些“会了”全是假的,我只是记住了答案长什么样,并没有真的想过为什么要这么写。从那以后我每次写编程题,都强制先自己写一版,哪怕写得丑、跑得慢、要多写十几行,也要先让它跑通,再去翻答案对照。这个习惯一开始很磨人,进度肉眼可见地变慢,但两三章之后,看到题目能自己拆出步骤的感觉,是刷答案永远给不了的。
这份资料的价值也在这里:它把每章的概念题和编程题整理成了一份可以对照的笔记,程序、程序设计、源程序与目标程序、函数与库函数、调试与测试这些容易打结的地方,都能找到对应的表述和例子。它适合放在手边当参照物,不适合当替代品。需要的时候,按自己的节奏取用就好,希望帮到你。
本文还有配套的精品资源,点击获取