简介:南京信息工程大学编译原理期末试卷(2021—2022学年B卷,任课教师凌妙根)含完整答案解析,以docx文档形式整理呈现。适合正在学习编译原理的计算机专业本科生用于期末复习自测,也可供高校教师参考命题思路与考察方式。试卷系统覆盖编译核心考点,包括词法分析、语法分析、错误处理、非递归预测分析、语法制导翻译、SLR自底向上分析、代码优化以及正则表达式与自动机理论。题型涉及选择题、画图题、计算分析题和综合题,具体考查最左推导与语法分析树绘制、短语与句柄识别、DAG图构建与基本块优化、消除左递归与FIRST/FOLLOW集合构造、预测分析表设计、SLR项集族与分析表构造、NFA确定化和最小化DFA等关键操作。随卷附有答案,便于对照梳理解题思路。资源共1个docx文件,压缩包大小1.11MB,已有1022人学习或浏览,适合考前突击核心知识点、查缺补漏和把握高频考题方向。
1. 这份试卷对复习编译原理到底有多大参考价值
期末复习最怕的不是题难,而是不知道往哪个方向使力。不少同学在考前一周才把编译原理的教材翻出来,面对词法分析、语法分析、中间代码生成、代码优化这些大块内容,往往陷入一种“哪都看过、哪都没底”的状态。这时候,一份带答案的往年试卷就成了稀缺资源——它能直接告诉你命题人关注哪些知识点、题型怎么分布、答案的踩分点在哪里。这里讨论的某高校2021-2022学年编译原理期末试卷(含答案)正是这类资料。它适合正在准备期末考的学生快速圈定复习范围,也适合考研复试想找回专业课手感的人,甚至对刚入职做编译器相关工作的开发者梳理基础知识也有帮助。需要说明的是,本文不涉及具体学校、命题人及试卷原文内容,只从普遍适用的复习方法出发,谈谈如何利用这类试卷资源把编译原理真正学扎实。
先说结论:一份好的期末试卷,价值不在于让你背下几道题,而在于帮你建立“知识地图”。编译原理这门课的特点是概念密集、算法链长,从正则表达式到自动机,从自顶向下分析到自底向上归约,再到语义分析和中间代码,每个环节都是下一环节的铺垫。如果平时没跟上,期末靠刷一两份试卷其实很难补天。但反过来,如果已经跟着课程走了一遍,试卷就是最好的查漏补缺工具——你能迅速发现哪一块是薄弱点,然后有针对性地回去翻教材、做习题。我当年复习时,就是把课程近三年的试卷按知识点做了统计,发现语法分析部分几乎占了40%的分值,这才把复习重心从词法分析移到了LL(1)和LR(1)上,最后成绩比预期高了不少。
不过也要泼一盆冷水:网上流传的试卷质量参差不齐,有的答案错误不少,有的排版混乱、缺页漏题,甚至还有“试卷”和“答案”对不上的情况。所以拿到手之后,先别急着开刷,花十分钟检查一下文档完整度和答案可信度,是值得的。这就像写代码之前先确认依赖版本一样,基础不牢,后面全是翻车现场。接下来,我从复习方法论说起,逐步拆解一份编译原理试卷应该怎么用。 ## 2. 从试卷反推复习重点:编译原理的三大核心模块
2.1 词法分析:正则表达式与自动机的得分点
词法分析在试卷里通常占15到20分,题型集中在正则表达式书写、NFA转DFA、DFA最小化这三类。其中正则表达式书写最容易丢分,因为教材上的例子都比较标准,但考试题往往给出的是自然语言描述,比如“以数字开头、后面跟字母或数字、长度不超过8”这样的约束。很多同学能把基本框架写出来,却漏掉长度限制的编码方式——其实这种题的标准答案往往是把长度约束拆成多个并列分支,或者用单词边界符处理。
NFA转DFA的子集构造法是必考内容,这里有个容易踩的坑:不少人在计算ε-闭包时会把已经加入集合的状态重复处理。我在做模拟项目X时写过一个小工具,用Python实现子集构造法,核心逻辑如下:
def epsilon_closure(states, transitions): # states: 当前状态集合 # transitions: dict, key=(state, symbol), value=set of states # 返回从 states 出发经过任意条 ε 边能到达的所有状态 stack = list(states) closure = set(states) while stack: s = stack.pop() for nxt in transitions.get((s, 'ε'), set()): if nxt not in closure: closure.add(nxt) stack.append(nxt) return closure # 参数说明: # - states 必须是 set 类型,避免重复状态导致死循环 # - transitions 中的 ε 边必须显式列出,不能省略 # - 使用栈/队列进行 BFS/DFS 均可,关键在于 visited 集合记录已访问状态这段代码看起来简单,但考试时手写这个算法很多人会漏掉“新生成的DFA状态也要继续计算闭包”这一步。实际上,子集构造法的核心是一个循环:对每个新生成的DFA状态,计算它在每个输入符号下到达的NFA状态集合的ε-闭包。如果你在草稿纸上画NFA转DFA时发现画出来的DFA状态数比预期的少,大概率就是这一步漏了。
DFA最小化也是高频考点,但分值通常不高,5到8分。它的套路很固定:先划分终态和非终态,然后反复根据输入符号的转移结果细分等价类。这里有一个实用的检查方法——最小化完成后,最少状态数应为1到2个,如果得到3个以上,说明原始DFA可能本来就不够简单或划分过程有误。
2.2 语法分析:LL(1)与LR(1)的必考套路
语法分析是试卷的绝对重点,两道大题加起来往往超过30分。LL(1)分析通常考三件事:计算FIRST集和FOLLOW集、构造预测分析表、判断是否为LL(1)文法。这里的门槛不在计算,而在对定义的理解。FIRST集要记住“看产生式右部第一个符号”,FOLLOW集要记住“看产生式右部中该非终结符后面跟什么”。我见过很多同学算FOLLOW集时忘记“如果A→αB,则把FOLLOW(A)加入FOLLOW(B)”,这个规则在教材上叫“若有产生式A→αBβ,则FOLLOW(B)包含FOLLOW(A)”。背下来不难,但做题时总是丢。
LR(1)分析则要掌握LR(0)项目集族的构造、SLR(1)和LR(1)的区别。考试一般不会让你从头构造一个完整的LR分析表,因为工作量太大,但会给你一个已经构造好的部分表,让你填几个空缺项,或者直接给文法让你判断是SLR(1)还是LR(1)。这里有一条实用判断经验:如果文法在某个状态下同时存在移进和归约冲突,但归约的非终结符的FOLLOW集与移进符号不相交,那么它是SLR(1)文法;如果相交,再看LR(1)的展望符是否能解决冲突。我自己复习时把这三种文法的冲突判定条件整理成了一张对比表,考前过一遍非常管用:
| 文法类型 | 冲突判定条件 | 典型解决手段 |
|---|---|---|
| LL(1) | 预测分析表中每个格子至多一个产生式 | 提取左公因子、消除左递归 |
| SLR(1) | 归约项的FOLLOW集与移进符号不相交 | 使用更精细的展望符 |
| LR(1) | 同一项目集中无移进-归约冲突 | 合并同心项目集得到LALR |
这里要提醒一个容易被忽略的细节:LR(1)项目集族中,每个项目都带展望符,而SLR(1)的展望符是统一取FOLLOW集。所以LR(1)比SLR(1)能力更强,但状态数也多得多。考试如果问“为什么LR(1)分析表比SLR(1)大”,答案就是展望符的精细程度不同。
2.3 语义分析与中间代码生成:三地址码的惯用套路
这部分在试卷里通常占20分左右,考得最多的是给一段赋值语句或条件语句,写出其三地址码序列。很多同学在这里丢分是因为对临时变量的编号不统一,或者对数组元素引用的处理方式不对。实际上,三地址码的生成有固定模板:算术表达式用左右子树的后序遍历生成临时变量;下标变量要单独处理,先计算出地址偏移量;条件语句则要关注跳转指令的标号管理。
例如对赋值语句a[i] = b + c * 2,标准的三地址码序列是:
t1 = c * 2 t2 = b + t1 t3 = i * 4 // 假设每个元素占4字节 t4 = a[t3] // 计算地址并取出数组元素 a[t3] = t2这套模板里有两个关键点:一是临时变量按出现顺序编号,不能跳号;二是数组元素引用必须同时写出地址计算和取值两步。如果你在考场上写出的代码里没有单独计算数组偏移的步骤,多半会被扣分。
中间代码生成还会考布尔表达式的回填技术,尤其是短路计算。题目常给一个包含&&和||的复杂条件,让你写出带标号的跳转指令。这里最容易搞混的是真值出口和假值出口的确定——&&表达式的假出口要回填到第一个失败的地方,||表达式的真出口要回填到第一个成功的地方。用一个简单的例子:if (a > b && c < d) x = 1; else x = 0;,中间代码应该有两个标号,一个对应真分支,一个对应假分支,跳转指令的目标在最外层才能确定,这就是回填的意义。 ## 3. 用试卷做三轮复习:从摸底到仿真到错题归档
3.1 第一轮:不看答案做一遍,统计知识点失分率
拿到试卷后,第一件事不是逐题看答案,而是把它当作一次模拟考试。我建议的做法是:找一段完整的两小时时间,关闭手机和其他资料,严格按照考试节奏做一遍。做完之后不急着对答案,而是先自己评估每道题属于哪个知识模块(词法分析、语法分析、语义分析、代码生成、代码优化、运行时环境等),然后统计每个模块的失分情况。这样做的价值在于:你看的是整体知识结构上的漏洞,而不是单个题目的对错。
举个例子,如果你在词法分析的一道正则表达式题上丢了4分,又在DFA最小化上丢了3分,那说明词法分析模块整体不扎实,需要系统性回顾这一章。但如果你只在一道LR(1)的填表题上丢了分,那可能只是那个具体算法步骤没记住,针对性补一下就行。我通常会把失分率按模块汇总,做一个简单的表格:
| 知识模块 | 试卷分值 | 实际得分 | 失分率 |
|---|---|---|---|
| 词法分析 | 18 | 12 | 33% |
| 语法分析 | 34 | 22 | 35% |
| 语义分析 | 12 | 10 | 17% |
| 中间代码 | 16 | 14 | 12% |
| 代码优化 | 10 | 6 | 40% |
| 运行时环境 | 10 | 8 | 20% |
这个统计做完,复习优先级一目了然。代码优化失分率最高,那就先把公共子表达式删除、死代码消除这几类优化算法重新学一遍;语法分析分值高但失分率也不低,那就必须重点突破。第一轮的产出不是分数,而是这张失分率表。
3.2 第二轮:按模块查漏补缺,逐题吃透答案
第二轮是复习的主体,也是最耗时的阶段。这时候已经知道薄弱模块是哪些,就要回到教材和课堂笔记,把这个模块的完整知识链重新梳理一遍,然后再回头看试卷里对应的题目。这里有个技巧:不要直接看答案,而是自己尝试重新做一遍做错的题,做完后再对照答案,重点比较你的思路和标准答案的差异。很多时候,你的计算结果和答案一样,但推导过程不同,这也值得注意——因为考试是按步骤给分的,过程不合理可能被扣分。
这一轮我强烈建议动手写代码验证算法。比如做LR(1)项目集族的构造题,拿不准时可以用Python写一个小脚本,把文法输入进去,输出项目集族。这并不是为了应付考试,而是帮你建立对算法过程的直觉——当你亲眼看到closure和goto是如何一步步作用的时候,很多记忆性的规则就不再是死记硬背了。类似的,写一个递归下降解析器算表达式,也能加深对自顶向下分析的理解。下面这个递归下降表达式解析器的核心函数,是我当年为了理解LL(1)而写的最小实现:
def parse_expr(tokens): # tokens: list of (type, value),type 包括 'num', 'op', 'lparen', 'rparen' # 文法: expr -> term { + term } # term -> factor { * factor } # factor -> num | ( expr ) pos = 0 def peek(): return tokens[pos] if pos < len(tokens) else ('eof', '') def advance(): nonlocal pos pos += 1 def parse_factor(): nonlocal pos ttype, value = peek() if ttype == 'num': advance() return ('num', value) if ttype == 'lparen': advance() node = parse_expr(tokens) if peek()[0] != 'rparen': raise SyntaxError('expected )') advance() return node raise SyntaxError(f'unexpected token: {value}') def parse_term(): node = parse_factor() while peek()[0] == 'op' and peek()[1] in ('*', '/'): op = peek()[1] advance() rhs = parse_factor() node = ('binop', op, node, rhs) return node def parse_expr(): node = parse_term() while peek()[0] == 'op' and peek()[1] in ('+', '-'): op = peek()[1] advance() rhs = parse_term() node = ('binop', op, node, rhs) return node return parse_expr()这段代码展示了LL(1)的递归下降实现思路:每个非终结符对应一个函数,根据当前token决定走哪条产生式。参数说明:tokens是词法分析器输出的Token流,peek()用于向前看一个Token,advance()消费当前Token。每个函数返回的node是一棵语法树。这个实现里有个关键点:parse_term中的while循环对应文法中的{ * factor }部分,而parse_expr中的while循环对应{ + term }部分。如果你在考试中遇到“写出某文法的递归下降子程序”这类题,套这个模板基本不会走偏。
第二轮结束时,你应当能做到:看见试卷上的任意一道题,不需要思考太久就能说出它考的知识点和标准解法路径。这种“题目-知识点-解法”的映射直觉,比背十套试卷都管用。
3.3 第三轮:重做错题,看答案,压缩成考前速查卡
第三轮是考前一周或两三天做的。此时不再系统复习整本书,而是把第二轮标记出来的错题重新做一遍,重点看是否还在相同的地方犯错。如果一道错题重做还是错,那说明你对该知识点的理解有结构性偏差,需要立即回到教材对应章节再过一遍。如果一次就对了,说明之前的错误只是记忆不牢,现在可以放心了。
我在考前通常会把每套试卷的错题压缩成一页速查卡,正面写知识点,背面写对应的陷阱。比如“FIRST集的陷阱:左递归文法必须先消除左递归再求FIRST”,“LR(1)的陷阱:移进-归约冲突要看展望符”,“三地址码的陷阱:数组元素必须分两步(算地址+取值)”。这些速查卡考前半小时过一遍,比临时翻书效率高得多。 ## 4. 三种典型试卷题型的作答技巧与失分陷阱
4.1 计算型题目:FIRST集、FOLLOW集、预测分析表的规范步骤
FIRST集和FOLLOW集是计算型题目的基础,几乎所有语法分析大题都会用到。FIRST集的计算规则总结起来就四条:终止符的FIRST是自身;非终止符的产生式以终止符开头,则该终止符加入FIRST;产生式以非终止符开头,则把该非终止符的FIRST加入;如果产生式右部能推导出空串,则空串加入FIRST。FOLLOW集计算规则也有四条:开始符号的FOLLOW包含结束符;产生式右部某个非终止符后面紧跟终止符,则该终止符加入FOLLOW;后面紧跟非终止符,则该非终止符的FIRST非空部分加入FOLLOW;产生式形如A→αB或A→αBβ且β可推导出空串,则FOLLOW(A)加入FOLLOW(B)。
这里有一个考试中容易踩坑的地方:求FOLLOW集时,很多人只关注题目给出的文法,忘记了“结束符”也要在FOLLOW集中。开始符号的FOLLOW集默认包含$(或#),这个细节在构造预测分析表时是决定性的——如果少了这个结束符,分析表的最后一列可能全是空白,导致整个表无法使用。
答题时我习惯用表格来整理FIRST和FOLLOW集的计算结果:
| 非终结符 | FIRST集 | FOLLOW集 |
|---|---|---|
| E | { (, id } | { $, ) } |
| E' | { +, ε } | { $, ) } |
| T | { (, id } | { +, $, ) } |
| T' | { *, ε } | { +, $, ) } |
| F | { (, id } | { *, +, $, ) } |
一旦把表列出来,构造预测分析表就是机械操作:每个产生式A→α,对FIRST(α)中的每个终止符a,在M[A,a]填入该产生式;如果α可推导出空串,则对FOLLOW(A)中的每个终止符b,在M[A,b]填入该产生式。如果某个格子需要填入两个产生式,则说明该文法不是LL(1)文法。考试时遇到这种情况不要慌,题目多半是在考你“判断是否为LL(1)”的能力,而不是要你强行构造表。
4.2 证明/构造型题目:判断LR(1)文法的思路与满分书写
LR类题目通常分两种考法:一是给一个文法,问你它是不是SLR(1)、LR(1)或LALR(1),并说明理由;二是给一个自动机或分析表,让你补全或使用它分析某个输入串。第一种考法是很多人的噩梦,因为判断过程需要构造项目集族,工作量大且容易出错。
我的做题步骤是固化的:第一步,写出增广文法,即加上一个新的开始产生式S'→S;第二步,构造LR(0)项目集族,标注每个集合中哪些项目是移进、哪些是归约;第三步,检查是否存在移进-归约或归约-归约冲突;第四步,如果有冲突,计算涉及的非终结符的FOLLOW集,判断能否用SLR(1)解决;第五步,如果SLR(1)不能解决,则构造LR(1)项目集族,看展望符是否能区分冲突。
这里有一个节省时间的技巧:如果文法本身没有左递归,且每个非终结符的产生式右部都以不同的终止符开头,那么它大概率是LL(1)文法,更进一步是SLR(1),你在考场上可以优先判定为SLR(1),然后再快速验证。这个启发式判断不能保证100%正确,但能显著加快做题速度。
作答时,一定要把构造项目集族的过程写出来,不要只写结论“该文法是SLR(1)”。阅卷时看的是你的推理过程,而不是最终的yes/no。我见过太多同学直接在试卷上写“不是”,但没有任何分析步骤,分数只能给一半。
4.3 综合型题目:从语法树到中间代码的完整链条
期末试卷最后一道大题往往是综合题:给一段小程序或一个表达式,要求画出语法树、写出中间代码、再说明如何优化。这类题目分值高,但套路也最固定。首要步骤是把语法树画对——这是后面所有步骤的基础。画语法树时要注意运算符优先级和结合性,乘除优先于加减,赋值是右结合的。
以a = b * c + (d - e) * f为例,完整的答题过程是:
语法树: = / \ a + / \ * * / \ / \ b c - f / \ d e 三地址码: t1 = b * c t2 = d - e t3 = t2 * f t4 = t1 + t3 a = t4这个例子看起来很基础,但综合题的丢分点往往不在大框架,而在细节:一是临时变量的编号是否连贯,二是中间代码的运算顺序是否与语法树一致,三是最后一步赋值是否写清楚了目标变量。还有一个容易被忽视的考点是“优化中间代码”。常见的优化手段包括常量折叠、公共子表达式删除、死代码消除。比如上述代码中如果d和e都是常量5和3,那么t2 = d - e就可以在编译期计算出t2 = 2,这一步就叫常量折叠。如果某段代码是if (a > 0) b = 1; else b = 1;,那么整个if语句可以消除,这就是死代码消除的思想。答题时把优化后的代码写出来,并在旁边注明用了哪种优化技术,能拿到额外的步骤分。
综合题还有一个加分项:如果题目允许,用DAG(有向无环图)来合并公共子表达式。比如a = b * c + d; e = b * c + f;中b * c是公共子表达式,DAG中只会计算一次。画DAG时,每个运算节点对应一个内部节点,相同运算且操作数相同则复用节点。这个方法在代码优化章节一定会考,提前练熟能提高做题速度。 ## 5. 使用试卷资源的四个常见坑与排查方法
5.1 坑一:答案错误率高于预期,盲目信任导致越学越偏
这是使用往年试卷最常见的风险。网上流传的试卷答案大多由学生整理,难免有错漏。有的错误很明显,比如FIRST集算错导致预测分析表填错;有的错误则很隐蔽,比如LR(1)的展望符判断有误,导致整道大题都被带偏。踩坑的表现是:你做某道题时感觉解法不合理,但对应答案却发现“答案就是这么写的”,于是怀疑自己的理解有误,其实答案本身就是错的。
排查方法:找2到3个不同来源的答案对照同一道题。如果两份答案一致,那大概率是对的;如果不一致,就需要回到教材或权威资料(比如经典编译原理教材的习题解答)确认。我自己的习惯是,遇到模棱两可的题,先按自己的理解做一遍,再用工具验证——比如用前面提到的Python脚本计算FIRST集和FOLLOW集,机器算出来的结果比人肉可靠得多。
5.2 坑二:试卷与课程大纲不匹配,白做一套题浪费时间
不同学校甚至同一学校不同老师的编译原理课程,教学重点会差别很大。有的老师偏理论,考大量自动机证明题;有的老师偏实践,考语法制导翻译和中间代码生成。如果拿到的试卷和你正在上的课不匹配,刷完一套题可能完全覆盖不到自己的考点。
排查方法:拿到试卷后,先看标题上标注的学年和课程信息,再看第一道大题的题型,与自己的课堂PPT或老师划的复习重点比对。如果发现考纲差异太大,不要浪费时间去一题一题做,只挑重合的知识点做即可。比如某高校的试卷如果大量考语法制导定义(SDD),而你的课上重点在语法分析算法,那你就只需要做语法分析部分,其他部分果断跳过去。
这里还有一条实际经验:同一个学校同一个老师的试卷,往往在题型结构上保持稳定,但题目内容会逐年变化。你复习时不要只依赖单一学年的一份试卷,最好能收集两三年的做对比,找出命题趋势。如果只拿到一份,就把那一年当成一个样例,不要过度推断。
5.3 坑三:文档本身不完整或乱码,答案页缺失
Word文档类的试卷资源经常出现排版混乱、公式丢失、图片模糊甚至缺页的问题。编译原理试卷里的公式很多,比如FIRST集的集合表达式、产生式中的希腊字母等,一旦Word中嵌入的公式编辑器版本不兼容,打开后可能就是一片乱码。更常见的是表格错位——预测分析表本来应该是一张规整的二维表格,但复制粘贴后行和列完全对不上,根本没法用。
排查方法:打开文档后,先整体滚动一遍,确认试卷页数是否完整(一般期末试卷在4到6页),再检查是否有明显的空白区域或乱码符号。如果预测分析表看起来错位了,可以尝试在阅读模式下打开Word,或者用另存为PDF的方式重新排版。如果文档实在损坏严重,不要硬用,直接换一份资源,否则都是在浪费复习时间。
有一点值得说明:试卷的“含答案”不应成为你选择它的唯一理由。很多情况下,只有试卷没有答案的资源同样有价值——你可以用来做第一轮的摸底测试,做完后再找老师或同学对答案。没有答案不等于没有用,关键是你怎么使用它。
5.4 坑四:过度依赖往年试卷,忽视了平时作业和课堂例题
最后一个坑比较隐蔽,但对成绩影响最大。往年试卷反映的是过去的考点分布,不等于今年的实际考卷。有些内容大纲里写了但往年没考,你怎么知道今年不会突然考一次?最典型的例子是“运行时存储组织”,很多学校的试卷多年不考,但某一年突然出了道大题,导致大量考生措手不及。单纯刷试卷而不看平时的作业题和课堂例题,就会遗漏这些“低频但可能考”的知识点。
排查方法:把老师的PPT目录和教材目录对照一遍,划出所有章节,然后用往年试卷标记出已考知识的范围。未标记的部分不代表安全,而是“机会型考点”。考前至少要把这些机会型考点的基础概念过一遍,不做深入推演,但至少能写得出基本定义和简单例子。这样即使真的考到了,也不至于交白卷。我当年复习时整理过一份“机会考点清单”,考前花了两小时浏览,结果期末试卷最后一题就考了清单里一个“机会型考点”,虽然答得不够深入,但至少拿到了基础分。这件事之后,我每次复习专业课都会留出20%的时间给非高频考点。 ## 6. 把试卷价值最大化:建立自己的编译原理错题本
复习不能止于做几套卷子,最终目的是把知识内化成自己的框架。我强烈建议花半天时间,把做过的试卷按知识点拆解,整理成一个属于自己的错题本。这个错题本不需要多精美,一张张活页纸或一个电子表格都可以。关键在于格式要统一:每页记录一个知识点,顶部写知识点名称和对应题型,中间抄一道最具代表性的错题,底部写自己的错因分析和标准解法。
以“LR(1)冲突判定”为例,错题本的一条记录可能是这样的:
【知识点】LR(1)冲突判定 【错题来源】2021-2022学年期末模拟试卷 第3大题 【题目】判断文法 S→L=R | R; L→*R | id; R→L 是否为SLR(1) 【我的错误】直接判定为SLR(1),没有构造项目集族验证 【错因】省略了关键的构造步骤,凭感觉判断 【正确思路】 1. 写出增广文法:S'→S 2. 构造LR(0)项目集族,发现状态: S→L·=R 与 R→L· 存在移进-归约冲突 3. 计算FOLLOW(R) = { =, $ },与移进符号=相交 4. 交集非空,所以不是SLR(1)文法 5. 需要进一步构造LR(1)项目集族检查展望符这样的记录有两点价值:一是你在写下它的时候,已经做了一次完整的复盘,比单纯看答案理解深刻得多;二是考前复习时,你不需要翻整套试卷,只翻错题本就能快速回忆所有易错点。这个错题本越看越薄,考前两小时过一遍,效果远好于从头到尾翻教材。
另外想跟你分享一个我自己的习惯:每整理完一个知识点的错题记录,我会在底部尝试自己编一道类似题目,写完后再回头用正确解法验算一遍。如果编题时发现“自己不知道该怎么出题”,那说明对知识点还没吃透——真正理解了才能出题,出题比做题更能暴露漏洞。这个习惯帮我发现过不少自以为懂了但实际理解有偏差的地方。比如我以为自己掌握了FOLLOW集的计算,但编题时才发现自己从没认真考虑过“产生式右部有两个相同非终结符时该怎么处理”这种情况,回去翻教材补了一课才彻底明白。
最后想对你说:一份往年试卷只是工具,工具再好也只能帮你发现漏洞,不能替你填补漏洞。真正让成绩发生变化的,是你花在错题分析上的时间,是你在纸上一步一步画项目集族的耐心,是你反复默写三地址码模板的熟练度。希望上面的拆解法能帮到你,祝期末顺利。
本文还有配套的精品资源,点击获取