C++ Qt词法分析器课设:NFA/DFA状态图可视化与完整实现
简介一套面向编译原理课程与期末课设场景的C/Qt词法分析器工程包适合正在学习词法分析、自动机理论与GUI开发的学生参考。工具将源代码拆分为标记token覆盖关键字、标识符、数字、运算符等常见规则并通过Qt界面直接展示分割结果让正规式到状态转换表的对应关系更直观。压缩包共30个文件包含6个cpp与4个h源文件、Qt界面与工程配置ui/qrc/pro、测试代码、文档及图片等其中源文件负责词法分析与界面交互docx/md提供项目说明jpg/png等直观呈现NFA、DFA与最小化DFA状态图整个包约571KB适合按模块查阅。已有188人浏览学习。资源提供了完整的词法分析核心逻辑、可视化界面及配套课设文档可对照自动机最小化等原理快速迁移到自己的课程作业、实验演示或进一步功能扩展中。1. 词法分析器课设项目一份带 Qt 图形界面的 C 完整打包很多人交词法分析器课设是一段控制台代码运行后把 token 打印出来就完事。原理倒是讲得出但状态怎么迁移、NFA 怎么变成 DFA全程黑匣子。这个 zip 包不一样它用 C 配 Qt 把整个流程做成了带窗口的工具输入一段源代码吐出一串 token还能在图形界面里看到 NFA、DFA、最小化 DFA 三张状态图。包里还带着课设文档、测试代码和 README适合两类人一类是编译原理课设还没头绪的学生可以直接拿它的结构改造另一类是自认为懂词法分析、但从没写过完整 DFA 的开发者用它验证自己的理解。下面按核心逻辑、界面层、状态图可视化、排错、验收技巧的顺序把这个包拆开讲。2. 词法分析核心从 lex.cpp 的 token 组织到状态识别2.1 token 类型与 lex.h 的数据结构词法分析器要解决的问题很朴素把源代码字符串切成有意义的片段再给每个片段贴上类型标签。包里 lex.h 干的就是这件事。它的核心是一个 token 类型枚举外加一个带位置信息的 Token 结构。// lex.h 中的关键定义 #ifndef LEX_H #define LEX_H enum TokenType { TOKEN_KEYWORD, // if、else、while、int 等关键字 TOKEN_IDENTIFIER, // 变量名、函数名 TOKEN_NUMBER, // 整数、小数 TOKEN_OPERATOR, // - * / ! 等 TOKEN_DELIMITER, // ; ( ) { } [ ] 等界符 TOKEN_EOF // 文件结束 }; struct Token { TokenType type; QString text; int line; // 所在行号 int column; // 所在列号 }; #endif注意 Token 里带了 line 和 column。这不是可有可无的装饰Qt 界面里定位错误、高亮问题行都要靠它。许多课设代码只输出 token 文本结果真碰到非法字符时完全不知道错在源码哪一行答辩时老师一问就露馅。项目里把位置信息直接放进基础结构说明作者是奔着完整工具去的不是交差了事。关键字识别有个常见技巧先按标识符规则匹配再查关键字表。这样不用为每个关键字单独写一条匹配规则状态机规模能小一大截。包里大概率也是这么做的const QSetQString kKeywords { if, else, while, for, return, int, char, float, void, struct }; // 识别出一个标识符后先查表再定类型 if (kKeywords.contains(text)) { token.type TOKEN_KEYWORD; } else { token.type TOKEN_IDENTIFIER; }这里用QSet的 contains 查询平均 O(1)。关键字表本身很小就算用QStringList::contains也不会有性能问题但课设里养成选对容器的习惯总是好的。2.2 手工状态机的识别循环与最长匹配词法分析最忌讳的是用一堆 if-else 从头到尾比较字符串比如判断是不是关键字就逐个if (text if)。这样做小语言还行一旦运算符多了既难维护又容易漏匹配。标准做法是维护一个状态变量配合状态转移表推进。// 词法分析器主循环状态表驱动 最长匹配 int state 0; int i 0; QString buf; while (i src.length()) { int cls charClass(src[i]); // 把字符归约成字符类如 DIGIT、LETTER、OP int next trans[state][cls]; // 查状态转移表 if (next -1) { if (isAccept[state]) { // 当前状态是接受态说明已经匹配到一个 token pushToken(buf, state); // 用当前状态对应的 token 类型产出结果 buf.clear(); state 0; continue; // 当前字符不消费留到下一轮重新匹配 } reportError(src[i], i); // 死路非法字符跳过 state 0; i; continue; } buf.append(src[i]); state next; i; } if (isAccept[state]) { pushToken(buf, state); // 收尾文件结束时的最后一个 token }这段代码有四个关键点。charClass把字符归约成少数字符类这是整张状态表能写进二位数组的前提。比如所有数字都归为DIGIT所有字母和下划线归为LETTER运算符各自成一类。如果直接拿 ASCII 码做下标表会膨胀成几百列查起来反而不直观。trans[state][cls]是核心查询。它返回下一个状态-1 表示当前状态下遇到这类字符没有合法转移。表的规模通常很小几十个状态乘十几类字符一个二维 vector 就能装下。最长匹配体现在那个continue上。比如识别时读到已经可以结束但下一个字符是状态机还能继续走。代码的处理方式是只有走到死路时才回头用上一个接受态产出 token。这样和不会互相打架。isAccept[state]是一个布尔数组标记哪些状态是接受态。这个数组和状态转移表是配套的改词法规则时两边要一起改。包里 test.cpp 的作用就是验证这套规则匹配的边界情况比如数字后紧跟字母到底该拆成123和abc还是直接报错。2.3 从正则到 NFA 再到 DFA三个 dot 文件暴露的实现路径有些人写词法分析器直接跳到最后一步手写一个 DFA 就开始跑。这个包不一样它保留了nfa.dot、dfa.dot、mindfa.dot三个文件说明实现路径是教科书标准的用正则描述每个 token 的规则通过 Thompson 构造法把正则转成 NFA输出nfa.dot用子集构造法把 NFA 转成 DFA输出dfa.dot对 DFA 做最小化等价状态合并输出mindfa.dot。这也是lexical.cpp存在的意义。它承接 lex.cpp 里的规则定义负责把正则表达式翻译成 NFA 结构。如果你打开源码看到NFAState、EpsilonTransition这类命名就是这个流程没跑了。为什么要费劲转两遍直接手工画 DFA 不是更快因为正则描述规则最直观比如[a-zA-Z_][a-zA-Z0-9_]*一眼就知道是标识符。NFA 是正则在机器里的直接映射状态多但有 epsilon 边DFA 把多个并行路径确定化执行时不再回溯最小化则是把等价状态合并让查表更快。三段各自解决一个问题表达能力、执行效率、存储效率。在这个包里dfa.dot和mindfa.dot很值得做一次对比。同一门小语言的 DFA 和最小化 DFA状态数通常能差 20% 到 40%。如果两个文件状态数一模一样八成是文中的最小化算法没有真正执行或者执行了但有 bug——这点第五章和第六章还会专门讲。3. Qt 界面层mainwindow 事件流与大数据量 token 展示优化3.1 打开文件到分析完成的事件流mainwindow.ui 定义了界面布局mainwindow.cpp 负责把界面操作和分析逻辑接起来。整个工具的使用动线很清晰打开源文件、显示原文、点分析、在表格里看 token。典型实现是一个槽函数搞定打开和分析两个动作void MainWindow::onOpenFile() { QString filePath QFileDialog::getOpenFileName( this, 选择源代码文件, QString(), C/C Source (*.c *.cpp *.h);;All Files (*)); if (filePath.isEmpty()) return; QFile file(filePath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::warning(this, 打开失败, file.errorString()); return; } QTextStream stream(file); stream.setCodec(UTF-8); // 统一按 UTF-8 读避免中文乱码 QString sourceCode stream.readAll(); file.close(); Lexer lexer; QVectorToken tokens lexer.analyze(sourceCode); fillTokenTable(tokens); }注意几个细节。QFileDialog的过滤器限制了文件类型但实际课程设计可能要分析自定义语法所以后面加了All Files (*)兜底。stream.setCodec(UTF-8)在 Qt 5 里是常规操作如果源文件是 GBK 编码这里需要改成GBK或者干脆自动探测编码。lexer.analyze是一次性同步调用对课设规模够用如果以后要分析超大文件就得改成后台线程分块处理避免界面卡死。UI 交互可以加重量的地方是错误定位。词法分析发现非法字符时不要把错误信息只打在日志里而是从 Token 结构里读出 line 和 column用QPlainTextEdit的光标定位到那一行甚至用额外颜色标出问题字符。这个功能不复杂但对答辩加分很有用——它能证明你的位置信息字段不是摆设。3.2 token 列表展示从 QTableWidget 到 QTableView 自定义 Model项目里的mainwindow.ui最直接的实现是用 QTableWidget 展示 token五行代码就能铺满数据课设验收完全够。但有个隐患QTableWidget 是 QTableView 加内置 model 的便捷封装行数多了刷新会卡。如果你用一份几百 KB 的 C 源码做测试token 数量很容易破万QTableWidget 的逐行 setItem 会明显变慢滚动时还会掉帧。这类问题就是 Qt 表格大数据卡顿优化里最典型的一种。我在自己的项目里一般直接上 QTableView 自定义 QAbstractTableModel把数据访问的职责交给 model表格只负责向 model 要数据class TokenTableModel : public QAbstractTableModel { Q_OBJECT QVectorToken tokens; public: int rowCount(const QModelIndex parent QModelIndex()) const override { return parent.isValid() ? 0 : tokens.size(); } int columnCount(const QModelIndex parent QModelIndex()) const override { Q_UNUSED(parent); return 4; // 类别、文本、行号、列号 } QVariant data(const QModelIndex index, int role) const override { if (role ! Qt::DisplayRole) return QVariant(); const Token t tokens.at(index.row()); switch (index.column()) { case 0: return tokenTypeName(t.type); // 返回可读的类型名 case 1: return t.text; case 2: return t.line; case 3: return t.column; } return QVariant(); } };关键点是只重写 model 的 rowCount、columnCount、data 三个虚函数然后把 modelsetModel()给 QTableView。视图滚动时model 按需返回当前可见区域的数据内存占用和绘制开销都远小于 QTableWidget 一次性塞完所有 item。替换之后一万行 token 的滚动体验和几十行几乎没有差别。想更进一步可以给表格加一列“错误信息”只有非法字符所在行的这一列为非空用dataChanged信号触发单元格刷新——这个信号槽机制也是 Qt 程序里最基础也最好用的协作方式。3.3 资源文件 qrc把图片和 dot 收进二进制项目里有两个 qrc 文件dots.qrc和imges.qrc。很多初学者不理解 qrc 的意义以为 Qt 可以直接读相对路径的文件。其实 qrc 是把资源文件编译进可执行程序二进制运行时通过:/前缀访问根本不依赖磁盘路径。这样程序发布后图片和状态文件不会因为工作目录变化而丢失。!-- dots.qrc 的结构示意 -- RCC qresource prefix/dots filenfa.dot/file filedfa.dot/file filemindfa.dot/file /qresource /RCC// 通过 qrc 路径读取 dot 文件内容 QFile file(:/dots/dfa.dot); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qWarning() cannot open dfa.dot from resources; return; } QString content file.readAll();结合前面的事件流程序启动时从资源文件加载三个 dot词法分析完成后按当前分析结果重新生成 dot 文件内容再刷新图形区。这里要注意prefix/dots让资源路径变成:/dots/dfa.dot如果文件放在 qrc 所在目录的下一层路径里要带上相对目录名。常见翻车点是把 qrc 路径写错编译不报错运行时打开文件永远失败图形区空白一片——第五章会具体展开。4. 状态图可视化mygraph.cpp 如何把 NFA/DFA/minDFA 画出来4.1 为什么词法分析器要留三张状态图很多课设做到 DFA 最小化就停了觉得后面的工作只是实现细节。实际上看图比看代码更容易发现问题。三张图分别对应三个阶段的产物加上比较关系正好是答辩时讲设计思路的天然素材。文件对应阶段状态数特征直观作用nfa.dot正则转 NFA多含 epsilon 边看正则到自动机的映射关系dfa.dot子集构造法比 NFA 少无 epsilon 边看状态确定化结果mindfa.dotDFA 最小化通常更少看等价状态合并效果NFA 状态多、分叉多DFA 把相同的前缀路径合并minDFA 再去掉不可区分状态。对我自己来说最值的不是看懂每一步而是对比 dfa 和 mindfa如果两者状态数差得离谱说明算法写错了如果一模一样要确认最小化是不是真的执行过。这个自查思路在最后一章还会再提。4.2 QGraphicsScene 版本与调用 dot.exe 版本怎么选mygraph.cpp 如果直接调 Graphviz 的 dot.exe 子进程再把生成的 png 塞进 QLabel实现最快。但代价是目标机器必须装 Graphviz还要处理临时文件路径。课设演示用的机器往往不是你自己的开发机现场缺依赖就是翻车现场。所以在 Qt 课设里常见做法是自己解析 dot 文本直接用 QGraphicsScene 手动画节点和边不依赖任何外部程序// mygraph.cpp 中基于 QGraphicsScene 的绘图骨架 QGraphicsScene* scene new QGraphicsScene(this); for (const DotNode node : nodes) { // 普通状态画单圈接受态画双圈 QGraphicsEllipseItem* outer scene-addEllipse( node.x, node.y, 50, 30, QPen(Qt::black), QBrush(Qt::white)); if (node.isAccept) { // 接受态再画一个内圈形成双圈效果 scene-addEllipse(node.x 5, node.y 5, 40, 20, QPen(Qt::black), QBrush(Qt::white)); } QGraphicsSimpleTextItem* label scene-addSimpleText(node.name); label-setPos(node.x 10, node.y 5); } for (const DotEdge edge : edges) { // 状态之间画有向箭头边上标注转移字符 QGraphicsLineItem* line scene-addLine( edge.x1, edge.y1, edge.x2, edge.y2); // 箭头和 label 的位置做二次调整避免线压字 }解析 dot 的原理不复杂逐行读文本发现X - Y的 pattern 就当边处理发现node [shape...]就当节点处理。布局算法反而是最麻烦的部分。Graphviz 用的层次布局算法不是几十行能讲清的课设里一般用固定网格摆放节点或者按边的拓扑顺序排层。这个包的 mygraph.cpp 如果只做了基础布局不用担心效果完全够用。4.3 dot 文件怎么读节点、边、接受态一眼定位阅读理解 dot 是调试可视化工具的基本功。一个迷你 NFA 的 dot 内容大致长这样digraph nfa { rankdirLR; node [shape circle]; q0 [shape start]; q0 - q1 [labeld]; q1 - q2 [label]; q2 [shape doublecircle]; }q0 [shape start]是开始状态q2 [shape doublecircle]是接受状态箭头上的 label 是触发转移的字符。看到这个文件你就能在脑子里还原出自动机从 q0 读一个数字到 q1再读一个加号到 q2q2 结束。如果 label 写的是字符集比如[d]说明这一步是把数字归为一类。整个项目里最有答辩价值的就是把nfa.dot、dfa.dot、mindfa.dot三张图依次展示讲清楚每一步状态数怎么变化。这比贴十倍代码量都管用因为图形能让人直接理解算法做了什么。mygraph.cpp 的作用就是把这三张文本描述变成窗口里可以缩放查看的图形。5. 避坑排查QtC 词法分析器课设最容易翻车的四类问题5.1 Qt 版本与编译工具链不匹配现象用 Qt Creator 打开.pro文件编译报一堆找不到头文件的错误比如QWidget: No such file or directory或者连接阶段出现无法解析的 Q_OBJECT 相关符号。原因Qt 5 和 Qt 6 的模块划分差异很大不少旧项目按 Qt 5 API 写的代码在 Qt 6 里不再兼容。常见比如QRegExp被移除、QTextCodec挪到了 core5compat 模块、部分字符串转换函数签名变了。解决课设项目不追新装 Qt 5.14.2 或 5.15 LTS 就好。安装时选好组件MinGW 版本要和编译器一致。如果你用 CLion它走 CMake需要额外配置CMAKE_PREFIX_PATH指向 Qt 安装目录用 Qt Creator 则直接开.pro文件最省事。这个包同时带.pro和 CMake 相关文件就别在 Qt Creator 里强行用 CMake 构建了用哪个构建系统就选哪条路。5.2 中文注释乱码与QString::fromLocal8Bit现象界面按钮正常显示中文但读入 C 源码后注释里的中文全部变成了乱码或者反过来源代码里中文正常界面上的中文变成问号。原因源文件是 GBK 编码而代码按 UTF-8 处理字符串或 Qt Creator 编辑器按 UTF-8 保存了源码但编译器按系统区域设置去读。Qt 在不同平台上对const char*到QString的隐式转换有一套默认编码规则这个规则在不同 Qt 版本里并不完全一致。解决从两端收口。编辑器文件统一用 UTF-8 保存并在读取文件时显式指定编码QTextStream stream(file); stream.setCodec(UTF-8); // 读文件强制定 UTF-8 // 如果源文件是 GBK改成下面这样 // stream.setCodec(GBK);中文界面上凡是自己代码里写的字面量字符串直接用QStringLiteral(分析完成)包起来避免走一次隐式编码转换。那次转换就是乱码玄学的主要来源。5.3 构建系统混用.pro 与 CMake 两套引擎打架现象在 CLion 里改完代码再点运行发现程序还是旧行为或者 Qt Creator 里用.pro构建通过但 CLion 里打开项目后 CMake 配置一堆报错。原因这个包根目录有.pro又有 CMake 相关目录和 clion-log.txt说明源码工程既支持 qmake 也碰过 CMake。两套构建系统各自维护自己的中间产物Qt Creator 用的是 qmake 生成的 MakefileCLion 用的是 CMake 生成的构建目录改动不会互相同步。解决选定一个构建系统另一个的构建缓存整体无视。如果长期用 CLion就在 CLion 里重新跑一次 CMake 配置不要手动去碰 CMakeFiles 里的生成文件稳定下来后只保留一套构建目录。CLion 里编译 Qt 项目如果报CMAKE_PREFIX_PATH找不到 Qt在 CMakeLists.txt 里显式指定一行set(CMAKE_PREFIX_PATH C:/Qt/Qt5.14.2/5.14.2/mingw73_64)就能绕过去。5.4 mygraph 图形区空白但词法分析结果正常现象token 表格有数据点“显示状态图”图形区域一片空白控制台还提示打开:/dots/dfa.dot失败。原因dot 文件没有写进dots.qrc或者 qrc 里路径写错也可能是代码直接按磁盘相对路径去找 dot 文件程序工作目录不在预期位置。qrc 编译期不校验文件是否存在路径错了编译照常通过运行时才炸排查全靠看运行日志。解决先从程序工作目录和二进制资源路径两个方向分别确认。看代码里读取 dot 用的前缀是:/还是纯相对路径如果是相对路径把输出目录里的 dot 文件找到看名字是否和代码一致。推荐直接改成 qrc 读取把三个 dot 文件在dots.qrc里登记好运行时用QFile(:/dots/dfa.dot)不依赖外部文件。5.5 换电脑运行直接崩溃或闪退现象自己开发机上跑得好好的把生成的 exe 拷到另一台电脑双击没反应或者弹出缺少 DLL 的提示。原因Qt 程序不是静态单文件运行时依赖 Qt 的 DLL 和编译器运行时库。MinGW 编译的还需要libgcc_s_seh-1.dll、libstdc-6.dll、libwinpthread-1.dllMSVC 编译的则需要 VC 运行库。很多人只拷了 exe 就以为能跑。解决把开发机上的 windeployqt 用起来cd build目录 C:/Qt/Qt5.14.2/5.14.2/mingw73_64/bin/windeployqt.exe 你的程序名.exe它会自动收集 Qt 相关 DLL 到 exe 同目录连同整个文件夹一起拷走。MinGW 的三个运行时 DLL 如果缺失手动从编译器的 bin 目录复制到 exe 目录。好的做法是做完这一步之后先找一台干净的虚拟机做一次空跑确认没问题再交。我之前就因为只 deploy 不验证答辩现场换电脑直接闪退得亏提前准备了备用方案才没出事。6. 进阶验收技巧用 dot 文件反查最小化算法有没有做对状态图可视化不只是给人看的还可以当自动化验证工具用。正常流程下NFA 和 DFA 的规模关系有明确规律NFA 因为存在子集并行状态通常比 DFA 多DFA 最小化之后状态数只可能减少或持平绝不可能增多。这个性质可以写一个小脚本自动判断最小化环节有没有翻车。比如把三个 dot 文件放在同一个目录下用下面的 Python 脚本统计状态数和边数import re from pathlib import Path for name in [nfa.dot, dfa.dot, mindfa.dot]: text Path(name).read_text(encodingutf-8) # 匹配形如 q0 [shapecircle] 的节点定义 nodes set(re.findall(r(q\d)\s*\[, text)) # 匹配边定义形如 q0 - q1 edges re.findall(r--|-, text) # 统计接受态数量 accept_states re.findall(r(q\d)\s*\[shape\s*\s*doublecircle\], text) print(f{name}: nodes{len(nodes)}, edges{len(edges)}, faccept_states{len(accept_states)})判断标准如果mindfa.dot的节点数大于dfa.dot说明最小化算法有 bug大概率在划分等价状态时把不该拆的状态拆开了如果两者节点数完全相等一种可能是你的语言本来就没有等价状态可合并另一种是最小化函数根本没有被调用后者的典型特征是mindfa.dot和dfa.dot的文件内容完全一致如果 NFA 节点数和 DFA 节点数相同要回头检查子集构造法有没有把 NFA 的 epsilon 闭包处理干净最常见的坑是漏算 epsilon 闭包导致状态分裂。这个脚本跑完你就能在答辩材料里写清楚“本设计经过 NFA 构造、子集构造、DFA 最小化三阶段过程产物的状态数分别为 X、Y、Z满足|NFA| |DFA| |minDFA|”。比口头说“我做了最小化”有说服力得多。还可以顺手把 dot 文件渲染成图片作为论文或文档插图dot -Tpng dfa.dot -o dfa.png dot -Tpng mindfa.dot -o mindfa.png如果本机装了 Graphviz这一步是白送的没装也没关系现有包里已经有 dfa.jpg、nfa.jpg、mindfa.jpg 三张现成图可以直接用来对比。我当初做词法分析器课设时最初版本没有任何可视化输出代码能跑但答辩时讲不清状态怎么迁移被问住两次。后来重新整理每完成一个阶段就导出 dot 文件再写脚本验证状态数变化学习效果反而比闷头调代码好得多。从那以后我每次经手自动机相关项目都强制走一遍“正则 → NFA → DFA → minDFA → 状态数对比”这一条完整链路不完成对比就不算收工。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Python神经网络赛车游戏实战:从零搭建到训练避坑

Python神经网络赛车游戏实战:从零搭建到训练避坑

简介:这份资源面向神经网络与强化学习入门者,以及希望用Python动手实践AI控制游戏的开发者,核心是用两种方式实现神经网络操纵赛车游戏:一是基于TensorFlow框架搭建训练模型,二是不依赖框架、从零手写DNN,帮…

2026/10/10 14:31:25 阅读更多 →
基于Python的虚假新闻检测多模态识别:源代码与文档说明

基于Python的虚假新闻检测多模态识别:源代码与文档说明

简介:这份资源面向计算机相关专业的本科生与研究生,提供一套基于Python的虚假新闻检测多模态识别完整项目源码,可用于毕业设计、期末大作业或课程设计场景,帮助解决多模态特征融合与虚假新闻分类的实践难题。压缩包共39个文件&…

2026/10/10 14:31:25 阅读更多 →
Python金融大数据风控建模实战:机器学习评分卡与树模型全流程

Python金融大数据风控建模实战:机器学习评分卡与树模型全流程

简介:这份资源面向金融风控方向的学生与开发者,提供一套基于机器学习的Python大数据风控建模完整项目,可直接用于毕业设计、期末大作业或课程设计。项目围绕信贷违约预测等典型风控场景展开,涵盖数据清洗、特征工程、模型训练与评…

2026/10/10 14:31:25 阅读更多 →

最新新闻

Java八种基本类型全解析:从内存布局到线上避坑实战

Java八种基本类型全解析:从内存布局到线上避坑实战

Java的八种基本类型,这个话题放在互联网上一搜一大把,但相信我,很多人在第一年学完就忘得干干净净。我自己带过几个人,面试时问int占几个字节,有人能回答上来,再问int的上限是多少、为什么负数下限比正数上…

2026/10/10 20:55:38 阅读更多 →
给AI对话助手外挂长期记忆:claude-mem架构与实战

给AI对话助手外挂长期记忆:claude-mem架构与实战

claude-mem 这名字起得相当直白——mem 就是 memory,把这个小工具和主流通用对话助手(下文就统一叫“模型助手”吧)放在一起,它的定位立刻清晰:给没有长期记忆的对话系统补上一块“外挂记忆”。我自己长期重度使用这类…

2026/10/10 20:55:38 阅读更多 →
微信点餐小程序毕设:SSM+MySQL全栈实战指南

微信点餐小程序毕设:SSM+MySQL全栈实战指南

简介:这是一套面向计算机专业本科生的微信点餐小程序毕业设计全栈开发资源,适用于课程设计、毕设选题与Java小程序技术栈综合实践。项目采用微信小程序前端(WXML/WXSS/JS) SSM(SpringSpringMVCMyBatis)后端…

2026/10/10 20:55:38 阅读更多 →
AnyPS5技术解析:PS5硬件约束下的跨运行时抽象实践

AnyPS5技术解析:PS5硬件约束下的跨运行时抽象实践

项目标题:“AnyPS5”这个名称本身带有强烈的指向性与模糊性并存的特征——它既像一个技术代号,又像一句口号;既暗示兼容性、泛用性(“Any”),又锚定在特定硬件生态(“PS5”)。但必须…

2026/10/10 20:55:38 阅读更多 →
Java Web动漫之家系统实战:从设计到部署避坑指南

Java Web动漫之家系统实战:从设计到部署避坑指南

简介:Java动漫之家系统设计与实现是一套面向动漫爱好者在线互动平台的完整开发设计方案,适用于JavaWeb课程设计、毕业设计或快速搭建动漫资源社区的项目预研。该方案以SSM框架为核心,结合MySQL数据存储与HTML5前端交互,从系统背景…

2026/10/10 20:55:38 阅读更多 →
免费开源 vs 截图 API 月入 2000 美金:独立开发的两条变现路线

免费开源 vs 截图 API 月入 2000 美金:独立开发的两条变现路线

免费开源 vs 截图 API 月入 2000 美金:独立开发的两条变现路线 【免费下载链接】tendedero Screenshots, hung out to dry. A tiny native macOS app that hangs every screenshot on a line at the top of your screen. 项目地址: https://gitcode.com/gh_mirror…

2026/10/10 20:54:37 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

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/10 11:14:25 阅读更多 →
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/10 1:36:08 阅读更多 →
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/10 11:14:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/10 5:23:50 阅读更多 →
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/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练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/10 10:38:42 阅读更多 →