← 12套面试训练

LOOP 04 / INTERVIEW LOOP / 4H

严格解析与失败语义:一场小型 G0 练习

系统接口收到一个十进制长度字符串。面试官故意给看似正常的前缀和越界值,观察你是否只处理 happy path。本场可作为 G0 的练习材料,但不是自动验收。

完成单元 33 · 独立测试、构建模式与调试及其先备后安排本次训练。不绑定日历周。

先写自己的答案,再展开参考。这里按技能编写问题,不声称公司真题;自评与阅读都不会自动通过 G0。

先备与学习位置

回到对应的路线里程碑 →

TIME WITH OUTPUTS

240 分钟怎样用

  1. 闭卷恢复先备 · 15min

    解释 string_view 的借用期限、optional 的两种状态、编译错误与链接错误;说出 Debug/Release 必须都执行的检查。

    留下:先不查章节,写三条判断和一个不确定点;再只补读相关章节的解释段。

  2. 澄清题目与手算 · 25min

    读主问题,逐条写输入、输出、范围与失败行为。手算前两个公开用例,给自己的方案找一个反例。

    留下:一份接口合同、逐步状态表和最小反例;不要先打开参考推演。

  3. 独立实现或设计 · 55min

    实现 parse_count(std::string_view text),返回 std::optional<int>。只接受完整的、非空的 ASCII 数字串,数值在 0..100;不允许符号、空白或尾随字符。允许前导零。先用字符检查约束语法,再用 from_chars 并检查 ec 和指针到达末尾。

    留下:保存个人代码或设计稿。编码题保留编译命令;设计题为每个事件编号,不能只画没有状态的箭头。

  4. 边界与反证 · 25min

    用题目的全部公开用例核对真实输出;另外创造一个与公开输入不同的边界。发现失败时缩小输入,再解释修复。

    留下:实际结果、原始失败和修复原因各一份;设计题记录一个被拒绝的执行顺序。

  5. 按表现进入追问树 · 35min

    从 n1 开始。每题先录下自己的回答,再展开标准;按满足或未满足条件跳转。树最多走一轮,卡住时把剩余时间用于分支中的纠错,不循环加时。

    留下:记录经过的节点、原话、缺失条件和修订;只会复述标准的节点仍标记待重做。

  6. 英文口述与打断 · 30min

    用本页英文提纲录制两轮 90 秒回答;第二轮在 30 秒处自问追问,先回答追问再回到主线。每轮回听并改写两个含糊句。

    留下:两轮录音或逐字稿;圈出输入、因果、边界和限制各一句。参考英文在录完第一轮后再读。

  7. 复盘与安排重做 · 25min

    对照强弱答案,选择一个真正出错的环节:合同、状态、实现、验证或表达。填本页记录模板,并约定下一天的 30 分钟。

    留下:一个有失败输入的错误记录和一个可观察修复标准;不要把全部问题归因为粗心。

  8. 次日无答案重做 · 30min

    次日改变合同:只接受 1..20,仍允许前导零。关闭原答案,重新写函数并测试 "00"、"01"、"20"、"21"、"1 "、"1x"。

    留下:这是本周 240 分钟中的最后 30 分钟,不另加预算。先关闭解答,用 20 分钟独立做,再用 10 分钟核验并记录是否仍需复习。

包括次日重做,总计 240min。局部错因复盘属于本次练习,额外的计划复盘按实际需要另记。

SOLVE BEFORE READING THE ANSWER

先独立处理这个问题

实现 parse_count(std::string_view text),返回 std::optional<int>。只接受完整的、非空的 ASCII 数字串,数值在 0..100;不允许符号、空白或尾随字符。允许前导零。先用字符检查约束语法,再用 from_chars 并检查 ec 和指针到达末尾。

输入与输出合同

  • 有效 0 必须与失败区分;返回 nullopt 表示失败。
  • 传入的 string_view 仅在调用期间借用;不能保存返回给以后使用。
  • 不调用会自动跳过空格的宽松转换来替代本合同。
手算之后,对照公开用例
输入或情形预期为什么
"007"有值 7允许前导零。
"0"有值 00 不是失败哨兵。
"100"有值 100包含上界。
"101" / "" / "-1" / "+2"均无值范围、空串和符号分别被拒绝。
" 2" / "2 " / "2x"均无值必须严格匹配完整输入。
"999999999999999999999999"无值转换越界应显式失败,不绕回。

先保留自己的解法、状态轨迹与验证记录,再打开参考。允许用自然语言或伪代码补充解释;不能用参考输出代替真实运行。

保存独立尝试后,阅读解法与状态轨迹

解法依据

先拒绝空串,逐字符要求 0..9。设置一个 int 接收值,用 from_chars 解析;若错误码非零或返回指针未到输入末尾则失败。最后检查不超过 100;所有条件通过才返回数值。测试应检查 optional 是否有值,再比较里面的值,避免把 nullopt 与 0 混在一起。

逐步推演

"007":三个字符都合法,转换产生 7,指针到末尾,范围通过。"2x":字符检查在 x 处拒绝。超长数字字符合法,但 from_chars 报越界;不能读取一个假定成功的结果。"0":合法数字,返回 engaged optional,其值为 0。

FOLLOW THE ANSWER, NOT A SCRIPT

从回答进入下一层追问

n1 开始。先录下回答,再展开判定;达到条件就走深入分支,未达到就按反馈缩小问题。一次最多走一轮,不靠反复查看同一答案累积“通过”。

把实际走过的节点记入模板 →

NODE n1

如果只检查 from_chars 的 ec 而忽略末尾指针,会漏掉什么?

我已作答:查看判定与下一分支

需要解释清楚:一般的前缀解析会让 "2x" 的数字部分成功;本题额外字符检查已拒绝它,但完整消费仍应作为解析合同的独立检查。

达到

结论正确,并解释本节点给出的具体状态或反例。

保留关键推理:一般的前缀解析会让 "2x" 的数字部分成功;本题额外字符检查已拒绝它,但完整消费仍应作为解析合同的独立检查。

继续到 n2 →

待补

只报术语、漏掉条件,或不能解释题中的数值。

去掉字符预扫作纸上反例,比较 "2" 和 "2x" 的消费位置。

继续到 r1 →

NODE r1

把第一个追问缩到最小输入,重新逐步说明。

我已作答:查看判定与下一分支

需要解释清楚:一般的前缀解析会让 "2x" 的数字部分成功;本题额外字符检查已拒绝它,但完整消费仍应作为解析合同的独立检查。

修复后达到

用具体输入改正原回答,能指出之前错在哪里。

去掉字符预扫作纸上反例,比较 "2" 和 "2x" 的消费位置。

继续到 n2 →

仍未达到

仍依赖答案复述,不能独立重建状态。

本次树到此结束;把 n1 的输入和缺口写入复盘,再进入英文练习与次日重做。

这一分支结束:对照并复盘 →

NODE n2

为什么 optional 的 if 判断不能改成 if(*value) 来区分成功?

我已作答:查看判定与下一分支

需要解释清楚:必须先判断是否有值;合法 0 的布尔转换是 false,解引用空 optional 也不满足前提。

达到

结论正确,并解释本节点给出的具体状态或反例。

保留关键推理:必须先判断是否有值;合法 0 的布尔转换是 false,解引用空 optional 也不满足前提。

继续到 n3 →

待补

只报术语、漏掉条件,或不能解释题中的数值。

分别画 nullopt 与 optional{0} 两种状态,再给各自测试。

继续到 n3 →

NODE n3

Debug 成功、Release 失败,你第一步会查什么?

我已作答:查看判定与下一分支

需要解释清楚:保存相同输入和命令,查未初始化/越界/生命周期以及依赖 assert 的逻辑;用可复现最小例子和动态检查定位,不先指责优化器。

达到

结论正确,并解释本节点给出的具体状态或反例。

保留关键推理:保存相同输入和命令,查未初始化/越界/生命周期以及依赖 assert 的逻辑;用可复现最小例子和动态检查定位,不先指责优化器。

这一分支结束:对照并复盘 →

待补

只报术语、漏掉条件,或不能解释题中的数值。

缩小到一个失败输入,检查所有状态初始化和始终执行的验证,再比较构建条件。

这一分支结束:对照并复盘 →

答案强在哪里,弱在哪里

保存自己的回答后,打开对照

弱答案

“用 atoi,失败时给 0;我试了 7 能输出 7。”

强答案

“0 是合法长度,所以我用 optional 区分失败。语法检查拒绝符号和空白,转换必须消费全部字符串且没有错误,最后才检查范围。我分别测空串、尾随字符和溢出。”

强答案把词法、数值转换和业务范围分开,测试覆盖不同失败机制。只展示一次运行不能说明接口严格,更不能替代 sanitizer 与陌生题验收。

在自己的原回答里划出一个缺失的条件或错误推理,再重说一遍。完整句子背熟,不代表能处理新约束。

ANSWER, THEN HANDLE AN INTERRUPTION

英文口述与打断

Describe a parsing bug and how your contract prevents it.

  1. Separate syntax from range.
  2. Explain valid zero versus failure.
  3. Name three independent negative tests.

“Why do you check the end pointer if the error code says success?”

录完第一轮后,读英文示范
The parser accepts a complete decimal string from zero to one hundred. I separate syntax validation, conversion errors, and the final range check. An optional distinguishes a valid zero from failure. I test an empty string, a trailing character, and a value too large for the target integer type.
  • 前 15 秒说明输入、输出和一个关键约定。
  • 至少用一个本题的数值解释因果,不只罗列英文术语。
  • 明确一个边界或尚未验证的限制;不能把教学推演说成项目经验。

次日关掉解答,换一个问题

次日改变合同:只接受 1..20,仍允许前导零。关闭原答案,重新写函数并测试 "00"、"01"、"20"、"21"、"1 "、"1x"。

独立重做后核对

"00" 无值;"01" 有值 1;"20" 有值 20;其余无值。注意新下界改变了合法 0,尾随换行仍是非法字符。

  • 关闭主问题答案并使用新输入独立完成。
  • 给出结果与原因;失败时记录最小反例,不能只把完成标记改成通过。

重做的 30min 已计入本套4h;需要更多补课时记录实际用时,按缺口顺延。

记录实际回答与证据

本次面试练习模板
# W04 算法 / 英文训练记录(仅个人练习,不是能力认证)
日期:
本次先备与尚不确定点:
主问题接口合同:
我最初的方案与状态表:
运行命令或设计事件编号:
失败输入 / 预期 / 实际:
修复与理由:
追问路径(节点 → 自己原话 → 缺口):
英文第一轮两处含糊句:
英文第二轮修订:
次日重做日期(30 分钟已含本周预算):
重做输入 / 实际结果 / 解释:
仍需补练:

本次练习的检查依据

公开正反用例一致,英文能解释失败合同;关键所有权/生命周期不能靠总分补偿。G0 仍需个人独立编码、既定构建与口述的真实验收。

模板在你的个人笔记中填写。网页只提供空模板;不会把这次训练写成项目经验或学习验收结果。