程序设计语言专题 Programming Language · 编译解释 · 正规式 · 后缀式 · 传值传址

软考 · 软件设计师 | 上午约 6 分(2024 上 Q10–15 一整条都在这)
你错过的:Q10 Python 异常、Q11 列表 +、Q12 后缀式、Q15 解释器哪句是错的。正规式 Q13/Q14 当时对了,这页仍把算式拆开,避免再混。
⏱ 考前 10 分钟速览
① 编译 vs 解释:编译一次变成机器码,跑得快;解释边译边跑,慢。Java/Python 常先变成字节码再解释。问「错误」:说解释器比编译链接出的机器码效率更高 → 这句话反了。
② 编译六步:词法(切单词)→ 语法(搭树)→ 语义(类型对不对)→ 中间代码 → 优化 → 目标代码。词法用正规式/自动机;语法用上下文无关文法。
③ 正规式:|=或,ab=先 a 再 b,*=前面那团 0 次或多次,()打包。字符种类=式子里出现过的不同字母/数字各算一个。
④ 后缀式:运算符写在两个操作数后面。括号先算完;* / 比 + - 紧。2024:b*(a+c)-d → bac+*d-。
⑤ 传值 / 传址:传值=给副本,函数里改了外面不知道;传址=给门牌号,里面改外面跟着变。
⑥ Python:raise 手动抛异常;finally 有 except 也照跑;没有传统 switch。列表+列表=拼接,不是相加、也不会报错。
目录: ⚡ 今早先看 · ① 编译 / 解释 · ② 编译六步 · ③ 正规式 · ④ 中缀 → 后缀 · ⑤ 传值 / 传址 · ⑥ 文法 · 自动机 · ⑦ Python 小题 · 真题索引 · 速记口诀

⚡ 今早先看 · 对照表

看见题干闭眼选
解释器比编译出的机器码效率更高这句错(解释更慢)
词法分析依据什么正规式 / 有限自动机
语法分析依据什么上下文无关文法
正规集「字符种类」式子里出现过的不同字符个数(ab 是 a 和 b 两个)
(ab|c)(1|2|3) 能匹配谁前半 ab 或 c,后半 1/2/3 → 如 ab2,不是 abc、不是 a2
b*(a+c)-d 后缀bac+*d-(括号里的 + 先贴在 ac 后面)
改形参、实参跟着变传址 / 引用传递
Python y = [1,2,3]+[4,5,6][1,2,3,4,5,6] 拼接
Python 手动抛异常raise

① 编译、解释、字节码 谁快谁慢

源程序是给人看的(a = b + 1)。CPU 只认机器码。中间这座翻译桥有两种走法:

编译解释
怎么干先整份译成机器码(还常再链接成可执行文件),然后 CPU 直接跑不产出完整机器码,翻译程序拿着源程序边看边执行
速度跑得快(翻译只做一次)跑得慢(每次执行都要再译)
改一行常常要重新编译改完立刻再跑,调试方便
典型C、C++早期 BASIC;命令行脚本

还有第三条路,Java / Python / C# 常用:先编译成中间的字节码,再由虚拟机解释(或即时编译 JIT)。所以「解释器可以直接啃源程序」对,「也可以先变成字节码再解释」也对。

🎯 比较对象要看清楚:跟「编译+链接得到的机器码」比,解释执行一定更慢、效率更低。出题人把「更慢」改成「效率更高」,整句就错了。

练一练 · 2024上 · Q15(空白卷 OCR · 你选了 B,答案是找「错误的」)

Q15 解释器 · 错误的是
以下关于通过解释器运行程序的叙述中,错误的是(15)。
A. 可以由解释器直接分析并执行高级语言源程序代码
B. 与直接运行编译后的机器码相比,通过解释器运行程序的速度更慢
C. 解释器运行程序比运行编译和链接方式产生的机器代码效率更高
D. 可以先将高级语言程序转换为字节码,再由解释器运行字节码
答案 C。 题干要的是错的那句。A 对(纯解释);B 对(就是「更慢」);D 对(Java/Python 那条路)。C 把「更慢」说成「效率更高」,反了。
你当时选 B:B 其实是正确叙述,不是「错误的是」。

② 编译器六个车间 从源程序到机器码

编译不是一锅炖。源程序进厂,依次过六个车间。前三个负责看懂,后三个负责生成代码。

步车间人话依据 / 产物
1词法分析把字符流切成「单词」:关键字 if、名字 score、数字 95、符号 +依据正规式(3 型文法),用有限自动机;产出单词流
2语法分析检查单词能不能排成合法句子,搭出语法树。例如 if 后面该跟条件依据上下文无关文法(2 型);产出语法树 / 分析树
3语义分析句子合法,意思对不对?类型匹不匹配、变量声明过没有类型检查、符号表
4中间代码生成先译成一种跟具体 CPU 无关的中间表示,方便后面优化、换机器三地址码等
5代码优化删废话、把循环算快一点,不改变程序意思更短 / 更快的中间码
6目标代码生成变成某一种 CPU 的汇编 / 机器码还要再链接上库,才是可执行文件
习惯分法含哪几步
前端(分析部分,跟源语言有关)词法 + 语法 + 语义(有的书把中间代码也算前端)
后端(综合部分,跟目标机器有关)优化 + 目标代码
🎯 口诀:词法切词、语法搭树、语义查对错、中间过渡、优化减肥、目标落地。 问「扫描源程序识别单词」→ 词法;问「形成语法树」→ 语法。
⚠️ 词法用正规式,语法用上下文无关——这两对千万别对调。

③ 正规式 / 正规集 词法分析的配方

正规式是一张「字符串长什么样」的配方。它描述的那一堆合法字符串,叫正规集。词法分析就靠它认单词。

3.1 三个符号,先认人

写法名字人话例子
a|b或左边这个、或右边那个,二选一1|2|3 能写出 1,或 2,或 3
ab连接(中间那一点常省略)先写完左边,紧接着写右边ab 是字母 a 后面立刻跟 b,不是「a 或 b」
a*闭包前面那一团可以出现 0 次、1 次、很多次ab* = a、ab、abb、abbb…(b 可没有)
(…)打包括号里先当成一个整体,再跟外面的 | / 连接 / * 算(ab)* 是 ab、abab、ababab… 和 ab* 不是一回事
🎯 ab 是两个字符连着出现;问「字符种类」时,a 和 b 要分开数,不能把 ab 当成一种字符。

3.2 2024 那道:(ab|c)(1|2|3) 拆开看

这是两大段连接。前半必须先匹配完,后半再跟上,中间不能穿插。

段式子只能是这些
前半ab|c字符串 ab,或者 字符串 c。没有单独的 a,也没有 abc
后半1|2|3字符 1 或 2 或 3

所以正规集里一共就这 6 个串:ab1 ab2 ab3 c1 c2 c3。

字符种类问的是:式子里出现过哪些不同的字?前半用到 a、b、c,后半用到 1、2、3 → 6 种。不是 2 种(两段),也不是 3 种(只数了数字)。

选项串能不能被这套正规式收下原因
ab2能前半 ab,后半 2
abc不能前半若取 ab,后半必须是 1/2/3,不能是 c
a2不能前半没有「单独一个 a」这条路
123不能前半不是 1;整个串也不在那 6 个里

练一练 · 2024上 · Q13、Q14(空白卷 OCR)

Q13 正规集 · 字符种类
正规集 (ab|c)(1|2|3),可以识别的字符种类有(13)个。
A. 1  B. 2  C. 3  D. 6
答案 D。 出现过的字符:a、b、c、1、2、3,共 6。别把 ab 算成一种,也别只数两段。
Q14 正规集 · 谁能匹配
正规集 (ab|c)(1|2|3),下列(14)可被匹配。
A. ab2
B. abc
C. a2
D. 123
答案 A。 合法只有 ab1/ab2/ab3/c1/c2/c3。B 后半变成了 c;C 前半只写了 a;D 两段都不对。

④ 中缀式变成后缀式 运算符写到后面

我们平时写的 b*(a+c)-d 叫中缀:运算符夹在两个数中间。计算机更爱后缀(逆波兰):两个数写完,运算符贴在屁股后面,这样就不再需要括号。

写法例子(b 乘 (a+c) 再减 d)
中缀(人写的)b * (a + c) - d
后缀(机器爱的)b a c + * d - 连写 bac+*d-
前缀(运算符在最前)- * b + a c d 上午较少单独考

4.1 纸上怎么搬(不用背栈代码,按运算顺序贴)

规则就三条:

规则
1字母、数字按出现顺序原样抄到答案里,一个都不许重排成 c 在 a 前面这种
2哪个运算先算完,它的运算符就早一点贴到已经抄出来的那两个操作数后面
3优先级:括号里的最先;* / 比 + - 紧;同样优先级从左往右

拿 b*(a+c)-d 走一遍:

步先算哪一块这一块的后缀整式目前变成
①括号里 a+c 最先a 和 c 抄下来,+ 贴后面 → ac+b * (ac+) - d
②接着是乘法 b*(ac+)b 在前,后面跟上刚才那坨,* 再贴尾 → bac+*(bac+*) - d
③最后减法左边整坨、右边 d,- 贴最尾 → bac+*d-完成
🎯 验算口诀:后缀从左往右读,遇见运算符就吃掉它前面最近的两个结果。
bac+*d-:先 ac+ 得到 (a+c);再被 b 和 * 吃掉 → b*(a+c);再和 d 做 - → b*(a+c)-d。还原回去和原式一样,就对了。
⚠️ 你当时选的 bacd+*-:等于先算 c+d,再拿去和 a 乘、和 b 乘——括号已经没了,顺序全乱。选项里 bac+d*- 则是乘法一直乘到 d,少了最后那个单独的减。

练一练 · 2024上 · Q12(空白卷 OCR · 你选了 B)

Q12 中缀转后缀
算术表达式 b*(a+c)-d 的后缀式是(12)。(+、−、* 表示算术的加、减、乘运算,运算符的优先级和结合性遵循惯例)
A. ba+cd*-
B. bacd+*-
C. bac+d*-
D. bac+*d-
答案 D。 括号里 a+c → ac+;再乘 b → bac+*;再减 d → bac+*d-。
A 变成 (b+a)*(c-d);B 变成 b*(a*(c+d)) 再减什么,括号乱了;C 是 (b*(a+c))*d 再减空。

再手热一个:(a+b)*c → ab+c*;a+b*c(没有括号,先乘)→ abc*+。这两串差一个顺序,最爱拿来挖坑。

⑤ 传值调用 vs 传址调用 函数参数怎么递进去

调用函数时,外面的变量叫实参,函数括号里接住的叫形参。递法只有两种常考:

传值(值传递)传址(引用传递)
递进去的是实参的复印件实参的门牌号(地址)
函数里改形参只改复印件,外面的实参不变顺着门牌号改原件,实参跟着变
形参能把结果带回来吗不能(要结果得靠 return)能
典型C 里普通 int;Java 基本类型C 里指针 *、数组名;C++ 引用 &

想交换两个整数 x、y:只传值,函数里怎么倒腾,外面还是原样;必须传址(或传指针),外面才会真的对调。

🎯 题眼:「改变形参,实参相应改变」= 传址;「形参的改变不影响实参」= 传值。C 的数组作参数,传的是首地址,属于传址。

递归函数每次调用把自己的局部变量压进栈,一层层叠,返回再一层层弹。问「递归靠什么实现」→ 栈。

⑥ 文法与自动机(够用的几句)

文法别名对应什么编译里谁用
3 型正规文法正规式 = 有限自动机词法分析
2 型上下文无关文法下推自动机语法分析
1 型上下文有关—上午很少算
0 型短语结构图灵机最强、上午不展开
NFA 不确定有限自动机DFA 确定有限自动机
读一个字符下一步可能有好几条路,还可以有 ε(空边)最多一条路,没有空边
能力两者识别的语言一样(都能描述正规集),DFA 好实现

正规式 → 先画 NFA → 再确定化成 DFA。上午一般只问「词法分析用有限自动机 / 正规式」,不必现场做子集构造。

语法树里:句柄 = 最左的那个直接短语(规约时先收它)。见到选项能认名字即可。

作用域两句:静态(词法)作用域 = 看变量写在哪一层(C / Java / Python);动态作用域 = 看谁调用的。多数题「C 语言」闭眼选静态。

⑦ Python 上午就这几句

不是让你当 Python 工程师,是认对错。

点对的说法错的说法
抛异常用 raise 手动抛—
try / except / finallyfinally 几乎总会执行(有 except 也跑、return 之前也跑)「有了 except 就不必执行 finally」
except Exception能抓住一般错误「能捕获所有异常」—— SystemExit / KeyboardInterrupt 属于 BaseException,漏在 Exception 外面
选择结构if / elif / else;3.10 才有 match「可以用 switch…case」(软考按没有传统 switch 来考)
列表 +[1,2,3]+[4,5,6] → 拼接成 [1,2,3,4,5,6]报错;或以为对应位置相加成 [5,7,9];或以为嵌成 [1,2,3,[4,5,6]](那是把一个列表 append 进去)

练一练 · 2024上 · Q10、Q11(空白卷 OCR · 你错过)

Q10 Python 异常
关于 Python,下列说法正确的是(10)。
A. 用 try 捕获异常,有 except,无需执行 finally
B. 可以使用 raise 关键字来手动抛出异常
C. except Exception 可以捕获所有异常
D. 可以用 switch…case 语句表示选择结构
答案 B。 A:finally 照样跑。C:捕获不了所有(漏了 BaseException 那一支)。D:软考认定没有传统 switch。只剩 B。
你当时选 D,把「错误说法」当成了正确答案。
Q11 Python 列表 +
执行以下 Python 语句之后,列表 y 为(11)。
x=[1,2,3]
y=x+[4,5,6]
A. 出错
B. [1,2,3,4,5,6]
C. [5,7,9]
D. [1,2,3,[4,5,6]]
答案 B。 两个 list 用 + 就是首尾拼接。C 是对应元素相加(NumPy 才常这样,普通 list 不是);D 是把第二个列表当成一个元素塞进去;A 不报错。
你当时选 A。

真题按年索引

2024上 Q10 Python 异常 · Q11 列表拼接 · Q12 后缀式 · Q13 正规集种类 · Q14 正规集匹配 · Q15 解释器错误项

Q10–Q15 题干来自 2024 上空白卷 OCR。答案按考点与你当时的对错记录核对。
本专题速记总收
① 解释比编译出的机器码慢;也可以源码直接解释,或先字节码再解释。
② 词法切单词(正规式/自动机)→ 语法搭树(上下文无关)→ 语义查类型 → 中间码 → 优化 → 目标码。
③ | 或、连接、 * 闭包。(ab|c)(1|2|3) 合法串 6 个;字符种类也是 6。
④ 后缀:先抄操作数,谁先算完谁的运算符先贴。 b*(a+c)-d = bac+*d-。
⑤ 传值改不了实参;传址能改。递归靠栈。
⑥ Python:raise 抛异常;finally 必跑;无 switch;list+list=拼接。