编译原理实验:C++词法分析器从字符流到二元式的实现
简介词法分析是编译原理的基础环节其核心任务是将源程序的字符流转换为具备语义的二元式序列为后续语法分析提供输入。有限状态机是词法分析器实现的主流模型通过状态转移识别标识符、关键字、数字和运算符等单词类型。在实际工程中词法分析器还需处理非法字符、注释未闭合等异常场景并具备稳定的错误恢复能力。C语言因其高效的字符处理能力常被选作教学和工程实践的实现语言。本文从字符集定义、状态机设计、错误检测分支等角度剖析一个可运行的C词法分析器如何将源文件逐字扫描并输出二元式并给出实操中的调试经验与回归测试思路适合正在学习编译原理或需要复习文本扫描技术的开发者参考。1. 编译原理词法分析器一个 cpp 怎么完成从字符流到二元式编译原理课的第一个动手实验通常就是写词法分析器。我这次拆的这份压缩包核心只有一个“编译原理词法分析器 实验一.cpp”。跑起来是控制台交互先输入测试程序文件名程序自动完成整份源文件的扫描输出每个单词的二元式序列同时能认出三种词法错误——非法字符、字符常数缺右单引号、注释缺右侧界符。这个资源最值钱的地方不是“跑通”本身而是错误检测分支的写法。很多同学的代码能把正常文件分析完一到错误测试用例就崩或死循环。这里适合两类人正在做编译原理实验一的在校生以及想复习有限状态机在文本扫描里怎么落地的开发者。接下来按输出格式、状态机、错误分支、实测踩坑的顺序拆开。2. 先定二元式输出与 SAMPLE 字符集分析器的接口契约开发词法分析器的第一步不是写扫描循环而是先把输出格式定死。二元式序列长什么样直接决定了内部状态机的数据结构和结束判定方式。这一章先把“接口”对齐后面写代码才不返工。2.1 二元式序列长什么样二元式的通用形式是类别码, 单词值类别码用整数编号单词值是从源文件中抽取出来的具体字符串或数值文本。常见的做法是把 int、if、while 等关键字分别编成不同类别码标识符整体编一个类别码整数常数编一个类别码运算符和界符再各自编码。拿到这份源码后第一步要做的就是在 cpp 里找到这张编号表确认老师要求的编号和源码里的查表逻辑一致否则输出格式对不上后面全是白跑。我按常见的实验要求给一张编号表做参考类别类别码说明int/float/while 等关键字1、2、3…每个关键字一个独立码顺序自定标识符20字母或下划线开头的连续字母数字串整数常数21连续数字串运算符40~49 - * / ! 等界符50~55( ) { } [ ] , ;这张表不是标准不同学校差异很大。源码里如果已经有宏定义就以源码为准。一个简单的测试文件int sum 0; while (sum 100) { sum sum 1; }对应的输出是每行一个二元式(1, int) (20, sum) (40, ) (21, 0) (3, while) ...这里有一个重要认知输出顺序必须和源文件从左到右的单词出现顺序完全一致包括换行也不能打乱。如果哪一行输出顺序不对多半不是打印逻辑问题而是状态机在某个分支提前消费了字符。2.2 SAMPLE 字符集合法字符边界先列出来实验说明里提到的“SAMPLE 字符集”指允许出现在测试程序源文件里的字符全集。词法分析器每读一个字符第一件事是判断它在不在这个集合里不在就直接走非法字符错误分支。我一般会把字符集拆成三类字母数字一类运算符和界符一类空白一类。而且要把单引号、双引号、斜杠星号单独对待因为它们分别是字符常数、字符串常量、注释的定界符状态机要特殊处理不能和普通运算符混在一起。给一个参考实现bool isAlphaNum(char ch) { return (ch a ch z) || (ch A ch Z) || (ch 0 ch 9); } bool isOpOrDelim(char ch) { const char* opChars -*/(){}[],;|!:; for (int i 0; opChars[i] ! \0; i) { if (ch opChars[i]) return true; } return false; } bool isLegalChar(char ch) { return isAlphaNum(ch) || isOpOrDelim(ch) || ch || ch \n || ch \t || ch \r; }这里有一个常见坑isLegalChar 把 \r 和 \n 同时算作合法空白但行号统计依赖 \n 作为行结束标志。Windows 平台打开测试程序时每行结尾是 \r\n 两个字符如果不做预处理就会把 \r 当成一个“合法”字符吞进去行号列号全乱。我的习惯是打开文件后统一把 \r 过滤掉让状态机里只看到 \n。参数说明isAlphaNum 负责字母和数字isOpOrDelim 负责运算符和界符isLegalChar 是总入口。把这三个函数分开写是因为后面标识符、数字、运算符的识别各自还要复用它们分离后状态机里不用重复写字符范围判断。2.3 主控流程文件名输入与逐字符扫描框架主程序流程分为三步提示输入文件名、以二进制方式打开、进入逐字符扫描循环。用二进制方式打开保留 \r\n 原样然后扫描时统一映射成 \n这样行号计算不受平台干扰。#include cstdio #include cstring #include cstdlib int main() { char fileName[128]; printf(请输入测试程序名: ); scanf(%s, fileName); FILE* fp fopen(fileName, rb); if (!fp) { printf(无法打开文件 %s\n, fileName); return 1; } int line 1, col 1; char ch; while ((ch fgetc(fp)) ! EOF) { if (ch \r) continue; // 统一过滤 \r if (ch \n) { line; col 1; continue; } // 这里调用状态机处理当前字符 processChar(ch, line, col); col; } // 循环结束检查是否有未闭合的注释或字符常数 checkUnclosedState(); fclose(fp); return 0; }这段的逻辑是逐个字符喂给状态机而不是按行读入。状态机天然没有“跨行”感知问题注释、字符常数这类不能跨行的结构在遇到 \n 时可以直接判断报错。line 和 col 在循环里维护状态机报错时能拿到准确的出错位置。参数说明processChar 是后续状态机的统一入口传 ch 和当前行列checkUnclosedState 必须存在否则 EOF 时还在注释里的缺陷测例不会报错。注意 fgetc 返回的是 int用 char 接收时对中文或多字节字符会截断但这个实验按字符集限定单字节 ASCII 足够。3. 状态机实现标识符、数字和运算符是怎么被“认出”的把字符流变成二元式核心是有限状态机。不用正则库不用现成词法生成器是因为这类课程实验考核的就是对状态转换图的理解。状态机的状态划分按单词种类走初始态、标识符态、数字态、运算符态、字符常数态、注释态。3.1 状态划分与转移条件状态转移条件本质上就是字符类型看到字母进 ST_ID看到数字进 ST_NUM看到运算符进 ST_OP看到单引号进 ST_CHAR看到 / 且下一个字符是 * 进 ST_COMMENT。如果是注释则整体丢弃不生成二元式。enum LexState { ST_START, ST_ID, ST_NUM, ST_OP, ST_CHAR, ST_COMMENT };用一张表把核心转移说清楚当前状态读到字母读到数字读到普通运算符读到空格/换行读到引号或斜杠ST_START进入 ST_ID进入 ST_NUM进入 ST_OP忽略进入 ST_CHAR/ST_COMMENTST_ID继续收集继续收集结束当前词并重新处理结束当前词同上ST_NUM按非法字符处理继续收集结束当前词并重新处理结束当前词报非法字符关键在“结束当前词并重新处理”。实现时最容易出错的地方在 ST_ID 里读到一个运算符这个运算符本身是下一个单词的开头不能丢掉。惯用做法是把当前字符 ungetc 回去或者把扫描循环设计成“当前字符已经读进来了状态机处理完再决定消费不消费”。我一般用 peek 变量来代替 ungetc跟踪起来更直观。3.2 标识符识别与关键字查表标识符规则是以字母或下划线开头后面跟字母、数字或下划线。识别完成后先查关键字表命中就按关键字类别码输出没命中按标识符输出。const char* keywords[] { int, float, if, else, while, return, void }; int lookupKeyword(const char* token) { for (int i 0; i sizeof(keywords) / sizeof(char*); i) { if (strcmp(keywords[i], token) 0) { return i 1; // 类别码从1开始 } } return -1; }参数说明类别码用 i1 计算意味着关键字表里第一个 int 对应类别码 1第二个 float 对应 2依次类推。如果你的实验要求里另有编号规则就把返回值改成查表后的映射核心逻辑不变。token 收集要注意长度上限。我一般设 256 字节的缓冲区每收集一个字符检查长度超过限制就截断并继续扫描避免缓冲区溢出。这种限制合理测试程序的标识符不太可能超过 256。char token[256]; int tokenLen 0; void processChar(char ch, int line, int col) { if (state ST_ID) { if (isAlphaNum(ch) || ch _) { if (tokenLen 255) token[tokenLen] ch; } else { token[tokenLen] \0; int code lookupKeyword(token); printf((%d, %s)\n, code -1 ? ID_CODE : code, token); tokenLen 0; state ST_START; // 把当前字符重新交给 ST_START 处理 processChar(ch, line, col); } } }这里提到的 ID_CODE 是标识符的固定类别码比如 20。递归调用 processChar 是为了“重新处理当前字符”递归层级不会深因为每个分支最多重新处理一次。3.3 数字常数识别与数字后跟字母的边界数字态的收集规则是连续吃数字直到遇到第一个非数字字符。碰到运算符或空白就正常结束并输出整数常数二元式如果碰到字母按实验常见要求报“非法字符”。if (state ST_NUM) { if (ch 0 ch 9) { token[tokenLen] ch; } else if (isAlphaNum(ch)) { printf(第%d行第%d列: 非法字符 %c 跟随在数字后\n, line, col, ch); tokenLen 0; state ST_START; } else { token[tokenLen] \0; printf((%d, %s)\n, NUM_CODE, token); tokenLen 0; state ST_START; processChar(ch, line, col); } }注意这里的 isAlphaNum 已经包含字母和数字。数字后跟字母的测例很多教材里不强制要求报错但老师给的样板输出里可能就藏着这一条。我建议保留这个分支它不会影响正常代码的识别。正常识别路径到这里闭环了真正的难点在下一章的三类错误检测。4. 三类词法错误检测时机、位置与错误恢复策略错误检测比正常识别难在没有直观输出可对照。错误发生后处理策略错了还会污染后续所有单词的识别。这一章把三类错误的分支逐个拆开。4.1 非法字符先判断状态再过滤非法字符的定义很直接不在 SAMPLE 字符集里的符号。但过滤时机放状态机之前还是状态机内部效果差很远。放在状态机之前的问题有些字符在特定状态下是合法定界符比如单引号在 ST_START 下是字符常数的开头如果先被过滤了就会打断状态。所以正确顺序是先看当前状态如果是 ST_START 且不在合法字符集才报非法字符其他状态内遇到的字符由当前状态自行决定是否结束当前词。if (state ST_START) { if (isLegalChar(ch)) { // 按首字符类型进入相应状态 } else { printf(第%d行第%d列: 非法字符 %c\n, line, col, ch); // 跳过当前字符不改变状态 } }错误恢复策略是“跳过当前字符继续扫描”。不要因为一个非法字符就让整个程序退出否则老师给的错误测试用例只会显示第一个错误后面全被截断。4.2 字符常数缺右单引号字符常数的合法结构是单引号 一个字符 单引号。扫描进入 ST_CHAR 状态后如果一直没等到右单引号先看是不是换行或 EOF。因为题目明确要求字符常数不能跨行所以在 ST_CHAR 里看到换行就是缺右单引号的错误现场。if (state ST_CHAR) { if (ch \) { token[tokenLen] \0; printf((%d, %s)\n, CHAR_CODE, token); tokenLen 0; state ST_START; } else if (ch \n || ch EOF) { printf(第%d行第%d列: 字符常数缺右边的单引号\n, charStartLine, charStartCol); tokenLen 0; state ST_START; // 换行后的内容交给主循环正常处理 } else { if (tokenLen 255) token[tokenLen] ch; } }charStartLine 和 charStartCol 是在进入 ST_CHAR 时记录的位置。报错位置用起始行而不是发现错误那一行因为结构缺陷是从左单引号开始就存在了老师校对样板输出时通常按左单引号位置来算。注意这里不用把换行符再放回状态机重新处理因为换行在 ST_START 里也按空白丢弃。如果实验要求字符常数内允许转义序列比如 表示单引号本身就得在进入 ST_CHAR 时多加一个转义判断分支。4.3 注释缺右侧界符 */注释的合法结构是 /* 开头*/ 结束不能跨行。在 ST_COMMENT 状态下读到 * 还要看下一个字符是不是 /不是就继续吃是则结束注释回到 ST_START。这个“预读一个字符”是隐藏难点。if (state ST_COMMENT) { if (ch * peekChar() /) { consumeChar(); // 把预读的那个 / 消费掉 state ST_START; tokenLen 0; } else if (ch \n || ch EOF) { printf(第%d行第%d列: 注释缺右边的界符*/\n, commentStartLine, commentStartCol); state ST_START; tokenLen 0; } // 其余字符全部忽略不生成二元式 }peekChar 和 consumeChar 的实现依赖文件指针读操作。我习惯用一个全局变量 lookahead 存放“已经读入但还没处理”的字符状态机每次取字符都先检查这个变量。好处是不用调 ungetc跟踪起来更直观。需要小心的是ST_COMMENT 内读到换行就报错是因为题目限定注释不跨行。如果你的测试文件里真的有跨行注释这个实现会误报。但实验要求明确写了“不能跨行”就按题目来不用为了兼容通用 C 语法把边界放宽。4.4 EOF 时刻的遗漏检查三类错误里最容易漏的是注释和字符常数缺右界符而文件恰好在此结束。扫描循环到最后状态机可能还停在 ST_CHAR 或 ST_COMMENT必须补一次检查。void checkUnclosedState() { if (state ST_CHAR) { printf(第%d行第%d列: 字符常数缺右边的单引号\n, charStartLine, charStartCol); } if (state ST_COMMENT) { printf(第%d行第%d列: 注释缺右边的界符*/\n, commentStartLine, commentStartCol); } }EOF 时想清楚一件事fgetc 返回 EOF 后再 peek 是拿不到后续内容的。所以 checkUnclosedState 里不要再尝试读文件只看当前状态变量就够了。这比在循环里做分支判断更清晰。错误分支和主循环全部对上之后接下来是实践里最容易翻车的细节。5. 词法分析器排查五类实测翻车与修复记录写这类实验源码真正花时间的不是理解自动机而是处理各种“看起来不该错却偏错”的边界。下面五条是反复踩过的坑按现象、原因、解决三层记录。5.1 行号错位错误信息指错位置现象报错说第 8 行第 2 列有非法字符但打开源文件第 8 行根本没有特殊符号反倒是第 9 行有问题。原因line 的更新写在主循环末尾但状态机在某个状态内部已经把下一行字符读进来处理了。比如 ST_COMMENT 分支在读到换行后直接报错却没有把 line 的通知传给主循环。状态机自行输出行列时和主循环的自增就对不上。解决把所有行列维护全部收进同一个取字符函数。主循环不再单独更新 line 和 col每次执行 processChar 前先由 getNextChar() 完成自增。这样状态机报错时用的行列一定是当前字符的真实位置。5.2 关键字全被识别成标识符现象int sum 0 输出出来是 (20, int)而期望的是关键字 int 的独立类别码。原因查表前没有给 token 做字符串结束处理或者 token 里残留了上一个单词的字符。strcmp 比较时会继续往后读结果永远匹配不上。解决收集完 token 后立刻写 token[tokenLen] \0再调 lookupKeyword。另外检查 keywords 数组里是否有重复项或者大小写不匹配导致 if 和 IF 被当成同一个单词。5.3 所有运算符都少了一个字符现象输入 复合运算符输出却是 (40, ) 和 (40, ) 两行期望是一行 (45, )。原因状态机在 ST_OP 里看到一个运算符就立即结束并输出没有“再读一个字符看看能不能组成复合运算符”的逻辑。fgetc 已经把第二个字符读完了主循环又把它当作新单词开头处理。解决在 ST_OP 内遇到可能组成复合运算符的字符 - * / !时预读下一个字符能匹配就一起消费不能匹配则把预读字符回退或交给 ST_START 重新处理。预读失败后千万别自己吞掉否则后面字符全部错位。5.4 注释缺右侧界符的测例死活不报错现象测试文件最后一行是未闭合的 /*程序正常退出输出里没有错误信息。原因注释状态在 EOF 时被忽略checkUnclosedState 没写或者写了但条件判断的是 ch EOF 而不是 state ST_COMMENT。通常这两个问题同时存在。解决扫描循环结束后强制检查状态变量。同样适用于字符常数缺右单引号的测例。不要相信“输出为空就说明通过”错误分支必须在 EOF 处显式判定。5.5 字符常数里的转义符导致判定异常现象输入 a 正常但输入 \n 时输出成了两个二元式或者报非法字符。原因常见实现把反斜杠当成普通字符收集后面遇到 \n 中的 n 和右单引号逻辑全乱。解决在 ST_CHAR 状态里加一个 escape 标志。读到反斜杠时置位并直接收集反斜杠和下一个字符不再单独对下一个字符判定。如果实验模板不要求支持转义就保持现状如果老师会追加这类测例这个分支必须提前做。提示字符常数和注释的错误恢复本质都是“丢弃当前残缺结构回到 ST_START 继续”。恢复后能不能正确识别后续单词才是错误处理写得是否合格的试金石。6. 把源码改造成可回归的实验测试集与参数化拿到这份源码我建议第一件事不是看代码而是先编三个测试文件一个全合法代码、一个包含三类错误的混合文件、一个空文件。合法代码验证正常识别路径错误文件验证三个错误分支空文件验证有没有多余的启动输出。测试文件可以做成输入与期望输出分离。给一份最小合法用例int a 1; if (a 0) a a 1;期望输出行数与源文件单词数一致每个二元式格式为类别码, 值。把期望输出保存成同名 .exp 文件再用一段脚本批量 diff。for case in valid mixed missing_quote missing_comment; do ./lexer $case.txt $case.out 21 if diff -q $case.exp $case.out /dev/null; then echo $case: PASS else echo $case: FAIL diff -u $case.exp $case.out fi donediff 的退出状态配合脚本一次能跑完所有预设用例。改一行代码就重跑一次90% 的回归问题能当场暴露。参数化方面我会把源码里散落的类别码替换成 const 常量或枚举enum TokenCode { TC_KEYWORD_INT 1, TC_IDENTIFIER 20, TC_NUMBER 21, TC_OP_ASSIGN 40 };替换的目的是让查表函数和输出函数不再依赖魔数。类别码写死成数字老师临时改编号表你得改十几个地方漏一个就是全错。最后一项习惯跑完 diff 再把一个包含所有运算符、所有关键字、所有错误场景的混合测试文件放进去确认错误恢复后扫描还能继续输出后续单词。别让错误分支把扫描卡死这也是答辩现场经常被追问的点。从那以后我每次做这类实验第一件事都是先建好测试目录和期望输出文件代码改到哪里就跑到哪里比对着控制台肉眼找错快得多。希望这个习惯也能帮到你。本文还有配套的精品资源点击获取

相关新闻

Python logging模块深度解析:从print到生产级日志系统

Python logging模块深度解析:从print到生产级日志系统

1. 日志系统到底在解决什么问题刚入行那会儿,我对日志的理解就是“print大法”——哪里出问题就在哪里加一行打印,调试完再删掉。直到有一次线上服务半夜挂了,我翻遍代码发现所有调试打印都被清理得干干净净,只能靠猜。那次事故之…

2026/10/9 10:41:12 阅读更多 →
终端用户视角下的性能测试:体验与度量的融合实践

终端用户视角下的性能测试:体验与度量的融合实践

1. 为什么终端用户视角的性能测试值得单独拿出来说做性能测试的人,大多经历过这样的场景:压测报告上TPS、响应时间、错误率全部达标,曲线平滑得像教科书,结果上线之后客服电话被打爆,用户抱怨“卡死了”“转圈半天”“…

2026/10/9 10:41:12 阅读更多 →
OpenChatCut occ命令行工具实战:不打开应用,管理、剪辑并渲染全部项目的完整指南

OpenChatCut occ命令行工具实战:不打开应用,管理、剪辑并渲染全部项目的完整指南

OpenChatCut occ命令行工具实战:不打开应用,管理、剪辑并渲染全部项目的完整指南 【免费下载链接】OpenChatCut Open-source, local-first conversational AI video editor with a professional multi-track timeline, Agent Skills, MCP integration, a…

2026/10/9 10:41:12 阅读更多 →

最新新闻

树结构核心术语解析:根、父子兄弟、深度高度与路径的工程意义

树结构核心术语解析:根、父子兄弟、深度高度与路径的工程意义

1. 为什么“树”这个词在计算机里被反复提起,却没人真去种一棵?你打开任何一本算法入门书,翻到第三章,大概率会看到一个分叉的图示:一个圆圈在最上面,下面连着两个圆圈,再往下又分出更多——旁边…

2026/10/9 11:18:10 阅读更多 →
锂电池清洗水枪EMC整改实战:从超标12dB到6dB余量的系统化方案

锂电池清洗水枪EMC整改实战:从超标12dB到6dB余量的系统化方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 11:18:10 阅读更多 →
GCC编译全解析:从预处理到链接的实战指南

GCC编译全解析:从预处理到链接的实战指南

1. 从一行报错说起:为什么值得花时间搞懂gcc很多人第一次接触gcc,不是因为想学它,而是因为被它拦住。编译一个C文件,终端甩出一堆看不懂的英文,什么undefined reference to、implicit declaration of function&#xf…

2026/10/9 11:18:10 阅读更多 →
电机测试数据飘?先查平台再查传感器——机械安装细节全解析

电机测试数据飘?先查平台再查传感器——机械安装细节全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 11:18:10 阅读更多 →
Eclipse导出可执行Jar的原理与三种依赖策略详解

Eclipse导出可执行Jar的原理与三种依赖策略详解

简介:本资源是一份面向Java初学者与中小型项目开发者的Eclipse工程打包实战指南,聚焦解决「如何导出含第三方Jar依赖的可执行Jar文件」这一高频部署痛点。内容基于Eclipse Indigo(3.7)环境,系统讲解Runnable JAR File导…

2026/10/9 11:18:10 阅读更多 →
Codex 额度重置后,开发者如何用 TaoToken 统一管理 API 调用?

Codex 额度重置后,开发者如何用 TaoToken 统一管理 API 调用?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 11:17:09 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →