手写C++递归下降语法分析器:326行实现AST构建与调试
简介本资源是一份面向高校计算机专业本科生的编译原理课程实践材料聚焦语法分析核心环节提供基于递归下降子程序法的C完整实现方案帮助学习者将文法理论转化为可运行、可评测的分析器代码。压缩包共2个文件17KB含1份详细说明文档.doc阐述实验要求、输入输出规范及语法成分输出格式以及1个已通过CG实验平台满分评测的C源码文件.cpp涵盖词法单元衔接、预读处理、多层语法结构识别等关键逻辑。目前已有6107人学习下载适用于课程实验复现、期末备考、编译器开发入门及自动评测环境适配参考。读者可直接编译运行支持以testfile.txt为输入、自动生成output.txt严格遵循教学文法定义输出单词流与语法成分标记如常量说明具备清晰的模块划分与工程可用性。1. 一个能跑通的语法分析器输入ab*c输出 AST 树结构不是画饼是真能编译、真能调试、真能改规则的 C 实战项目你是不是也经历过教材讲 LL(1) 表驱动、递归下降、FIRST/FOLLOW 集推导头都大了但一到写代码——空有文法却卡在“怎么把E → E T | T变成可执行的 C 类”这个项目就是为这种时刻准备的它不讲抽象理论而是用 326 行核心 C 代码不含注释和空行实现了一个完整、可单步调试、支持错误恢复的递归下降语法分析器。输入是标准 C 风格的算术表达式如a b * (c - d)输出是带节点类型、值、子节点指针的 AST抽象语法树还能打印缩进结构图。它面向的是正在做编译原理课程设计、想亲手把文法落地为可运行模块的 C 初学者也适合需要快速验证新文法规则、或给词法分析器接上“大脑”的嵌入式/工具链开发者。项目无第三方依赖仅需 g 7.5 或 ClangWindows/Linux/macOS 全平台可编译所有源码在一个.cpp文件里连main()都给你写好了——不是框架模板是已经跑通的最小可行系统。2. 项目结构与技术选型为什么只用纯 C、不引入 Boost/Spirit、也不生成 parser 表这个项目刻意回避了 Yacc/Bison、ANTLR 等生成器也拒绝使用 Boost.Spirit 这类重型模板库。原因很实际课程实验要求你亲手写分析逻辑而不是调用parse_expression()就完事而生产环境里轻量级嵌入式解析器往往要避免 STL 容器动态分配、规避异常机制、控制栈深度——本项目全部满足。它采用手写递归下降Recursive Descent 手动 FIRST 集引导的设计所有非终结符对应一个 C 成员函数如parseExpression()、parseTerm()每个函数内部通过lookahead向前看一个 token决定走哪条产生式分支。没有状态机表没有宏展开黑魔法只有清晰的 if-else 和函数调用栈。整个工程就 3 个文件syntax_analyzer/ ├── main.cpp # 主入口读取 stdin / 文件调用 parser打印 AST ├── parser.h # Parser 类声明含 Token 类型定义、AST 节点基类、Parser 接口 └── parser.cpp # 核心实现所有 parseXXX() 函数、错误处理、AST 构建逻辑提示parser.h中Token结构体只含type枚举和valuestd::string不存位置信息——课程实验通常不考核错误定位精度但若你需要加行号列号只需在Token里增两个int字段并在词法分析阶段填充后续 parser 完全无需修改。2.1 Token 设计为什么用枚举 string而不是 enum class variantToken的定义长这样节选自parser.henum TokenType { TOK_EOF, TOK_IDENTIFIER, TOK_NUMBER, TOK_PLUS, // TOK_MINUS, // - TOK_STAR, // * TOK_SLASH, // / TOK_LPAREN, // ( TOK_RPAREN, // ) TOK_SEMICOLON, // ; TOK_ERROR }; struct Token { TokenType type; std::string value; // 存 identifier 名或 number 字面量 // 注意此处未包含 pos/line/column —— 简化模型聚焦语法逻辑 };为什么不直接用std::variantstd::string, int, char因为课程实验中value永远是字符串形式变量名a是a数字123是123运算符是。统一用std::string避免模板膨胀降低调试复杂度。更重要的是——你在 GDB 里p token.value就能直接看到内容不用std::getstd::string(token.value)绕一圈。这是血泪经验当 parser 卡死在第 47 行时少一层解包就多一分生还希望。2.2 AST 节点设计为什么用基类指针 工厂函数而不是 std::any 或 void*AST 节点采用经典多态设计// parser.h class ASTNode { public: virtual ~ASTNode() default; virtual void print(int indent 0) const 0; }; class BinaryOpNode : public ASTNode { public: TokenType op; std::unique_ptrASTNode left; std::unique_ptrASTNode right; BinaryOpNode(TokenType o, std::unique_ptrASTNode l, std::unique_ptrASTNode r) : op(o), left(std::move(l)), right(std::move(r)) {} void print(int indent) const override; }; class IdentifierNode : public ASTNode { public: std::string name; IdentifierNode(const std::string n) : name(n) {} void print(int indent) const override; };关键点在于所有子节点用std::unique_ptrASTNode持有而非裸指针或std::shared_ptr。原因有三所有权明确父节点完全拥有子节点无需引用计数开销自动内存管理析构时递归释放杜绝内存泄漏课程实验最怕 valgrind 报 leak移动语义友好parseTerm()返回std::unique_ptrASTNode可直接 move 给BinaryOpNode成员零拷贝。你可能会问“为什么不用std::any存不同节点”——因为std::any在运行时才做类型擦除print()调用必须std::any_cast既慢又易崩而虚函数表在编译期绑定GDB 里p *node就能看清具体类型调试体验天壤之别。2.3 Parser 类核心接口四个函数撑起整棵语法树Parser类只暴露 4 个公有函数极简但完备// parser.h class Parser { private: std::vectorToken tokens; size_t pos 0; Token lookahead() const { return (pos tokens.size()) ? tokens[pos] : Token{TOK_EOF, }; } void consume() { if (pos tokens.size()) pos; } public: explicit Parser(const std::vectorToken tks) : tokens(tks) {} std::unique_ptrASTNode parse(); // 入口解析整个输入 std::unique_ptrASTNode parseExpression(); // E → E T | E - T | T std::unique_ptrASTNode parseTerm(); // T → T * F | T / F | F std::unique_ptrASTNode parseFactor(); // F → ( E ) | identifier | number };注意parse()是顶层函数它只调用parseExpression()并确保消费到TOK_EOF而parseExpression()内部用左递归消除技巧实现先 parse 一个T再循环检查是否为或-若是则构造BinaryOpNode并继续 parse 下一个T。这不是教科书伪码是真实可单步的 C 控制流// parser.cpp std::unique_ptrASTNode Parser::parseExpression() { auto left parseTerm(); // 先拿一个 term while (lookahead().type TOK_PLUS || lookahead().type TOK_MINUS) { auto op lookahead(); consume(); // 吃掉 或 - auto right parseTerm(); // 再拿下一个 term left std::make_uniqueBinaryOpNode(op.type, std::move(left), std::move(right)); } return left; }这段代码直接对应文法E → T ( ( | -) T )*没有栈、没有回溯、没有全局变量——就是干净的 while 循环。你把它粘进 VS Code打断点在consume()上看着left和right如何一步步组装出(a b) * c的树形结构语法分析就不再玄学。3. 编译与运行从空目录到 AST 可视化三步走完项目不依赖 CMake但提供Makefile支持一键构建同时也兼容直接 g 命令。无论你用什么环境核心目标只有一个让./analyzer跑起来并正确解析a b * c。3.1 环境准备确认编译器版本绕过 C17 特性陷阱首先确认你的 g 版本 ≥ 7.5Ubuntu 18.04 默认 7.5macOS Homebrew 安装gcc11即可g --version # 输出应类似g (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0注意本项目使用std::optionalC17但不使用std::string_view或if constexpr。如果你的编译器太老如 CentOS 7 默认 g 4.8请手动将std::optionalToken替换为Token加一个bool has_token标志位——我当年在某高校机房就干过这事改 3 行就通。3.2 构建方式Makefile 与手敲命令双路径项目根目录下Makefile内容极简CXX g CXXFLAGS -stdc17 -O0 -g TARGET analyzer SOURCES main.cpp parser.cpp $(TARGET): $(SOURCES) $(CXX) $(CXXFLAGS) -o $ $^ clean: rm -f $(TARGET) .PHONY: clean执行make # 输出g -stdc17 -O0 -g -o analyzer main.cpp parser.cpp或者不用 make直接g -stdc17 -O0 -g main.cpp parser.cpp -o analyzer-O0关键关掉优化否则 GDB 里变量显示错乱-g必须带调试符号才能单步看 AST 构建过程。3.3 运行与输入三种输入模式覆盖课程实验全部场景编译成功后./analyzer支持三种输入方式模式命令说明交互式./analyzer启动后直接输入表达式回车即解析输入quit退出文件输入echo a b * c./analyzer重定向文件./analyzer test.expr从文件读取test.expr每行一个表达式我们来跑第一个例子$ ./analyzer a b * c AST: BinaryOp() ├── Identifier(a) └── BinaryOp(*) ├── Identifier(b) └── Identifier(c) 看到这个缩进树了吗它证明*的优先级高于parseTerm()确实先于parseExpression()捕获了b * c子树——语法分析器没按“从左到右”线性执行而是按文法分层深入这就是递归下降的本质。提示main.cpp中printAST()函数用递归 缩进实现可视化不依赖任何图形库。如果你想导出 JSON 格式供前端渲染只需重写ASTNode::print()为toJSON()返回std::string5 分钟就能对接 Web IDE。4. 核心代码逐行拆解从parseExpression()到 AST 构建的完整链路现在我们沉到底层把parseExpression()函数一行行掰开看它如何把字符串变成内存里的树。4.1parseExpression()左递归消除的 C 实现回顾代码std::unique_ptrASTNode Parser::parseExpression() { auto left parseTerm(); // [1] while (lookahead().type TOK_PLUS || lookahead().type TOK_MINUS) { // [2] auto op lookahead(); // [3] consume(); // [4] auto right parseTerm(); // [5] left std::make_uniqueBinaryOpNode(op.type, std::move(left), std::move(right)); // [6] } return left; // [7] }逐行解释[1]auto left parseTerm();调用parseTerm()它会进一步调用parseFactor()最终返回IdentifierNode(a)。此时left持有a节点。[2]while (...)检查下一个 token 是否为或-。此时lookahead()返回TOK_PLUS进入循环。[3]auto op lookahead();保存当前token用于后续构造节点。[4]consume();将pos指针前移一位使lookahead()下次指向b。[5]auto right parseTerm();再次调用parseTerm()它会解析b * c整个子表达式因*属于Term层返回一个BinaryOpNode(*)其左右子节点分别是b和c。[6]left std::make_uniqueBinaryOpNode(...)用作为根a为左b*c子树为右构造新节点。注意std::move(left)和std::move(right)转移所有权避免拷贝。[7]return left;返回最终的节点它已完整包含三层结构。这个过程没有栈帧爆炸风险——parseTerm()最多嵌套 2 层b * c而parseExpression()的 while 循环是迭代式展开不是函数递归因此不会触发栈溢出。这是手写递归下降相比纯递归实现的关键优势。4.2parseFactor()括号、标识符、数字的三岔路口parseFactor()是文法中最基础的单元也是错误高发区std::unique_ptrASTNode Parser::parseFactor() { Token tok lookahead(); switch (tok.type) { case TOK_IDENTIFIER: consume(); return std::make_uniqueIdentifierNode(tok.value); case TOK_NUMBER: consume(); return std::make_uniqueNumberNode(tok.value); case TOK_LPAREN: consume(); auto expr parseExpression(); if (lookahead().type ! TOK_RPAREN) { error(expected )); return nullptr; } consume(); // eat ) return expr; default: error(unexpected token in factor: tok.value); return nullptr; } }重点看括号分支consume()吃掉(后立刻调用parseExpression()—— 这意味着括号内可以是任意复杂表达式如(a b) * c解析完表达式后必须校验下一个 token 是)否则报错。这里error()函数只是std::cerr Error: msg \n;不 throw 异常符合嵌入式场景需求若校验失败函数返回nullptr上游parseTerm()需检查返回值避免空指针解引用。提示error()不终止程序而是设一个has_error标志位parse()最终返回nullptr。这种软错误处理让你能继续解析后续表达式适合课程实验中“错一个不全崩”的需求。4.3 AST 打印逻辑缩进树如何生成递归 静态字符串拼接BinaryOpNode::print()实现缩进可视化void BinaryOpNode::print(int indent) const { std::string prefix(indent, ); std::string op_str (op TOK_PLUS) ? : (op TOK_MINUS) ? - : (op TOK_STAR) ? * : /; std::cout prefix BinaryOp( op_str )\n; if (left) left-print(indent 2); if (right) right-print(indent 2); }prefix(indent, )生成缩进空格indent初始为 0每深入一层加 2op_str将枚举转为可读字符避免输出BinaryOp(4)这种玄学数字递归调用left-print(indent 2)和right-print(indent 2)自然形成树形缩进。你可以在 GDB 里打断点在此函数p indent查看当前深度p op_str确认操作符比看内存地址直观十倍。5. 避坑指南5 个真实翻车现场与救命解法写语法分析器最痛苦的不是逻辑而是那些“看起来对、跑起来崩”的细节。以下是我在三个不同课程设计中踩过的坑附带复现方法和修复命令。5.1 现象输入a b正常但a b * c解析出错*被忽略原因parseTerm()内部 while 循环条件写成了lookahead().type TOK_STAR但漏掉了TOK_SLASH导致/被跳过*因未匹配而留在输入流中后续parseExpression()误以为已到结尾。解决检查parseTerm()的 while 条件必须是TOK_STAR || TOK_SLASH。修复后重新编译即可。5.2 现象GDB 调试时left指针显示optimized out无法查看内容原因编译时用了-O2或更高优化等级编译器将std::unique_ptr内联并优化掉符号信息。解决强制使用-O0 -g重新编译g -stdc17 -O0 -g main.cpp parser.cpp -o analyzer。课程实验阶段永远用-O0。5.3 现象输入(a b缺右括号程序直接 segfault原因parseFactor()中检测TOK_RPAREN失败后返回nullptr但parseExpression()未检查expr是否为空直接调用expr-print()。解决在parseFactor()括号分支末尾添加空指针防护if (!expr) return nullptr; // 加这一行 if (lookahead().type ! TOK_RPAREN) { ... }5.4 现象a或a--被识别为identifier但课程要求支持自增运算符原因词法分析器未定义TOK_INC/TOK_DEC类型parser.h中TokenType枚举缺失且parseFactor()未处理作为后缀运算符。解决在TokenType中添加TOK_INC,TOK_DEC修改parseFactor()在TOK_IDENTIFIER分支后增加else if (lookahead().type TOK_INC || lookahead().type TOK_DEC) { auto op lookahead(); consume(); return std::make_uniquePostfixOpNode(tok.value, op.type); // 自定义节点 }5.5 现象Windows 下编译报错error: snprintf was not declared in this scope原因main.cpp中snprintf未包含cstdio而 MSVC 默认不隐式包含。解决在main.cpp顶部添加#include cstdio。Linux GCC 宽松但跨平台必须显式 include。6. 二次开发实战给语法分析器加赋值语句x a b30 分钟搞定课程实验常要求从算术表达式升级到简单语句比如支持x a b * c;。这不需要重写 parser只需在现有骨架上扩展三层词法、语法、AST。6.1 第一步扩展 TokenType 与词法识别5 分钟在parser.h的TokenType枚举末尾加TOK_ASSIGN, // TOK_SEMICOLON // ;然后确保你的词法分析器如果独立存在能识别和;。若你用本项目自带的简易 lexermain.cpp中tokenize()函数找到它并添加else if (c ) { tokens.push_back({TOK_ASSIGN, }); } else if (c ;) { tokens.push_back({TOK_SEMICOLON, ;}); }6.2 第二步改造语法结构新增parseStatement()15 分钟LL(1) 文法需扩展为Statement → Identifier Expression ; Expression → Term ( (|-) Term )* Term → Factor ( (*|/) Factor )* Factor → ( Expression ) | Identifier | Number在Parser类中新增公有函数std::unique_ptrASTNode parseStatement();实现如下std::unique_ptrASTNode Parser::parseStatement() { if (lookahead().type ! TOK_IDENTIFIER) { error(expected identifier before ); return nullptr; } std::string var_name lookahead().value; consume(); if (lookahead().type ! TOK_ASSIGN) { error(expected after identifier); return nullptr; } consume(); auto expr parseExpression(); if (!expr) return nullptr; if (lookahead().type ! TOK_SEMICOLON) { error(expected ; at end of statement); return nullptr; } consume(); return std::make_uniqueAssignNode(var_name, std::move(expr)); }注意AssignNode需新建继承ASTNode含std::string var和std::unique_ptrASTNode value成员。6.3 第三步修改顶层parse()支持多语句10 分钟原parse()只调一次parseExpression()现在要支持语句序列std::unique_ptrASTNode Parser::parse() { auto stmt parseStatement(); if (!stmt) return nullptr; // 支持多个语句xab; yc*d; while (lookahead().type ! TOK_EOF lookahead().type ! TOK_ERROR) { auto next_stmt parseStatement(); if (!next_stmt) break; // 这里可构造 BlockNode 包裹多个 stmt stmt std::make_uniqueBlockNode(std::move(stmt), std::move(next_stmt)); } return stmt; }此时输入x a b * c; y d - e;就能生成嵌套 AST。6.4 验证技巧用 AST 节点计数代替肉眼检查每次改完别急着看打印结果。在main.cpp中加一行统计int count_nodes(const ASTNode* node) { if (!node) return 0; int cnt 1; if (const auto* bin dynamic_castconst BinaryOpNode*(node)) { cnt count_nodes(bin-left.get()) count_nodes(bin-right.get()); } else if (const auto* assign dynamic_castconst AssignNode*(node)) { cnt count_nodes(assign-value.get()); } return cnt; }输入x a b;应返回5Assign Identifier(x) BinaryOp() Identifier(a) Identifier(b)。数字对了结构大概率没错——这是我在某高校助教时教学生的“后悔药”当打印树太深看花眼就数节点。从那以后我每次加新语法都先写count_nodes()测试用例再补print()。宁可多写 10 行验证代码也不愿在 GDB 里追 20 分钟空指针。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

OV9650嵌入式Linux驱动实战:CAMIF+SCCB+DMA全链路解析

OV9650嵌入式Linux驱动实战:CAMIF+SCCB+DMA全链路解析

简介:本资源是一套基于Linux平台的OV9650摄像头驱动及配套测试程序,面向嵌入式Linux开发者、ARM平台(如S3C2410/S3C2440/Exynos4412)初学者与项目实践者,解决ARM架构下V4L2标准摄像头驱动移植与图像采集验证难题。驱动…

2026/10/17 12:11:42 阅读更多 →
Java手写单纯形法实现:轻量级线性规划求解器

Java手写单纯形法实现:轻量级线性规划求解器

简介:本资源是一份面向计算机专业学生与运筹学初学者的Java线性规划算法实现项目,聚焦于运筹学核心优化问题的编程落地,帮助学习者深入理解单纯形法思想、两阶段法原理及标准型转化过程。压缩包共11个文件,含2个核心Java源码&…

2026/10/17 12:11:42 阅读更多 →
Java手写单纯形法实现:线性规划求解器工程实践

Java手写单纯形法实现:线性规划求解器工程实践

简介:本资源是一份面向计算机专业学生与运筹学初学者的Java线性规划算法实现项目,聚焦于运筹学核心优化问题的编程落地,帮助学习者深入理解单纯形法思想、两阶段法原理及标准型转化过程。压缩包共11个文件,含2个核心Java源码&…

2026/10/17 12:11:42 阅读更多 →

最新新闻

ORM选型:MyBatis、MyBatis-Plus与JPA怎么选

ORM选型:MyBatis、MyBatis-Plus与JPA怎么选

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

2026/10/17 13:14:22 阅读更多 →
主动均衡原理与MP2642GR-Z+PIC18F8520工程实现

主动均衡原理与MP2642GR-Z+PIC18F8520工程实现

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

2026/10/17 13:14:22 阅读更多 →
PacketTracer设备接入OneNET云平台:物联网上云的仿真到真实实践

PacketTracer设备接入OneNET云平台:物联网上云的仿真到真实实践

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

2026/10/17 13:14:22 阅读更多 →
基于MP2642GR-Z与PIC18F4455的两节串联电池主动均衡方案设计与实现

基于MP2642GR-Z与PIC18F4455的两节串联电池主动均衡方案设计与实现

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

2026/10/17 13:14:22 阅读更多 →
claude code常用指令速查:从slash命令到CLI flags的TaoToken实战手册

claude code常用指令速查:从slash命令到CLI flags的TaoToken实战手册

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

2026/10/17 13:14:22 阅读更多 →
Visual Studio Debug/Release 自动切换库路径与DLL拷贝方案

Visual Studio Debug/Release 自动切换库路径与DLL拷贝方案

1. 这个需求到底在解决什么问题做过Windows平台C开发的人,大概率都遇到过这样一个场景:你写了一个基础库,编译出来两个版本——Debug版和Release版,分别放在Debug/和Release/两个目录下。然后你有一个上层应用工程,开发…

2026/10/17 13:13:21 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →